理论
parse_str
函数的作用就是解析字符串并注册成变量,在注册变量之前不会验证当前变量是否存在,所以直接覆盖掉已有变量。
void parse_str ( string $str [, array &$arr ] )
str 输入的字符串。
arr 如果设置了第二个变量 arr,变量将会以数组元素的形式存入到这个数组,作为替代。
实践
测试代码:
<?php
error_reporting(0);
$flag = 'flag{V4ri4ble_M4y_Be_C0verEd}';
if (empty($_GET['b'])) {
show_source(__FILE__);
die();
}else{
$a = "www.sqlsec.com";
$b = $_GET['b'];
@parse_str($b);
if ($a[0] != 'QNKCDZO' && md5($a[0]) == md5('QNKCDZO')) {
echo $flag;
}else{
exit('your answer is wrong~');
}
}
?>
考察点
- parse_str变量覆盖缺陷
write-up
找到核心代码:
@parse_str($b);
这里使用了parse_str函数来传递b的变量值
if ($a[0] != 'QNKCDZO' && md5($a[0]) == md5('QNKCDZO'))
这里用到的是文章上面的知识点md5()函数缺陷
因为这里用到了parse_str
函数来传递b
,if语句的条件是拿$a[0]
来比较的,因为这里的变量a的值已经是固定的了。
整体代码乍看起来又不可能,但是利用变量覆盖函数的缺陷这里可以对a
的变量进行重新赋值,后面的的if语句再利用本文前面提到的md5()
比较缺陷进行绕过:
http://localhost/?b=a[0]=240610708