一段困擾許久的防注入程式碼
阿新 • • 發佈:2021-01-11
有段時間一直熱衷於研究各種waf繞過,一般來說,雲WAF可以通過找到網站真實IP來繞過,硬體waf也常因為HTTP協議解析差異導致繞過,但是,程式碼層的防護往往只能從程式碼邏輯裡尋找繞過思路。
在一些網站通常會在公用檔案引入全域性防護程式碼,因此,我收集了網路上常見的PHP全域性防護程式碼進行分析。第一次看到safe3的防注入程式碼,花了不少時間去研究如何繞過,我在筆記裡記下了一句話:如果正面懟正則,實在想不到繞過的方式。
直到前幾天,我在T00LS論壇裡看到有人也問起了同一段防注入程式碼的繞過方式,在這個帖子的回覆了看到了一個繞過姿勢。這也正是安全社群最大的魅力,你總會在別人的回覆裡找到很有意思的思路或技巧。
繞過思路
利用preg_match函式正則匹配的字串長度限制繞過,PHP5.3之前preg_match函式閾值預設為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>提交引數: ".$StrFiltKey."<br>提交資料: ".$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>提交引數: ".$StrFiltKey."<br>提交資料: ".$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)構建一個sql注入點
在頁面中引入防注入程式碼:
require_once('360_safe3.php');
當引數中拼接sql語句時,觸發關鍵字正則匹配導致攔截。
(3)繞過姿勢
PHP測試版本:5.2.17
當填充字串超過10w的時候,可以繞過防注入程式碼,獲取資料庫資訊。
PHP測試版本:5.3.29
當填充字串超過100w的時候,可以繞過防注入程式碼,獲取資料庫資訊。