一、背景
参考链接: http://http://www.360doc.com/content/16/1204/19/27425026_611850045.shtml
1.1 MYSQL在遇到/*! SQL语句*/这种格式的时候,里面的SQL语句会当正常的语句一样被解析。
如图:
以上我们可以看到 where id =1;的部分被mysql解析了。
1.2 如果在!之后是一串数字(这串数字就是mysql数据库的版本号),如果当前数据库的版本号大于等于该数字,SQL语句则执行,否则就不执行(链接中的说法),如图:
如上图所示,在mysql新版本中将这条约束归到了开始的规则里面了,因为在更改了!后面的版本号之后,sql语句照样执行
二、示例
参考链接:http://http://www.freebuf.com/articles/web/22041.html
2.1 回到我们的注入点上来看看,我们使用mysql注释+CRLF来进行payload的构造(注意URL编码):
对其URL转义如下(注意转行符的解析):
0 div 1 union#foo*/*bar
select#foo
1,2,current_user
这句sql语句到了Mysql的解析引擎后会再次被解析为:
0 div 1 union select 1,2,current_user
可以看到,注释符之间进行了就近原则的交错组合,Mysql的Sql Parser则选择进行了忽略。
我们知道,ModSecurity使用正则表达式来对Input Sql进行匹配检测,对Select、Union在敏感位置的出现都进行了拦截,但是ModSecurity有一个特点(或者叫做优点),它会对输入进行"规范化",规范化的本意本来是防御"基于编码格式、解析顺序"的绕过的。
2.2 注入Payload
绕过分析:
这里采用了"碎片注入法(分段SQL注入)",或者是我们常说的"Split And Balance原则"。例如:
对于最简单的情况,可以使用字符串连接技术将较小的部分构造成一个字符串。不同的数据库使用不同的语法来构造字符串
oracle: 'selec'||'t'
sqlserver: 'selec'+'';
mysql: 'selec'+'t'
(这就是所谓的split and balance思想)
还要注意的是,加号和空格要先进行URL编码后在发送)
这种技术的好处是可以将原本完整的Payload分成几段,利用ModSecurity对SQL语义的理解不全来进行规则绕过。常常用于进行"二值逻辑"的盲注推理。
回到我们的注入点上来看:
对于Mod来说,我们的攻击Payload为:
hUserId=2276&FromDate=a1%27+or&ToDate=%3C%3Eamount+and%27&sendbutton1=Get+Statement
而对于Mysql的解析引擎来说,它会自动去除、转换这些链接控制符,从而变成:
hUserId=22768&FromDate=a1%27+or&ToData=<>amount and%27&sendbutton1=GetStatement
2.3 注入PayLoad:
这里使用了HPP(HTTP Parameter Pollution)注入技术,关于HPP,有很多资料:
http://www.freebuf.com/articles/web/5908.html
http://hi.baidu.com/aullik5/item/860da508a90709843c42e2ca
http://hi.baidu.com/4b5f5f4b/item/abc28dda72c100f154347f36
https://www.owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf
回到我们的注入PayLoad上来,我们注意到after这个字段出现了3次,其中后2次的出现其实是产生了逗号的作用,以此来绕过。
2.4 注入Payload:
思路分析:
这里采用了"半开注释符(Unterminated Comments)"+"Mysql注释符代码执行(MySQL Comment Extensions for conditional code execution)"技术来进行绕过。半开注释符是利用Mod的replaceComments来进行敏感关键字的绕过。而"Mysql注释符代码执行"则是Mysql的一个运行机制。
Mysql的Parser引擎会自动解析这种格式中的sql代码,同时其他的数据库(例如MSSQL、ORACLE会自动忽略这些注释),也就是说,这是Mysql特有的特性。
防御方法:采用使用多行匹配(MultiMatch Action)+规范化方法(ReplaceComments)
2.5 注入Payload:
注入分析:这里采用了COOKIE注入
防御方法:
关于这个COOKIE注入,我想眼神几点想法:
在注入点的选择中,HTTP中的任何字段、任何位置都"有可能"产生SQL注入,这里只能说有可能,因为是否能否产生注入,和具体的应用系统的环境有关,即应用系统会使用哪些字段带入数据进行执行.
2.6 注入Payload:
http://www.modsecurity.org/testphp.vulnweb.com/artists.php?artist=%40%40new%20union%23sqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapswlmapsqlmap%0Aselect%201,2,database%23sqlmap%0A%28%29
payload分析:
这里采用了"Mysql注释(MySQL Comment)"+"换行绕过(New Line trick)"的组合方法来进行Mod的绕过(本质上是对Mod所使用的正则表达式的绕过)
在Mod看来,我们的PayLoad如下:
http://www.modsecurity.org/testphp.vulnweb.com/artists.php?artist=@@new union#sqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmap select 1,2,database#sqlmap
()
然而,当这段SQL代码进入Mysql的解析引擎的时候,Mysql看到的是这样的形式:
artist=@@new union select 1,2,database()
防御方法:
SQL是一种极其灵活的命令式语言,各个元素之间的组合可以有很多种,采用正则REGEX的方法来进行匹配常常无法做到精确指导,为了解决这个问题,我们有两种思路:
a) 采用高阶的SQL解析方法,例如AST:
http://www.cnblogs.com/LittleHann/p/3495602.html
b) 改进正则,采用敏感关键字匹配的方法
SecRule REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* \
"([\~\!\@\#\$\%\^\&\*\(\)\-\+\=\{\}\[\]\|\:\;\"\'\`\‘\’\<\>].*){4,}" \
"phase:2,t:none,t:urlDecodeUni,block,id:'981173',rev:'2.2.1',msg:'Restricted SQL Character Anomaly Detection Alert - Total # of special characters exceeded',capture,logdata:'%{tx.1}',setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:tx.sql_injection_score=+1,setvar:'tx.msg=%{rule.msg}',setvar:tx.%{rule.id}-WEB_ATTACK/RESTRICTED_SQLI_CHARS-%{matched_var_name}=%{tx.0}"
2.7 注入Payload:
HTML URL编码链接:http://http://www.w3school.com.cn/tags/html_ref_urlencode.html
Payloag分析:
这里采用了"Mysql错误回显"+"Tab键分隔绕过"的组合方法来进行Mod的绕过,这里的关键点是没有使用传统的空格来进行"Split And Balance"。
如果一定要采用黑名单,则必须进行严格的代码审计和测试,保证黑名单的完整性
例如,在Mysql中允许的分隔符为:
09
0A
0B
0C
0D
A0
防御方法:
采用完整的"准空格分隔符"黑名单CRS
SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* \
"(?i:(?:,.*[)\da-f(\"|'|`|´|’|‘)](\"|'|`|´|’|‘)(?:(\"|'|`|´|’|‘).*(\"|'|`|´|’|‘)|\Z|[^(\"|'|`|´|’|‘)]+))|(?:\Wselect.+\W*from)|((?:select|create|rename|truncate|load|alter|delete|update|insert|desc)\s*\(\s*space\s*\())" \
"phase:2,capture,multiMatch,t:none,t:urlDecodeUni,t:replaceComments,block,msg:'Detects MySQL comment-/space-obfuscated injections and backtick termination',id:'981257',tag:'WEB_ATTACK/SQLI',tag:'WEB_ATTACK/ID',logdata:'%{TX.0}',severity:'2',setvar:'tx.msg=%{rule.id}-%{rule.msg}',setvar:tx.anomaly_score=+5,setvar:'tx.%{tx.msg}-WEB_ATTACK/SQLI-%{matched_var_name}=%{tx.0}',setvar:'tx.%{tx.msg}-WEB_ATTACK/ID-%{matched_var_name}=%{tx.0}'
三、总结
Blakclist filtering is not enough -- 不要依赖黑名单机制
应该使用多种方法进行纵深防御
对输入验证采用安全模型,包括规范化、数据类型、数据格式、数据长度
WAF作为一个防御手段,从某种程序上来说只是增加了攻击者的攻击成本,并不能从根本上解决注入的发生,要解决注入漏洞的产生,保护敏感数据,必须多管齐下,从应用系统、waf、数据库防火墙的角度去思考。
四、附录
4.1 information-schema和mysql数据库结构