第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查询。
通过参数污染构造攻击语句:
sql
?id=1&id=-1' union select 1,2,database() --+

第30关 "闭合

第31关 '')闭合
