乐趣区

关于web:Web-Security-之-Serverside-template-injection

Server-side template injection

在本节中,咱们将介绍什么是服务端模板注入,并概述利用此破绽的根本办法,同时也将提供一些防止此破绽的倡议。

什么是服务端模板注入

服务端模板注入是指攻击者可能利用模板本身语法将歹意负载注入模板,而后在服务端执行。

模板引擎被设计成通过联合固定模板和可变数据来生成网页。当用户输出间接拼接到模板中,而不是作为数据传入时,可能会产生服务端模板注入攻打。这使得攻击者可能注入任意模板指令来操纵模板引擎,从而可能齐全管制服务器。顾名思义,服务端模板注入无效负载是在服务端交付和执行的,这可能使它们比典型的客户端模板注入更危险。

服务端模板注入会造成什么影响

服务端模板注入破绽会使网站面临各种攻打,具体取决于所探讨的模板引擎以及应用程序如何应用它。在极少数状况下,这些破绽不会带来真正的平安危险。然而,大多数状况下,服务端模板注入的影响可能是灾难性的。

最重大的状况是,攻击者有可能实现近程代码执行,从而齐全管制后端服务器,并利用它对外部基础设施进行其余攻打。

即便在不可能齐全执行近程代码的状况下,攻击者通常仍能够应用服务端模板注入作为许多其余攻打的根底,从而可能取得服务器上敏感数据和任意文件的拜访权限。

服务端模板注入破绽是如何产生的

当用户输出间接拼接到模板中而不是作为数据传入时,就会呈现服务端模板注入破绽。

简略地提供占位符并在其中出现动静内容的动态模板通常不会受到服务端模板注入的攻打。典型的例子如提取用户名作为电子邮件的结尾,例如以下从 Twig 模板中提取的内容:

$output = $twig->render("Dear {first_name},", array("first_name" => $user.first_name) );

这不容易受到服务端模板注入的攻打,因为用户的名字只是作为数据传递到模板中的。

然而,Web 开发人员有时可能将用户输出间接连贯到模板中,如:

$output = $twig->render("Dear" . $_GET['name']);

此时,不是将动态值传递到模板中,而是应用 GET name 动静生成模板自身的一部分。因为模板语法是在服务端执行的,这可能容许攻击者应用 name 参数如下:

http://vulnerable-website.com/?name={{bad-stuff-here}}

像这样的破绽有时是因为不相熟平安概念的人设计了有缺点的模板造成的。与下面的例子一样,你可能会看到不同的组件,其中一些组件蕴含用户输出,连贯并嵌入到模板中。在某些方面,这相似于 SQL 注入破绽,都是编写了不当的语句。

然而,有时这种行为实际上是无意为之。例如,有些网站成心容许某些特权用户(如内容编辑器)通过设计来编辑或提交自定义模板。如果攻击者可能利用特权帐户,这显然会带来微小的平安危险。

结构服务端模板注入攻打

辨认服务端模板注入破绽并策动胜利的攻打通常波及以下形象过程。

探测

服务端模板注入破绽经常不被留神到,这不是因为它们很简单,而是因为它们只有在明确寻找它们的审计人员背后才真正显著。如果你可能检测到存在破绽,则利用它将非常容易。在非沙盒环境中尤其如此。

