0x00 闲话

em,这估计就是我的风格了。Gopher广泛用于SSRF,不可不认真学。

参考文章:Gopher协议在SSRF漏洞中的深入研究(附视频讲解) - 知乎 (zhihu.com)

0x01 概况

Gopher是互联网早期的一种协议。

利用gopher协议可以攻击内网的 Redis、Mysql、FastCGI、Ftp 等,也可以发送 GET、POST 请求,这可以拓宽 SSRF 的攻击面。

Gopher至少在PHP还是比较支持的。

0x02 格式

概述

1
gopher://<host>:<port>/<gopher-path>_后接TCP数据流

注意几点:

  • gopher的默认端口是70
  • 如果是post请求,回车换行要用到%0d%0a(post请求有几个必备请求头)
  • 基于post请求,如果有多个参数,也要把&进行URL编码

Gopher发送HTTP GET请求

基础

这里端口先开一个,姑且称之为num(已经有负载的端口不行哦)

监听:nc -lvp num

发送:gopher://555.555.555.555:num/_abcd

返回:abcd

没错,第一个字符给弄没了,这个很好解决(解决的方法就是不解决)

格式

三步:

  1. 构造HTTP数据包
  2. URL编码、替换回车换行为%0d%0a
  3. 发送gopher协议

注意事项:

  • 问号(?)需要转码为URL编码,也就是%3f
  • 回车换行要变为%0d%0a,但如果直接用工具转,可能只会有%0a
  • 在HTTP包的最后要加%0d%0a,代表消息结束(具体可研究HTTP包结束)

eg:

PHP代码

1
2
3
<?php
echo "Hello ".$_GET["name"]."\n"
?>

请求:

1
2
GET /ssrf/get.php?name=haandsome HTTP/1.1
Host: 555.555.555.555

构造请求包:

1
2
3
gopher://555.555.555.555/_GET /ssrf/get.php?name=handsome HTTP/1.1
Host: 555.555.555.555

编码(这里是一次的,一般情况下要两次,我还没搞懂):

1
gopher://555.555.555.555:80/_GET%20/ssrf/base/get.php%3fname=Margin%20HTTP/1.1%0d%0AHost:%20192.168.0.109%0d%0A

tip: URL 编码中,%0A%0a 实际上是表示相同的字符,即换行符。它们之间的区别在于大小写。在 URL 编码中,字母的大小写通常是不敏感的,因此 %0A%0a 都会被解释为换行符。

Gopher发送HTTP POST请求

格式:

1
2
3
4
5
6
POST /ssrf/post.php HTTP/1.1
host:555.555.555.555
Content-Type:application/x-www-form-urlencoded
Content-Length:11

name=handsome

这几个请求头不能少

写包:

1
2
3
4
5
6
7
gopher://555.555.555.555:80/_POST /ssrf/base/post.php HTTP/1.1
Host:192.168.0.109
Content-Type:application/x-www-form-urlencoded
Content-Length:11

name=Margin

url编码(实际操作要两次):

1
gopher://555.555.555.555:80/_POST%20%2Fssrf%2Fbase%2Fpost.php%20HTTP%2F1.1%0D%0AHost%3A555.555.555.555%0D%0AContent-Type%3Aapplication%2Fx-www-form-urlencoded%0D%0AContent-Length%3A11%0D%0A%0D%0Aname%3Dhandsome%0D%0A

SSRF Gopher URL编码两次

推荐文章:

https://blog.csdn.net/2202_75361164/article/details/137092879

https://cloud.tencent.com/developer/article/2348163

引用:

传参经过多少次跳转就需要经过多少次url编码。

直接curl后接gopher://就编码一次。

利用?url=gopher://就编码两次。

还经过302跳转,就编码三次。