1. 程式人生 > 實用技巧 >一段困擾許久的防注入程式碼

一段困擾許久的防注入程式碼

有段時間一直熱衷於研究各種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的時候,可以繞過防注入程式碼,獲取資料庫資訊。