与任何破绽一样,利用破绽的第一步就是先找到它。兴许最简略的初始办法就是注入模板表达式中罕用的一系列特殊字符,例如 ${{<%[%'"}}%\,去尝试模糊化模板。如果引发异样,则表明服务器可能以某种形式解释了注入的模板语法,从而表明服务端模板注入可能存在破绽。

服务端模板注入破绽产生在两个不同的上下文中,每个上下文都须要本人的检测办法。不论模糊化尝试的后果如何,也要尝试以下特定于上下文的办法。如果模糊化是不确定的,那么应用这些办法之一,破绽可能会裸露进去。即便模糊化的确表明存在模板注入破绽,你依然须要确定其上下文能力利用它。

Plaintext context

纯文本上下文。

大多数模板语言容许你通过间接应用 HTML tags 或模板语法自在地输出内容,后端在发送 HTTP 响应之前,会把这些内容渲染为 HTML。例如,在 Freemarker 模板中,render('Hello' + username) 可能会渲染为 Hello Carlos

这有时常常被误认为是一个简略的 XSS 破绽并用于 XSS 攻打。然而,通过将数学运算设置为参数的值,咱们能够测试其是否也是服务端模板注入攻打的潜在攻击点。

例如,思考蕴含以下模板代码:

render('Hello' + username)

在审查过程中,咱们能够通过申请以下 URL 来测试服务端模板注入:

http://vulnerable-website.com/?username=${7*7}

如果后果输入蕴含 Hello 49,这表明数学运算被服务端执行了。这是服务端模板注入破绽的一个很好的证实。

请留神,胜利计算数学运算所需的特定语法将因应用的模板引擎而异。咱们将在 Identify 步骤具体阐明。

Code context

代码上下文。

在其余状况下,破绽裸露是因为将用户输出放在了模板表达式中,就像上文中的电子邮件示例中看到的那样。这能够采纳将用户可管制的变量名搁置在参数中的模式,例如:

greeting = getQueryParameter('greeting')
engine.render("Hello {{"+greeting+"}}", data)

在网站上生成的 URL 相似于:

http://vulnerable-website.com/?greeting=data.username

渲染的输入可能为 Hello Carlos

在评估过程中很容易疏忽这个上下文,因为它不会产生显著的 XSS,并且与简略的 hashmap 查找简直没有区别。在这种状况下,测试服务端模板注入的一种办法是首先通过向值中注入任意 HTML 来确定参数不蕴含间接的 XSS 破绽:

http://vulnerable-website.com/?greeting=data.username<tag>

在没有 XSS 的状况下,这通常会导致输入中呈现空白(只有 Hello,没有 username),编码标签或错误信息。下一步是尝试应用通用模板语法来跳出该语句,并尝试在其后注入任意 HTML:

http://vulnerable-website.com/?greeting=data.username}}<tag>

如果这再次导致谬误或空白输入,则阐明你应用了谬误的模板语法。或者,模板款式的语法均有效,此时则无奈进行服务端模板注入。如果输入与任意 HTML 一起正确出现,则这是服务端模板注入破绽存在的要害证实:

Hello Carlos<tag>

辨认

一旦检测到潜在的模板注入,下一步就是确定模板引擎。

只管有大量的模板语言,但许多都应用十分类似的语法,这些语法是专门为防止与 HTML 字符抵触而抉择的。因而,结构试探性载荷来测试正在应用哪个模板引擎可能绝对简略。

简略地提交有效的语法就足够了,因为生成的谬误音讯会通知你用了哪个模板引擎,有时甚至能具体到哪个版本。例如,非法的表达式 <%=foobar%> 触发了基于 Ruby 的 ERB 引擎的如下响应:

(erb):1:in `<main>': undefined local variable or method `foobar' for main:Object (NameError)
from /usr/lib/ruby/2.5.0/erb.rb:876:in `eval'from /usr/lib/ruby/2.5.0/erb.rb:876:in `result'
from -e:4:in `<main>'

否则,你将须要手动测试不同语言特定的无效负载,并钻研模板引擎如何解释它们。应用基于语法无效或有效的排除过程,你能够比你设想的更快地放大选项范畴。一种常见的办法是应用来自不同模板引擎的语法注入任意的数学运算。而后,察看它们是否被胜利执行。要实现此过程,能够应用相似于以下内容的决策树:

你应该留神,同样的无效负载有时能够取得多个模板语言的胜利响应。例如,有效载荷 {{7*'7'}}Twig 中返回 49,在 Jinja2 中返回 7777777。因而,不要只因为胜利响应了就粗率下结论。

利用

在检测到存在潜在破绽并胜利辨认模板引擎之后,就能够开始尝试寻找利用它的办法。具体请翻阅下文。

如何避免服务端模板注入破绽

避免服务端模板注入的最佳办法是不容许任何用户批改或提交新模板。然而,因为业务需要,这有时是不可避免的。

防止引入服务端模板注入破绽的最简略办法之一是,除非相对必要,始终应用“无逻辑”模板引擎,如 Mustache。尽可能的将逻辑与示意拆散,这能够大大减少高危险性的基于模板的攻打的危险。

另一措施是仅在齐全删除了潜在危险模块和性能的沙盒环境中执行用户的代码。可怜的是,对不可信的代码进行沙盒解决自身就很艰难,而且容易被绕过。

最初,对于承受任意代码执行无奈防止的状况,另一种补充办法是,通过在锁定的例如 Docker 容器中部署模板环境,来利用你本人的沙盒。


利用服务端模板注入破绽

在本节中,咱们将更认真地理解一些典型的服务端模板注入破绽,并演示如何利用之前演绎的办法。通过付诸实践,你能够潜在地发现和利用各种不同的服务端模板注入破绽。

一旦发现服务端模板注入破绽,并确定正在应用的模板引擎,胜利利用该破绽通常波及以下过程。

  • 浏览

    • 模板语法
    • 平安文档
    • 已知的破绽利用
  • 摸索环境
  • 结构自定义攻打

浏览

除非你曾经对模板引擎一目了然,否则应该先浏览其文档。尽管这可能有点无聊,然而不要低估文档可能是有用的信息起源。

学习根本模板语法

学习根本语法、要害函数和变量解决显然很重要。即便只是简略地学习如何在模板中嵌入本机代码块,有时也会很快导致破绽利用。例如,一旦你晓得正在应用基于 Python 的 Mako 模板引擎,实现近程代码执行能够简略到:

<%
import os
x=os.popen('id').read()
%>
${x}

在非沙盒环境中,实现近程代码执行并将其用于读取、编辑或删除任意文件在许多常见模板引擎中都非常简单。

浏览平安局部

除了提供如何创立和应用模板的基础知识外,文档还可能提供某种“平安”局部。这个局部的名称会有所不同,但它通常会概括出人们应该防止应用模板进行的所有潜在危险的事件。这可能是一个十分贵重的资源,甚至能够作为一种备忘单,为你应该寻找哪些行为,以及如何利用它们提供指南。

即便没有专门的“平安”局部,如果某个特定的内置对象或函数会带来平安危险,文档中简直总是会呈现某种正告。这个正告可能不会提供太多细节,但至多应将其标记为能够深刻开掘钻研的内容。

例如,在 ERB 模板中,文档显示能够列出所有目录,而后按如下形式读取任意文件:

<%= Dir.entries('/') %>
<%= File.open('/example/arbitrary-file').read %>

查找已知的破绽利用

利用服务端模板注入破绽的另一个要害方面是长于查找其余在线资源。一旦你可能辨认正在应用的模板引擎,你应该浏览 web 以查找其他人可能曾经发现的任何破绽。因为一些次要模板引擎的宽泛应用,有时可能会发现有充沛记录的破绽利用,你能够对其进行调整以利用到本人的指标网站。

摸索

此时,你可能曾经在应用文档时偶尔发现了一个可行的破绽利用。如果没有,下一步就是摸索环境并尝试发现你能够拜访的所有对象。

许多模板引擎公开某种类型的 selfenvironment 对象,其作用相似于蕴含模板引擎反对的所有对象、办法和属性的命名空间。如果存在这样的对象,则能够潜在地应用它来生成范畴内的对象列表。例如,在基于 Java 的模板语言中,有时能够应用以下注入列出环境中的所有变量:

${T(java.lang.System).getenv()}

这能够作为创立一个潜在乏味对象和办法的短名单的根底,以便进一步钻研。

开发人员提供的对象

须要留神的是,网站将蕴含由模板提供的内置对象和由 web 开发人员提供的自定义、特定于站点的对象。你应该特地留神这些非标准对象,因为它们特地可能蕴含敏感信息或可利用的办法。因为这些对象可能在同一网站中的不同模板之间有所不同,请留神,你可能须要在每个不同模板的上下文中钻研对象的行为,而后能力找到利用它的办法。

尽管服务端模板注入可能导致近程代码执行和服务器的齐全接管,但在实践中,这并非总是能够实现。然而,仅仅排除了近程代码执行,并不一定意味着不存在其余类型的攻打。你依然能够利用服务端模板注入破绽进行其余高危害性攻打,例如目录遍历,以拜访敏感数据。

结构自定义攻打

到目前为止,咱们次要钻研了通过重用已记录的破绽攻打或应用模板引擎中已知的破绽来构建攻打。然而,有时你须要构建一个自定义的破绽利用。例如,你可能会发现模板引擎在沙盒中执行模板,这会使攻打变得艰难,甚至不可能。

在辨认攻击点之后,如果没有显著的办法来利用破绽,你应该持续应用传统的审计技术,查看每个函数的可利用行为。通过井井有条地实现这一过程,你有时能够构建一个简单的攻打,甚至可能利用于更平安的指标。

应用对象链结构自定义攻打

如上文所述,第一步是标识你有权拜访的对象和办法。有些对象可能会立刻跳进去。通过联合你本人的常识和文档中提供的信息,你应该可能将你想要更彻底地开掘的对象的短名单放在一起。

在钻研对象的文档时,要特地留神这些对象容许拜访哪些办法,以及它们返回哪些对象。通过深刻到文档中,你能够发现能够链接在一起的对象和办法的组合。将正确的对象和办法链接在一起有时容许你拜访最后看起来遥不可及的危险性能和敏感数据。

例如,在基于 Java 的模板引擎 Velocity 中,你能够调用 $class 拜访 ClassTool 对象。钻研文档表明,你能够链式应用 $class.inspect() 办法和 $class.type 属性援用任意对象。在过来,这被用来在指标零碎上执行 shell 命令,如下所示:

$class.inspect("java.lang.Runtime").type.getRuntime().exec("bad-stuff-here")

应用开发人员提供的对象结构自定义攻打

一些模板引擎默认运行在平安、锁定的环境中,以便尽可能地升高相干危险。只管这使得利用这些模板进行近程代码执行变得很艰难,然而开发人员创立的裸露于模板的对象能够提供更进一步的攻击点。

然而,尽管通常为模板内置对象提供了大量的文档,然而网站特定的对象简直基本就没有文档记录。因而,要想晓得如何利用这些破绽,就须要你手动考察网站的行为,以确定攻击点,并据此构建你本人的自定义攻打。

退出移动版