一段困擾許久的防注入代碼
本文轉(zhuǎn)載自微信公眾號「Bypass」,作者Bypass。轉(zhuǎn)載本文請聯(lián)系Bypass公眾號。
有段時間一直熱衷于研究各種waf繞過,一般來說,云WAF可以通過找到網(wǎng)站真實IP來繞過,硬件waf也常因為HTTP協(xié)議解析差異導致繞過,但是,代碼層的防護往往只能從代碼邏輯里尋找繞過思路。
在一些網(wǎng)站通常會在公用文件引入全局防護代碼,因此,我收集了網(wǎng)絡上常見的PHP全局防護代碼進行分析。第一次看到safe3的防注入代碼,花了不少時間去研究如何繞過,我在筆記里記下了一句話:如果正面懟正則,實在想不到繞過的方式。
直到前幾天,我在T00LS論壇里看到有人也問起了同一段防注入代碼的繞過方式,在這個帖子的回復了看到了一個繞過姿勢。這也正是安全社區(qū)最大的魅力,你總會在別人的回復里找到很有意思的思路或技巧。
繞過思路
利用preg_match函數(shù)正則匹配的字符串長度限制繞過,PHP5.3之前preg_match函數(shù)閾值默認為10w,PHP5.3開始默認值為100w。
測試情況
(1) safe3 防注入代碼
- <?php
- //Code By Safe3
- ini_set('date.timezone','Asia/Shanghai');
- function customError($errno, $errstr, $errfile, $errline)
- {
- echo "<b>Error number:</b> [$errno],error on line $errline in $errfile<br />";
- die();
- }
- set_error_handler("customError",E_ERROR);
- $getfilter="'|select|from|(and|or)\\b.+?(>|<|=|in|like)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
- $postfilter="\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
- $cookiefilter="\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
- function StopAttack($StrFiltKey,$StrFiltValue,$ArrFiltReq){
- if(is_array($StrFiltValue))
- {
- $StrFiltValue=implode($StrFiltValue);
- }
- if (preg_match("/".$ArrFiltReq."/is",$StrFiltValue)==1){
- slog("<br><br>操作IP: ".$_SERVER["REMOTE_ADDR"]."<br>操作時間: ".strftime("%Y-%m-%d %H:%M:%S")."<br>操作頁面:".$_SERVER["PHP_SELF"]."<br>提交方式: ".$_SERVER["REQUEST_METHOD"]."<br>提交參數(shù): ".$StrFiltKey."<br>提交數(shù)據(jù): ".$StrFiltValue);
- @header("http/1.1 404 not found");
- print "<html><title>404: Not Found</title>";
- //slog("<br><br>操作IP: ".$_SERVER["REMOTE_ADDR"]."<br>操作時間: ".strftime("%Y-%m-%d %H:%M:%S")."<br>操作頁面:".$_SERVER["PHP_SELF"]."<br>提交方式: ".$_SERVER["REQUEST_METHOD"]."<br>提交參數(shù): ".$StrFiltKey."<br>提交數(shù)據(jù): ".$StrFiltValue);
- print "<body>Url里含有非法字符串,屬于有誤操作!... <a href='/'>您還可以返回首頁</a></body></html>";
- ;exit();
- }
- }
- //$ArrPGC=array_merge($_GET,$_POST,$_COOKIE);
- foreach($_GET as $key=>$value){
- StopAttack($key,$value,$getfilter);
- }
- foreach($_POST as $key=>$value){
- StopAttack($key,$value,$postfilter);
- }
- foreach($_COOKIE as $key=>$value){
- StopAttack($key,$value,$cookiefilter);
- }
- function slog($logs)
- {
- $toppath=$_SERVER["DOCUMENT_ROOT"]."/log.htm";
- $Ts=fopen($toppath,"a+");
- fputs($Ts,$logs."\r\n");
- fclose($Ts);
- }
- ?>
(2) 構(gòu)建一個sql注入點
在頁面中引入防注入代碼:
- require_once('360_safe3.php');
當參數(shù)中拼接sql語句時,觸發(fā)關(guān)鍵字正則匹配導致攔截。
(3) 繞過姿勢
PHP測試版本:5.2.17
當填充字符串超過10w的時候,可以繞過防注入代碼,獲取數(shù)據(jù)庫信息。
PHP測試版本:5.3.29
當填充字符串超過100w的時候,可以繞過防注入代碼,獲取數(shù)據(jù)庫信息。