pikachu靶场通关笔记30 文件包含01之本地文件包含
目录
一、文件包含功能
二、文件包含Vulnerability
二、本地文件包含
三、文件包含探测
1、file1.php
2、file2.php
3、file6.php
四、源码分析
五、渗透实战
1、获取敏感信息win.ini
2、获取敏感信息hosts
本系列为《pikachu靶场通关笔记》渗透实战,本文通过对文件包含关卡(File Inclusion)源码的代码审计找到产生缺陷的真实原因,讲解本地文件包含关卡的原理并进行渗透实践。
一、文件包含功能
文件包含是文件操作的一个基本功能。在各种开发语言中都提供了内置的文件包含函数,其可以使开发人员在一个代码文件中直接包含(引入)另外一个代码文件。 比如 在PHP中,提供了如下函数实现文件包含功能。
include()
include_once()
require()
require_once()
这些文件包含函数,这些函数在代码设计中被经常使用到。
二、文件包含
文件包含Vulnerability(File Inclusion Vulnerability)通常发生在服务器端的脚本语言(如PHP、Java等)中。当应用程序在运行时动态地包含一个文件,而文件路径或名称是由用户输入控制的,且没有进行严格的过滤和验证时,攻击者就可能通过构造恶意的文件路径或URL,让应用程序包含一个非预期的文件(如服务器上的敏感文件或攻击者上传的恶意文件),从而实现恶意目的。
三、本地文件包含
本地文件包含(Local File Inclusion,LFI)主要出现在服务器端脚本语言中。当应用程序通过用户输入动态地包含本地服务器上的文件时,如果未对输入进行严格过滤和验证,攻击者可以通过构造路径(如../../../../etc/passwd
)来访问服务器上的敏感文件。
文件包含安全风险分为本地文件包含和远程文件包含,两者区别如下所示。
对比项 | 本地文件包含(LFI) | 远程文件包含(RFI) |
---|---|---|
包含文件位置 | 本地系统内的文件,像/etc/passwd 、config.php 等。 | 来自远程服务器上的文件。 |
服务器配置需求 | 一般无特殊配置要求。 | 服务器要开启allow_url_fopen 和allow_url_include 选项。 |
攻击方式 | 攻击者构造特殊的本地文件路径,让应用程序包含本地敏感文件,以此获取系统信息。 | 攻击者把恶意文件上传到远程服务器,再让应用程序包含该远程文件,进而执行恶意代码。 |
危害程度 | 通常危害相对较小,主要是信息泄露,如系统配置、用户信息等的泄露。 | 危害较大,攻击者可上传并执行恶意脚本,直接控制服务器。 |
防御难度 | 相对容易防御,通过对用户输入的本地路径严格验证,使用白名单机制等可有效防范。 | 防御较难,除了验证输入,还需严格配置服务器,禁用不必要的远程文件包含功能。 |
三、文件包含探测
1、file1.php
进入pikachu靶场的本地文件包含关卡,完整URL地址如下所示。
http://127.0.0.1/pikachu/vul/fileinclude/fi_local.php
进入了一个可以查询NBA player的页面,具体如下所示。
选择第一个运动员科比,URL中的参数多出了filename=file1.php,如下所示。
http://127.0.0.1/pikachu/vul/fileinclude/fi_local.php?filename=file1.php&submit=%E6%8F%90%E4%BA%A4#
我们在网址栏很容易就看到返回的信息,结果发现打开的是本地文件fiel1.php。
2、file2.php
选择第二个运动员Allen Iverson (Allen Iverson),URL中的参数多出了filename=file2.php,如下所示。
http://127.0.0.1/pikachu/vul/fileinclude/fi_local.php?filename=file2.php&submit=%E6%8F%90%E4%BA%A4#
我们在网址栏很容易就看到返回的信息,结果发现打开的是本地文件fiel2.php,猜测这里其他文件名可能也是个filex.php(x是数字)的格式。
表示我们可以通过修改URL中的filename参数进行渗透。首先,由于观察到上图的filename是file2.php,把5个NBA球星都选一遍,发现文件名确实是file1.php~file5.php。
3、file6.php
我们可以通过修改URL中的filename参数进行渗透,将filename改为file6.php,完整的URL地址如下所示。
http://127.0.0.1/pikachu/vul/fileinclude/fi_local.php?filename=file6.php&submit=%E6%8F%90%E4%BA%A4#
接下来我们看到了一个隐藏页面,提示“here is a secret box!admin/admin,kobe/123456”具体如下所示。
四、源码分析
根据第三部分探测效果,我们得知文件包含的源文件为fi_local.php,具体代码如下所示。
这段代码主要功能是根据用户通过 GET 请求传递的参数来实现文件包含操作,经过详细注释的源码如下所示。
// 初始化一个空的字符串变量 $html,可能后续用于存储 HTML 内容,但在这段代码中未使用
$html='';// 检查是否通过 GET 方法提交了表单,并且 $_GET['filename'] 不为空
if(isset($_GET['submit']) && $_GET['filename']!=null){// 如果条件满足,将 $_GET['filename'] 的值赋给变量 $filename$filename=$_GET['filename'];// 直接将用户输入的 $filename 拼接到 "include/" 路径后进行文件包含操作// 这里没有对用户输入的 $filename 做任何安全限制include "include/$filename";// 以下是安全的写法示例,使用白名单机制// 只有当 $filename 的值为 'file1.php'、'file2.php'、'file3.php'、'file4.php' 或 'file5.php' 时,才会进行文件包含操作// if($filename=='file1.php' || $filename=='file2.php' || $filename=='file3.php' || $filename=='file4.php' || $filename=='file5.php'){// include "include/$filename";// }
}
这段代码存在本地文件包含安全风险,主要原因在于没有对用户输入的 $filename
进行严格的安全验证和过滤,具体体现在以下方面:
-
用户可控输入:
$filename
变量的值直接来源于用户通过 GET 请求传递的filename
参数。攻击者可以自由构造这个参数的值。 -
无输入验证:代码没有对
$filename
的值进行任何验证,例如没有检查其是否为合法的文件名,是否包含恶意字符等。 -
可包含任意本地文件:由于没有验证,攻击者可以通过构造特殊的文件名,如
../../etc/passwd
(在 Linux 系统中),利用目录遍历技巧,突破include
目录的限制,包含系统中的任意敏感文件,从而导致信息泄露。
五、渗透实战
1、获取敏感信息win.ini
我们可以通过修改URL中的filename参数进行渗透,将filename改为../../../../../../windows/win.ini,完整的URL地址如下所示渗透成功。
filename=../../../../../../windows/win.ini
2、获取敏感信息hosts
接下来将filename改为../../../../../../windows/system32/drivers/etc/hosts进行渗透,完整的URL地址如下所示渗透成功。
filename=../../../../../../windows/system32/drivers/etc/hosts