第29關 HTTP參數污染
本關設置了web應用防火墻(WAF),利用白名單保護機制來檢測和攔截惡意請求。看本關源代碼。
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
//disable error reporting
error_reporting(0);// take the variables
if(isset($_GET['id'])) // 檢查URL參數中是否存在id
{$qs = $_SERVER['QUERY_STRING']; // 獲取完整的查詢字符串$hint=$qs; // 保存查詢字符串用于提示$id1=java_implimentation($qs); // 模擬Java處理HPP的函數,提取第一個id參數值$id=$_GET['id']; // 獲取PHP解析的id參數值//echo $id1;whitelist($id1); // 調用白名單過濾函數,驗證id1是否為純數字//logging the connection parameters to a file for analysis.$fp=fopen('result.txt','a'); // 以追加模式打開日志文件fwrite($fp,'ID:'.$id."\n"); // 記錄請求的id參數fclose($fp); // 關閉文件資源// connectivity $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1"; // SQL查詢語句,存在SQL注入風險$result=mysql_query($sql); // 執行SQL查詢$row = mysql_fetch_array($result); // 獲取查詢結果if($row) // 如果查詢到結果{echo "<font size='5' color= '#99FF00'>"; echo 'Your Login name:'. $row['username']; // 輸出用戶名echo "<br>";echo 'Your Password:' .$row['password']; // 輸出密碼echo "</font>";}else {echo '<font color= "#FFFF00">';print_r(mysql_error()); // 輸出MySQL錯誤信息echo "</font>"; }
}else { echo "Please input the ID as parameter with numeric value";} // 提示用戶輸入數值型ID//WAF implimentation with a whitelist approach..... only allows input to be Numeric.
function whitelist($input) // 白名單過濾函數,只允許純數字輸入
{$match = preg_match("/^\d+$/", $input); // 使用正則表達式檢查是否為純數字if($match){//echo "you are good";//return $match;}else{ header('Location: hacked.php'); // 非數字輸入重定向到hacked.php//echo "you are bad";}
}// The function below immitates the behavior of parameters when subject to HPP (HTTP Parameter Pollution).
function java_implimentation($query_string) // 模擬Java處理HPP的函數
{$q_s = $query_string;$qs_array= explode("&",$q_s); // 將查詢字符串按&分割為數組foreach($qs_array as $key => $value) // 遍歷參數數組{$val=substr($value,0,2); // 獲取參數名前兩個字符if($val=="id") // 找到第一個id參數{$id_value=substr($value,3,30); // 提取id參數值(從第3個字符開始的30個字符)return $id_value;echo "<br>";break;}}
}
?>
這里的WAF白名單只允許輸入的參數id為純數字,阻止了sql注入攻擊。
本關的關鍵點在于,調用java_implimentation函數處理查詢字符串,這個函數的作用是模擬 Java 對 HTTP 參數的解析方式,只返回第一個id參數的值。而直接使用$_GET['id']獲取的id是PHP默認行為(如果有多個id參數,則取最后一個)。
WAF檢測的是傳入的第一個id值,如果在傳入第二個id值中構造sql語句,則會產生注入攻擊。
這種傳遞多個參數,干擾正常邏輯,影響服務器判斷的行為,就是HTTP參數污染(HPP)。
構造測試語句:
這里id=1返回的是用戶Dumb,id=1&id=2返回的是用戶Angelina,也就是說實際上第一個id被用于白名單檢查,第二個id被用于sql查詢。
?通過參數污染構造攻擊語句:
?id=1&id=-1' union select 1,2,database() --+