Gopher URL协议与SSRF二三事
Gopher URL协议
协议工作原理(客户端 - 服务器交互流程)
Gopher 采用 TCP 面向连接 的通信模式,默认使用端口 70(这是 IANA 为 Gopher 分配的标准端口),交互流程极简,仅需 3 步:
建立连接:Gopher 客户端(如早期浏览器、专用 Gopher 工具)向目标服务器的 70 端口发起 TCP 连接;
发送请求:连接建立后,客户端发送 “请求字符串”(通常是资源路径,若请求根目录则发送空字符串),并以 回车换行(\r\n) 结尾;
接收响应与断开连接:服务器收到请求后,返回对应的资源数据(文本 / 二进制 / 菜单列表),数据传输完成后,服务器主动关闭 TCP 连接。
Gopher URL 格式(资源定位)
为了方便用户定位资源,Gopher 协议定义了标准化的 URL 格式,结构如下: gopher://<主机名>[:端口号]/<类型码><资源路径>
各部分含义:
gopher://
:协议标识符,表明使用 Gopher 协议;<主机名>
:服务器域名或 IP(必需,如gopher.example.com
);[:端口号]
:可选,默认 70 端口,非默认端口需指定(如:7070
);<类型码>
:单字符,指定资源类型(必需,如1
表示目录、0
表示文本);<资源路径>
:资源在服务器上的路径(如/docs/readme.txt
,若为根目录则仅/
)。
使用Gopher URL协议模拟 HTTP 的GET方法
1.CURL 工具 发送请求
curl "gopher://127.0.0.1:8080/_GET%20/index.html%20HTTP/1.1%0D%0AHost:127.0.0.1%0D%0A%0D%0A"
2. 使用python3的简单http服务器接收
3.客户端收到服务器的回复
4.通过wireshark 抓包工具我们看看发生了什么
模拟post协议
POST / HTTP/1.1
Host: 1.2.3.4
Content-Type: application/x-www-form-urlencoded user=admin&password=123
那么我的gopher的url协议需要这样写
curl "gopher://127.0.0.1:8090/_POST%20/%20HTTP/1.1%0D%0AHost:%20127.0.0.1%0D%0AContent-Type:%20application/x-www-form-urlencoded%0D%0AContent-Length:%2023%0D%0A%0D%0Auser%26admin%3Dpassword%26123"
可以看到使用这个协议,curl不会在头部中添加任何内容,完全是通过协议自身来发送的url方案决定的
要点
1.所有不安全的符号都要进行url编码
2. _后跟要发送的数据
为什么需要它
使用 SSRF 访问受限制的内部端点。但是,由于无法使用 http://
URL 方案发送 POST 请求,因此我们只能使用 GET 请求。例如,让我们考虑之前 Web 应用程序的另一个版本。假设我们像之前一样识别了内部端点 /admin.php
,那么这次的响应如下所示:
他表示要密码认证,这我们根本没有办法跟这个网页进行交互, 所以使用gopher url方案,因为他会解析我们的url,我们只要向上面一样,小心的构造它,就可以使得服务器发送post请求