- The Guide to Finding and Reporting Web Vulnerabilities
- About the Author
- About the Tech Reviewer
- Foreword
- Introduction
- Who This Book Is For
- What Is In This Book
- Happy Hacking!
- 1 Picking a Bug Bounty Program
- 2 Sustaining Your Success
- 3 How the Internet Works
- 4 Environmental Setup and Traffic Interception
- 5 Web Hacking Reconnaissance
- 6 Cross-Site Scripting
- 7 Open Redirects
- 8 Clickjacking
- 9 Cross-Site Request Forgery
- 10 Insecure Direct Object References
- 11 SQL Injection
- 12 Race Conditions
- 13 Server-Side Request Forgery
- 14 Insecure Deserialization
- 15 XML External Entity
- 16 Template Injection
- 17 Application Logic Errors and Broken Access Control
- 18 Remote Code Execution
- 19 Same-Origin Policy Vulnerabilities
- 20 Single-Sign-On Security Issues
- 21 Information Disclosure
- 22 Conducting Code Reviews
- 23 Hacking Android Apps
- 24 API Hacking
- 25 Automatic Vulnerability Discovery Using Fuzzers
Hunting for Template Injection
As with hunting for many other vulnerabilities, the first step in finding template injections is to identify locations in an application that accept user input.
与寻找其他漏洞一样,寻找模板注入的第一步是识别应用程序中接受用户输入的位置。
Step 1: Look for User-Input Locations
Look for locations where you can submit user input to the application. These include URL paths, parameters, fragments, HTTP request headers and body, file uploads, and more.
寻找可以向应用程序提交用户输入的位置。这些位置包括 URL 路径、参数、片段、HTTP 请求头部和主体、文件上传等。
Templates are typically used to dynamically generate web pages from stored data or user input. For example, applications often use template engines to generate customized email or home pages based on the user’s information. So to look for template injections, look for endpoints that accept user input that will eventually be displayed back to the user. Since these endpoints typically coincide with the endpoints for possible XXS attacks, you can use the strategy outlined in Chapter 6 to identify candidates for template injection. Document these input locations for further testing.
模板通常用于从存储的数据或用户输入动态生成网页。例如,应用程序通常使用模板引擎根据用户信息生成定制的电子邮件或主页。因此,要寻找模板注入,请寻找接受用户输入并最终显示回用户的端点。由于这些端点通常与可能的 XXS 攻击端点重叠,因此您可以使用第 6 章中概述的策略来识别模板注入的候选项。记录这些输入位置以进行进一步测试。
Step 2: Detect Template Injection by Submitting Test Payloads
Next, detect template injection vulnerabilities by injecting a test string into the input fields you identified in the previous step. This test string should contain special characters commonly used in template languages. I like to use the string {{1+abcxx}}${1+abcxx}<%1+abcxx%>[abcxx]
because it’s designed to induce errors in popular template engines. ${...}
is the special syntax for expressions in the FreeMarker and Thymeleaf Java templates; {{...}}
is the syntax for expressions in PHP templates such as Smarty or Twig, and Python templates like Jinja2; and <%= ... %>
is the syntax for the Embedded Ruby template (ERB). And [
random expression ]
will make the server interpret the random expression as a list item if the user input is placed into an expression tag within the template (we will discuss an example of this scenario later).
接下来,通过向先前识别出的输入字段注入测试字符串,检测模板注入漏洞。这个测试字符串应该包含常用模板语言中的特殊字符。我喜欢使用字符串{{1+abcxx}}${1+abcxx}<%1+abcxx%>[abcxx],因为它被设计为在流行的模板引擎中导致错误。${...} 是 FreeMarker 和 Thymeleaf Java 模板中表达式的特殊语法;{{...}} 是 PHP 模板(如 Smarty 或 Twig)和 Python 模板(如 Jinja2)中表达式的语法;<%= ... %> 是 Embedded Ruby 模板(ERB)中表达式的语法。而 [random expression] 则会使服务器将用户输入放入模板的表达式标记内并将其解释为列表项(稍后我们将讲述这种情况的一个例子)。
In this payload, I make the template engine resolve the variable with the name abcxx
, which probably has not been defined in the application. If you get an application error from this payload, that’s a good indication of template injection, because it means that the special characters are being treated as special by the template engine. But if error messages are suppressed on the server, you need to use another method to detect template injection vulnerabilities.
在这个有效载荷中,我让模板引擎解析名称为 abcxx 的变量,这个变量可能没有在应用程序中定义。如果你从这个有效载荷中得到应用程序错误,这是一个很好的模板注入指示,因为这意味着特殊字符被模板引擎视为特殊字符。但是,如果服务器抑制错误消息,你需要使用另一种方法来检测模板注入漏洞。
Try providing these test payloads to the input fields ${7*7}
, {{7*7}}
, and <%= 7*7 %>
. These payloads are designed to detect template injection in various templating languages. ${7*7}
works for the FreeMarker and Thymeleaf Java templates; {{7*7}}
works for PHP templates such as Smarty or Twig, and Python templates like Jinja2; and <%= 7*7 %>
works for the ERB template. If any of the returned responses contain the result of the expression, 49, it means that the data is being interpreted as code by the template engine:
尝试将这些测试载荷提供给输入字段$ {7 * 7},{{7 * 7}}和<%= 7 * 7 %>。这些载荷旨在检测各种模板语言中的模板注入。 $ {7 * 7}适用于 FreeMarker 和 Thymeleaf Java 模板; {{7 * 7}}适用于 PHP 模板,如 Smarty 或 Twig,以及 Python 模板,如 Jinja2;并且<%= 7 * 7 %>适用于 ERB 模板。如果返回的任何响应都包含表达式结果 49,则表示模板引擎正在将数据解释为代码:
GET /display_name?name={{7*7}}
Host: example.com
While testing these endpoints for template injections, keep in mind that successful payloads don’t always cause results to return immediately. Some applications might insert your payload into a template somewhere else. The results of your injection could show up in future web pages, emails, and files. A time delay also might occur between when the payload is submitted and when the user input is rendered in a template. If you’re targeting one of these endpoints, you’ll need to look out for signs that your payload has succeeded. For example, if an application renders an input field unsafely when generating a bulk email, you will need to look at the generated email to check whether your attack has succeeded.
在测试这些端点时防注入模板,请注意成功的有效负载并不总是立即返回结果。有些应用程序可能会将您的有效负载插入到其他地方的模板中。您的注入结果可能会在未来的网页、电子邮件和文件中显示。在有效负载提交后和用户输入在模板中呈现之间,可能会发生时间延迟。如果您正在针对其中之一的端点,则需要注意您的有效负载是否成功。例如,如果应用程序在生成批量电子邮件时不安全地呈现输入字段,则需要查看生成的电子邮件以检查攻击是否成功。
The three test payloads ${7*7}
, {{7*7}}
, and <%= 7*7 %>
would work when user input is inserted into the template as plaintext, as in this code snippet:
三个测试载荷 ${7*7}, {{7*7}}, 和 <%= 7*7 %> 当用户输入被插入模板中作为纯文本时将能够工作,就像这段代码片段中一样:
from jinja2 import Template
tmpl = Template("
<html><h1>The user's name is: " + user_input + "</h1></html>")print(tmpl.render())
But what if the user input is concatenated into the template as a part of the template’s logic, as in this code snippet?
但如果用户输入被连接到模板中并作为模板逻辑的一部分,如此代码片段所示,情况会怎样?
from jinja2 import Template
tmpl = Template("
<html><h1>The user's name is: {{" + user_input + "}}</h1></html>")print(tmpl.render())
Here, the user input is placed into the template within expression tags {{...}}
. Therefore, you do not have to provide extra expression tags for the server to interpret the input as code. In that case, the best way to detect whether your input is being interpreted as code is to submit a random expression and see if it gets interpreted as an expression. In this case, you can input 7*7
to the field and see if 49
gets returned:
在这里,用户输入会被放置在表达式标签{{...}}中的模板中,因此您不必为服务器提供额外的表达式标签来解释输入为代码。在这种情况下,检测您的输入是否被解释为代码的最佳方法是提交一个随机表达式,并查看它是否被解释为表达式。在这种情况下,您可以将 7 * 7 输入到字段中并查看是否返回了 49:
GET /display_name?name=7*7
Host: example.com
Step 3: Determine the Template Engine in Use
Once you’ve confirmed the template injection vulnerability, determine the template engine in use to figure out how to best exploit that vulnerability. To escalate your attack, you’ll have to write your payload with a programming language that the particular template engine expects.
确认模板注入漏洞后,确定使用的模板引擎以找出最佳利用方式。为了升级攻击,您需要使用特定模板引擎期望的编程语言编写有效载荷。
If your payload caused an error, the error message itself may contain the name of the template engine. For example, submitting my test string {{1+abcxx}}${1+abcxx}<%1+abcxx%>[abcxx]
to our example Python application would cause a descriptive error that tells me that the application is using Jinja2:
如果你的载荷导致了错误,错误信息本身可能包含模板引擎的名称。例如,将我的测试字符串{{1+abcxx}}${1+abcxx}<%1+abcxx%>[abcxx]提交到我们的示例 Python 应用程序中,将引起一个详细的错误,告诉我应用程序正在使用 Jinja2:
jinja2.exceptions.UndefinedError: 'abcxx' is undefined
Otherwise, you can figure out the template engine in use by submitting test payloads specific to popular template languages. For example, if you submit <%= 7*7 %>
as the payload and 49
gets returned, the application probably uses the ERB template. If the successful payload is ${7*7}
, the template engine could either be Smarty or Mako. If the successful payload is {{7*7}}
, the application is likely using Jinja2 or Twig. At that point, you could submit another payload, {{7*'7'}}
, which would return 7777777
in Jinja2 and 49
in Twig. These testing payloads are taken from PortSwigger research: https://portswigger.net/research/server-side-template-injection/ .
否则,你可以通过提交特定于流行模板语言的测试载荷来确定模板引擎的使用情况。例如,如果您提交 <%= 7*7 %> 作为载荷并返回 49,则该应用程序可能使用 ERB 模板。如果成功的负载是 $ {7*7},则模板引擎可能是 Smarty 或 Mako。如果成功的负载是 {{7*7}},则应用程序可能使用 Jinja2 或 Twig。在那时,您可以提交另一个负载{{7□7},它将在 Jinja2 中返回 7777777,在 Twig 中返回 49。这些测试载荷来自 PortSwigger 研究:https://portswigger.net/research/server-side-template-injection/。
Many other template engines are used by web applications besides the ones I’ve talked about. Many have similar special characters designed not to interfere with normal HTML syntax, so you might need to perform multiple test payloads to definitively determine the type of template engine you are attacking.
除了我所提到的模板引擎,许多其他网络应用程序也在使用。许多模板引擎都使用类似的特殊字符,以设计不会干扰正常的 HTML 语法,因此您可能需要执行多个测试负载以明确确定要攻击的模板引擎的类型。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论