Jinja2 SSTI
实验
from flask import Flask, request, render_template_string
app = Flask(__name__)
@app.route("/")
def home():
if request.args.get('c'):
return render_template_string(request.args.get('c'))
else:
return "Hello, send someting inside the param 'c'!"
if __name__ == "__main__":
app.run()其他
调试语句
如果启用了调试扩展,将会提供一个debug标签,用于转储当前上下文以及可用的过滤器和测试。这对于查看模板中可用的内容而无需设置调试器非常有用。
转储所有配置变量
源链接: https://jinja.palletsprojects.com/en/2.11.x/templates/#debug-statement
Jinja注入
首先,在Jinja注入中,您需要找到一种方法来逃离沙盒并恢复访问常规的Python执行流程。为此,您需要滥用来自非沙盒环境但在沙盒中可访问的对象。
访问全局对象
例如,在代码render_template("hello.html", username=username, email=email)中,对象username和email来自非沙盒的Python环境,并将在沙盒环境内可访问。
此外,还有其他对象将始终可以从沙盒环境中访问,这些对象包括:
恢复<class 'object'>
然后,从这些对象中,我们需要到达类:<class 'object'>,以便尝试恢复定义的类。这是因为从这个对象中,我们可以调用**__subclasses__方法并访问来自非沙盒**python环境的所有类。
为了访问那个对象类,您需要访问一个类对象,然后访问**__base__,__mro__()[-1]或mro()[-1]。然后,在到达这个对象类之后,我们调用** __subclasses__()。
请查看这些示例:
RCE Escaping
已经恢复 <class 'object'> 并调用 __subclasses__,现在我们可以使用这些类来读取和写入文件并执行代码。
调用 __subclasses__ 给了我们机会访问数百个新函数,我们将很高兴只是通过访问文件类来读取/写入文件或任何具有访问允许执行命令的类的类(如 os)。
读取/写入远程文件
远程代码执行(RCE)
了解更多可用于逃逸的更多类,您可以检查:
Bypass Python sandboxes过滤绕过
常见绕过
这些绕过将允许我们访问对象的属性,而无需使用某些字符。 我们已经在先前的示例中看到了一些这些绕过的情况,但让我们在这里总结一下:
避免HTML编码
默认情况下,Flask会对模板中的所有内容进行HTML编码,以确保安全性:
safe 过滤器允许我们将 JavaScript 和 HTML 注入到页面中,而无需对其进行HTML 编码,就像这样:
通过编写恶意配置文件实现远程代码执行(RCE)。
没有几个字符
没有 {{ . [ ] }} _
无需使用 <class 'object'> 的 Jinja 注入
从全局对象中有另一种方法可以实现 RCE 而无需使用该类。
如果你设法访问到这些全局对象中的任何 函数,你将能够访问 __globals__.__builtins__,从那里 RCE 就非常 简单。
你可以通过以下方式从对象 request、config 和任何其他你可以访问的有趣的 全局对象 中 找到函数:
一旦找到了一些函数,您可以使用以下方法恢复内置函数:
参考资料
最后更新于