文件包含通过哪个语言学的,php文件包含原理和伪协议利用,有没有了解过Java里的文件包含漏洞?
1 个回答
如果无能为力,那就顺其自然。如果心无所待,那就随遇而安。林雷# 我最早从哪学到文件包含 最早是在 **PHP** 里接触到文件包含(`include/require`),因为它把“把路径字符串交给解释器去打开并执行/输出”的能力暴露给了应用层;如果路径来自用户输入且缺少白名单校验,极易演化成 **LFI/RFI(本地/远程文件包含)** 类漏洞。 # PHP:文件包含原理 & 常见伪协议(安全视角) ## 原理(为什么会出问题) * `include/require` 接受一个**字符串路径** → 打开对应“流”(文件/URL/内存等),再**输出或执行**读取到的内容。 * 两个关键开关: * `allow_url_fopen / allow_url_include`:是否允许把 URL 当文件读/包含(远程包含风险点)。 * `open_basedir / secure_mode`(历史配置):约束可访问路径范围。 * 一旦**路径可控**(例如 `?page=about.php` 这类参数被直接拼到 `include` 上),就可能被滥用为任意文件读取/执行的入口。 ## 常见 stream wrapper(“伪协议”)与安全影响(示意性说明) > 这些 wrapper 是 PHP 官方提供的“统一资源流”机制,**本身不是漏洞**;风险来自把**未校验的用户输入**直接交给 `include/require`/`file_get_contents` 等 I/O API。 * `file://` 本地文件访问:可被用来**读取敏感文件**(如配置、源码)。 * `php://filter` 过滤器:常用来**以转换方式读取源文件**(如 base64 编码后输出源码,绕开直接执行),用于信息泄露。 * `data://` 内联数据流:可将**内联内容**作为“文件”喂给包含函数;若可执行上下文可达,可能导致执行内联代码。 * `phar://` 压缩/归档流 + **反序列化副作用**:许多文件函数在处理 `phar://` 时会触发 **反序列化元数据**,在存在 gadget 的项目里可能升级为 RCE(与“反序列化链”相关)。 * `zip://`、`rar://` 等归档访问:用于读取归档中的条目;路径可控时可读任意资源。 * `http/https/ftp://` 远程 URL:若 `allow_url_include=On`,会把远程资源当 PHP 包含,是典型 **RFI** 场景(强烈不建议在生产开启)。 * `php://input`(旧版本场景):历史上可直接作为输入流读取请求体;与包含函数结合会放大风险(新版本默认不会被当代码执行)。 > 防护点(PHP) > > * **永远不要**把**用户输入**直接拼到 `include/require`/`include_once`。 > * 只允许**白名单映射**:`$page = ALLOWED[$param] ?? '404.php'`,不要直接拼路径;或将**枚举值→固定模板**。 > * 关闭远程包含:`allow_url_include=Off`(默认 Off),谨慎使用 `allow_url_fopen`。 > * 路径约束:`open_basedir`、`chroot`、容器隔离;读取前 `realpath()` 并校验**必须位于受信目录**。 > * 对“只读文件”的功能,用**读取 API**而不是 `include`(避免把内容当代码执行)。 > * 审计对 `phar://` 的触发点(任意文件函数都可能触发元数据解析),升级依赖,限制上传/文件可控点。 # Java:有没有“文件包含”漏洞?有什么等价风险 Java 没有像 PHP 那样“把字符串路径交给解释器执行为代码”的常规语义,**典型的“远程代码包含”在 Java 里并不常见**。但仍有几类**功能等价或效果相近**的风险: ## 1) 视图/模板“包含”可控 → 任意文件读取/模板包含 * **JSP / Servlet**:`RequestDispatcher#include/forward`、`<jsp:include page="${param.p}">`、JSTL `<c:import url="${param.u}">` * 结果:若参数可控,可能读取/包含任意资源(含 `/WEB-INF/**`),或引出 **SSRF**(对外部 URL)。 * **模板引擎**:Thymeleaf / FreeMarker / Velocity 等若把模板名从用户输入拼接,可能造成**任意模板包含**,在某些错误配置下升级为 **SSTI**(模板表达式执行)。 **防护**: * 视图名/模板名**白名单枚举**,不要拼接路径; * 视图解析器(如 `InternalResourceViewResolver`)限制 `viewNames` 模式; * 对 `<c:import>` 这类 URL 导入关闭对外网访问或使用 SSRF 允许名单。 ## 2) 任意文件读取 / 路径穿越 * 任何基于 `FileInputStream`、`Files.newInputStream`、`ResourceLoader#getResource(userInput)`、`ClassPathResource(userInput)` 的**用户可控路径读取**,都可能演化成 **目录穿越(`../`)** → 读取任意文件(源码、秘钥、配置)。 * 某些历史 CVE(如某些静态资源处理器路径规范化缺陷)也属于这一类。 **防护**: * `Paths.get(base, userInput).normalize()` + 校验**必须以受信前缀开头**; * 将“可读目录”绑定为**不可写**并最小化权限; * 统一用 `ServletContext.getResourceAsStream`/受控 ResourceResolver 访问受限路径,不直接放行磁盘路径。 ## 3) 脚本/模板执行引擎误用 → 代码执行 * 引入 **Groovy/JRuby/JS(nashorn/graaljs)** 等脚本引擎,若**从用户可控路径**载入脚本再执行,本质上就是“包含并执行”外来代码。 * 模板引擎 **SSTI**(如 FreeMarker、Velocity 早期不安全用法)可演化为 RCE。 **防护**: * 禁止用户可控路径直接驱动脚本/模板解析; * 生产禁用动态语言引擎或开启沙箱; * 模板引擎开启安全模式/移除危险对象暴露。 ## 4) 其他相关:JNDI/反序列化并非“文件包含”,但常被混淆 * JNDI 注入、反序列化链属于**远程代码加载/执行**范畴,不是“包含文件”,但在“动态加载不受控”这一点上本质相近。 # 面试可用的精简总结 * **我是在 PHP 里最早系统性地接触到文件包含**:`include/require` 把路径当流读取并可能执行,若用户可控会出现 LFI/RFI。常见 wrapper 如 `php://filter`(读取源码)、`data://`(内联数据)、`phar://`(触发元数据反序列化)、`http(s)://`(在配置开启时导致远程包含)。 * **Java 没有典型的远程代码包含语义**,但存在“**模板/视图包含**、**任意文件读取/路径穿越**、**脚本引擎加载**”等等价风险。 * **我的做法**:严格白名单映射(模板/视图)、路径规范化+前缀校验(文件读取)、禁用远程包含/限制 wrapper(PHP)、最小化进程文件权限、关闭/沙箱化动态执行能力,并通过 SCA/IAST/代码审计工具(如 Sonar、Semgrep、Burp 的扫描器)例行巡检。发布于 2025-08-13 02:11 •IP属地 湖北举报评论收藏
公众号进入网站体验更佳

