PHP程式碼層防護與繞過
0x01 前言
在一些網站通常會在公用檔案引入全域性防護程式碼進行SQL注入、XSS跨站指令碼等漏洞的防禦,在一定程度上對網站安全防護還是比較有效的。
這裡討論一下關鍵字過濾不完善及常見正則匹配存在的問題,並收集了網路上常見的PHP全域性防護程式碼進行分析。
Bypass思路:利用資料庫特性或過濾函式邏輯缺陷繞過。
0x02 關鍵字過濾
1、使用strpos過濾關鍵字
PHP過濾程式碼如下:
<?php $str = "and|or|union|select|from|where|limit|order by|guoup by|<script>|</script>"; $arr=explode("|",$str); #print_r($arr); foreach($arr as $key=>$val){ $flag=strpos($_GET['id'],$val); if ($flag){ echo 'Error'; exit(); } } ?>
Bypass思路:strpos() 函式查詢字串在另一字串中第一次出現的位置。strpos() 函式對大小寫敏感。
大小寫繞過:id=1 AND 1=1 UNION SELECT 1,2,3 FROM ADMIN
2、使用stripos,進行關鍵字過濾
與strpos相比,stripos() - 查詢字串在另一字串中第一次出現的位置(不區分大小寫)
PHP過濾程式碼如下:
<?php $str = "and|or|union|select|from|where|limit|order by|guoup by|<script>|</script>"; $arr=explode("|",$str); #print_r($arr); foreach($arr as $key=>$val){ $flag=strpos($_GET['id'],$val); if ($flag){ echo 'Error'; exit(); } } ?>
Bypass思路:
當$flag等於0,即關鍵字在輸入引數的第一位,可繞過
id=</script><a href="javascript:alert(/xss/)">xsstest<a>
關鍵字過濾類似的方法:
<?php $blacklist_keywords = 'select,from,1=1,--,union,#'; $blacklist = explode(',',$blacklist_keywords); print_r($blacklist); foreach($blacklist as $key=>$value){ //$_REQUEST['id'] = str_replace(strtolower($value),'',strtolower($_REQUEST['id'])); $_REQUEST['id'] = str_replace($value,'',$_REQUEST['id']); } echo $_REQUEST['id']; ?>
0x03 正則匹配
1、邊界關鍵詞
b 表示單詞的邊界,因此只有獨立的 "union" 單詞會被匹配
PHP過濾程式碼如下:
<?php if (preg_match("/b(union|select|from)b/i",$_GET['id'])==1){ echo "Error"; exit(); } echo "success" ; ?>
Bypass思路:
通過資料庫的特性,在關鍵字前後新增字元,打擾關鍵字邊界判斷
id=1e0union/*!12345select*/1,2,3,4/*!12345from*/users
2、匹配模式
i 忽略大小寫,匹配不考慮大小寫,預設不匹配多行
PHP過濾程式碼如下:
<?php if (preg_match("/(?:(union(.*?)select))/i",$_GET['id'])==1){ echo "Error"; exit(); } echo "success" ; ?>
Bypass思路:
通過換行 n可繞過,url編碼為%0a
id=1 union%23%0aseleCT 1,2,3,4 from users
修復方案:
preg_match("/(?:(union(.*?)select))/ims",$_GET['id'])
0x04 PHP通用防護程式碼
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."rn"); fclose($Ts); } ?>
如果正面懟正則,實在想不到繞過的方式。。
2、360webscan防禦指令碼
360網站安全:http://webscan.360.cn
http://webscan.360.cn/protect/index/?act=reinstall&domain=www.test.com下載漏洞修復外掛360webscan.zip 多次下載解壓失敗,
無奈,跑到cmseasy下載最新版cms,解壓獲取 webscan360/360safe目錄,分享到網盤,連結: https://pan.baidu.com/s/1nviNi2l 密碼: 3itq
WEBSCAN_VERSION :0.1.3.2
SQL語句測試,成功攔截:
Bypass思路:
關鍵的兩個正則:
UNION.+?SELECTs*((.+)s*|@{1,2}.+?s*|s+?.+?|(`|'|").*?(`|'|")s*) (SELECT|DELETE)@{0,2}(\(.+\)|\s+?.+?\s+?|(`|'|").*?(`|'|"))FROM(\(.+\)|\s+?.+?|(`|'|").*?(`|'|")) id=1e0union select!1,user(),3,4 from users
0x05 結束
本文簡單演示了幾種防護程式碼和繞過場景,在攻與防的道路上,不只是掌握一些技巧,是與程式碼的對抗,更是人與人的對抗。