探究Flask/Jinja2中的服务端模版注入(一)
假如你还没听说过SSTI(服务端模版注入),或许对其还不够了解,在此之前主张咱们去阅览一下James Kettle写的一篇文章。
作为一名专业的安全从事人员,咱们的作业便是协助企业安排进行危险决议计划。及时发现产品存在的要挟,缝隙对产品带来的影响是无法精确核算。作为一名常常运用Flask结构进行开发的人来说,James的研讨促进我下定决心去研讨在运用Flask/Jinja2结构进行运用开发时服务端模版注入的一些细节。
Setup
为了精确评价Flask/Jinja2中存在的SSTI,现在咱们就树立一个PoC运用:
@app.errorhandler(404)
def page_not_found(e):
template = '''{%% extends "layout.html" %%}
{%% block body %%}
Oops! That page doesn't exist.
%s
{%% endblock %%}
''' % (request.url)
return render_template_string(template), 404
这段代码的背面场景应该是开发者愚笨的以为这个404页面有一个独自的模版文件, 所以他在404 view函数中创建了一个模版字符串。这个开发者期望假如发作过错,就将该URL反馈给用户;但却不是经由render_template_string函数将URL传递给模版上下文,该开发者挑选运用字符串格式化将URL动态增加到模版字符串中,这么做没错对吧?卧槽,这还不算我见过最糟糕的。
运转该功用,咱们应该能够看到以下预期作用
大多数朋友看到以下发作的行为马上就会在脑子中想到XSS,当然他们的主意是正确的。在URL后边增加alert(42)会触发一个XSS缝隙。
方针代码存在XSS缝隙,而且假如你阅览James的文章之后就会知道,他曾明确指出XSS极有可能是存在SSTI的一个要素,这便是一个很棒的比方。可是咱们经过在URL后边增加{{ 7+7 }}在深化的去了解下。咱们看到模版引擎将数学表达式的值现已核算出来
在方针运用中咱们现已发现SSTI的踪影了。
Analysis
接下来有得咱们忙的了,下一步咱们便深化模版上下文并探寻进犯者会怎么经过SSTI缝隙进犯该运用程序。以下为咱们修正往后的存在缝隙的view函数:
@app.errorhandler(404)
def page_not_found(e):
template = '''{%% extends "layout.html" %%}
{%% block body %%}
Oops! That page doesn't exist.
%s
{%% endblock %%}
''' % (request.url)
return render_template_string(template,
dir=dir,
help=help,
locals=locals,
), 404
调用的render_template_string现在包括dir, help, locals 内置模版,将他们增加到模板上下文咱们便能够经过该缝隙运用这些内置模板进行内省。
时间短的暂停,咱们来谈谈文档中关于模板上下文的描述。
Jinja globals
Flask template globals
由开发者增加的素材资料
咱们最关怀的是第一条和第二条,由于他们通常情况下都是默认值,Flask/Jinja2结构下存在SSTI缝隙运用中的任何地方都能够进行运用。第三条取决于运用程序而且完成的办法太多,stackoverflow评论中就有几种办法。在本文中咱们不会对第三条进行深化探讨,可是在对Flask/Jinja2结构的运用进行静态源代码剖析的时分仍是很值得考虑的。
为了持续内省,咱们应该:
阅览文档
运用dir内省locals目标来检查一切能够运用的模板上下文
运用dir和help.深化一切目标
剖析感兴趣的Python源代码(究竟结构都是开源的)
Results
经过内省request目标咱们收集到第一个愿望中的玩具,request是Flask模版的一个大局目标,其代表“当时恳求目标(flask.request)”,在视图中拜访request目标你能看到许多你等待的信息。在request 目标中有一个environ目标名。request.environ目标是一个与服务器环境相关的目标字典,字典中一个名为shutdown_server的办法名分配的键为werkzeug.server.shutdown,那么咱们能够猜猜打针{{ request.environ['werkzeug.server.shutdown']() }}在服务端会做些什么?一个影响极低的拒绝服务,运用gunicorn运转运用程序这个办法的作用便消失,所以该缝隙局限性仍是挺大的。
咱们的第二个发现来自于内省config目标,config也是Flask模版中的一个大局目标,它代表“当时装备目标(flask.config)”,它是一个类字典的目标,它包括了一切运用程序的装备值。在大多数情况下,它包括了比方数据库链接字符串,连接到第三方的凭据,SECRET_KEY等灵敏值。检查这些装备项目,只需注入{{ config.items() }}有效载荷。
[1] [2] [3] [4] 黑客接单网