PHP是世界上最好的语言
<?php
//flag in $flag
highlight_file(__FILE__);
include("flag.php");
$c=$_POST['sys'];
$key1 = 0;
$key2 = 0;
if(isset($_GET['flag1']) || isset($_GET['flag2']) || isset($_POST['flag1']) || isset($_POST['flag2'])) {
die("nonononono");
}
@parse_str($_SERVER['QUERY_STRING']);
extract($_POST);
if($flag1 == '8gen1' && $flag2 == '8gen1') {
if(isset($_POST['504_SYS.COM'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\?/", $c)){
eval("$c");
}
}
}
?>
解析
-
代码分析
PHP extract() 函数可以从数组中把变量导入到当前的符号表中,键名用于变量名,键值用于变量值。当有重复的键名,键值会被替换成新传入的,从而造成了extract() 函数变量覆盖漏洞。回到代码,POST数组中的变量通过extract() 函数被导入符号表,传入的变量与变量值需满足$flag1=8gen1&$flag2=8gen1,若变量名不冲突直接写入,若冲突将原来的变量值覆盖,同时判断POST请求若包含参数504_SYS.COM,则直接 执行 $c 存储的内容。
-
tips:
php变量名只能是数字字母下划线,传进去的变量名会将 + , . , [ 等符号转换成 _,
若变量中已经有 +,. ,[ 替换成 _ 后,之后的字符不会再被替换成 _ ,例如a[b.c → a_b.c 。
Payload
-
GET传入
无论是 GET 还是 POST 请求的参数都能够被解析出来并转换为对应的变量,这里由于题目限制,
不能直接通过GET或者POST传入$flag1=8gen1&$flag2=8gen1,故而构造 $_POST[‘flag1’] 和
$_POST[‘flag2’] 的值都设置为 ‘8gen1’。 - POST传入
504[SYS.COM=123&sys=echo $flag; // 504[SYS.COM=123 实际上是一个无意义的字符串,
它只是为了占据一个位置,从而使整个字符串能够通过 $_POST 数组被解析成一个键值对,
即 ‘504_SYS.COM’ => ‘123’。而 sys=echo $flag; 则是覆盖了原本的 $_POST[‘sys’] 值,
将其设置为 ‘echo $flag;’。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
暂无评论内容