or = ||
and = &&
xor = | 或者 ^ # 异或,例如Select * from cms_users where userid=1^sleep(5);
not = !
双写绕过
在某一些简单的waf中,会将关键字select等使用replace()函数置换为空。当关键词被过滤时可以采用双写的方式,在经过waf的处理之后又变成select,达到绕过的要求。
and写成anandd
select写成seleselectct
大小写变种:
当关键词被过滤时,可尝试变换大小写进行绕过。
UniOn
SeleCt
对等号=绕过
不加通配符的like执行的效果和 = 一致,所以可以用来绕过。
1. 正常加上通配符的like:
Select * from cms_users where username like "ad%"; 1
2.不加上通配符的like可以用来取代=:
Select * from cms_users where username like "admin"; 1
3.regexp:MySQL中使用 REGEXP 操作符来进行正则表达式匹配
Select * from cms_users where username REGEXP "admin"; 1
4 .使用大小于号来绕过
Select * from cms_users where userid>0 and userid<2; 1
5.<> 等价于 != ,所以在前面再加一个 ! 结果就是等号了
Select * from cms_users where !(username <> "admin");
畸形HTTP请求
当向WEB服务器发送畸形的、非RFC2616标准的HTTP请求时,WEB服务器出于兼容的目的,会尽可能解析HTTP请求。若WEB服务器的兼容方式与WAF不一致,则可能会出现绕过的情况。比如: GET id.php?id=1%20union/**/select这个请求,无请求的协议字段,也没有HOST字段,但Apache对这个请求的处理默认会设置协议为HTTP/0.9,HOST则默认会使用Apache默认的servername;
使用动态查询执行
许多数据库都允许动态执行SQL查询,只需向只需向执行查询的数据库函数传递一个包含SQL查询的字符串即可。如果找到了SQL注入点,但却被过滤器阻止注入,那就可以尝试动态执行进行绕过。
不同的数据库中动态查询执行的实现会有所不同;
在SQL Server中,可以使用exec函数执行一个字符串格式的查询,例如:exec('select * from users');
Oracle可使用execute immediate命令执行一个字符串格式的查询,例如:execute immediate 'select * from users'。
数据库提供了多种操作字符串的方法。想使用动态执行的关键是使用字符串操作函数将过滤器允许的输入转换成一个包含所需要查询的字符串。最简单的情况,可以使用字符串连接技术将较小的部分构造成一个字符串。不同数据库使用不同的语法连接字符串。若select被过滤,可使用(但连接符在http请求中被提交时需进行URL编码)
Oracle:'se'||'lect'
SQL Server:'se'+'lect'
MySQL:'se' 'lect'
也可使用字符串操作函数reverse()、substr()、replace()等。
使用空字节
通常需要绕过的SQL注入漏洞过滤器都是在应用程序自身的代码之外(IDS、WAF),这些组件通常由C++编写,所以我们可以针对这些语言的特性进行绕过,比如可以使用空字节攻击来避开输入过滤器并将漏洞输入至后台应用程序中。
空字节之所以能起作用,是因为原生代码和托管代码分别采用不同的方法来处理空字节。在原生代码中,根据字符串起始位置到出现第一个空字节的位置来确定字符串长度(空字节终止字符串)。而在托管代码中,字符串对象包含一个字符数组和一条单独的字符串长度记录。
这种差异意味着原生过滤器在处理输入时,如果遇到空字节,便会停止处理,因为在过滤器看来,空字节代表字符串的结尾。如果空字节之前的输入是良性的,那么过滤器将不会阻止该输入。不过在托管代码语境中,应用在处理相同的输入时,会将空字节后面的输入一同处理。所以只需要在过滤器阻止的字符前提供一个采用URL编码的空字节(%00)即可。
id=1%00' union select *password from users where username='admin'
二次注入
防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中,当WEB程序调用存储在数据库中的恶意数据并执行SQL查询时,产生二次注入。
二次注入虽然是SQL注入的一种,但挖掘二次注入需要对应用程序有完整的理解,需要知道应用程序的逻辑,所以自动化扫描很难发现,基本靠人工发现。
0x06 测试过程
通过手工或工具进行SQL注入测试,验证系统相关功能页面,查看是否能进行数据查询获取相关敏感数据。
测试案例1
-
系统某链接中的POST参数:hidZWCLFS存在SQL注入漏洞。如下图所示:
2.除上述链接外,其他链接同样存在若干SQL注入漏洞,需要对系统POST参数进行统一过滤,下列给出部分含有SQL注入漏洞的链接。如图所示:
测试案例2
1.使用椰树V1.9-web安全扫描工具 ( 提取码:nn1k)对测试站点进行扫描。将url链接放入工具中,点击扫描网站,并且等状态栏为done时,扫描完成,如下图所示,发现2个注入点。

2.对刚发现的注入点进行注入,选择SQL INJECTION POC。

3.注入成功,可查看用户名、加密过后的密码等数据。


4.使用MD5解密工具进行解密,成功获取用户名、密码。

再用御剑等目录爆破工具,扫描网站后台,使用SQL注入出的用户名密码进行登录。

测试案例3
CVE-2021-35042
1.访问列表视图 http://your-ip:8000/vuln/

2.添加?order=-id到 GET 参数,可看到按 id 按照降序排列的数据。

3.根据以上信息可以构造报错注入进行攻击获取数据信息。
?order=vuln_collection.name);select updatexml(1, concat(0x7e,(select @@version)),1)%23
执行payload后,系统返回数据库版本信息。

4.执行获取用户名、密码的payload,成功利用系统的SQL注入漏洞获取用户名、密码。

0x07 风险分析
攻击者可以通过构造特殊URL的手段,利用SQL注入漏洞:
使得系统业务功能异常或者失效;
恶意的破坏,比如修改数据,删数据,删表等恶意破坏;
探查数据库类型,结构,获取数据库敏感数据,造成数据泄露;
修改数据库配置,控制服务器,进行恶意活动等
在某些情况下能执行操作系统命令
0x08 加固建议
想要更好的防止SQL注入攻击,就必须清楚一个概念:数据库只负责执行SQL语句,根据SQL语句来返回相关数据。数据库并没有什么好的办法直接过滤SQL注入,哪怕是存储过程也不例外,了解此点后,应该明白,防御SQL注入,还是需要从代码入手。
1.对用户输入的数据进行全面安全检查或过滤,采用一些成熟的防注入产品。
服务器可以安装安全狗、360网站卫士等安全工具,数据库中的敏感信息加密后存放,严格控制数据库用户权限。
2.使用预编译语句,绑定变量(最佳方式),这样SQL语句的语义不会发生改变;
3.检查数据类型,限制邮箱、时间、日期等数据的格式;
4.使用安全的存储过程;
5.检查输入数据的数据类型;
6.使用安全函数,推荐OWASP ESAPI项目的安全函数,如:ESAPI.encoder().encoderForSQL(new OracleCodec(),queryparam)。
7.为所有数据库访问使用参数化查询并正确的参数化集成到查询中的每个可变数据项(防御二次注入);