1. 文件包含漏洞:一个被低估的“后门”
很多刚入门Web安全的朋友,可能对SQL注入、XSS跨站脚本这些名词耳熟能详,但一提到“文件包含漏洞”,总觉得它有点神秘,甚至觉得危害不大。这其实是一个巨大的误解。在我过去处理过的众多安全事件里,由文件包含漏洞引发的“惨案”比比皆是,它就像一个隐藏在代码深处的“后门”,一旦被攻击者发现并利用,往往能直接拿到服务器的控制权,后果非常严重。
简单来说,文件包含漏洞就是Web应用程序在引入(包含)其他文件时,由于对文件路径的控制不严,导致攻击者可以“指哪打哪”,让程序去加载并执行一个本不该被加载的文件。想象一下,你家的智能门锁(Web程序)本来只认你录入的指纹(指定的文件),但现在锁的识别逻辑出了问题,别人随便拿个东西(比如一张照片)往上一按,门就开了,甚至还能让锁去把隔壁家的门也打开。文件包含漏洞就是这么回事。
PHP之所以成为这个漏洞的重灾区,是因为它天生就提供了非常灵活的文件包含功能,比如 include 和 require 这些函数,初衷是为了让代码更模块化、更好维护。但很多开发者在追求开发效率时,忽略了安全性,直接把用户可控的数据(比如URL参数、Cookie、表单数据)拼接到文件路径里,这就埋下了祸根。攻击者不需要懂高深的加密破解,只需要在浏览器地址栏里“精心”构造一个URL,就可能读取服务器的敏感配置文件、日志,甚至上传一个木马后门,让整个服务器沦陷。接下来,我们就一层层剥开它的外衣,看看这个漏洞到底是怎么运作的。
2. 核心原理:为什么include和require会成为突破口?
要理解漏洞,得先明白这些函数是怎么工作的。PHP里的 include、require 以及它们的 _once 版本,本质都是一个“代码加载器”。当脚本执行到这些语句时,PHP解释器会暂停当前文件的执行,转去读取并执行指定路径文件中的代码,执行完毕后再回来继续。这就像导演在拍戏时,突然喊“卡,把第XX号道具剧本拿过来,把里面的戏份插到这里演一遍”。
关键的危险点在于:这个“文件路径”变量,开发者常常让它变得“可控”。
看一段最经典的漏洞代码:
<?php
$page = $_GET['page']; // 直接从URL参数获取文件名
include('/pages/' . $page . '.php'); // 拼接后包含
?>
开发者的本意可能是好的:通过 ?page=home 来加载 /pages/home.php 页面。但攻击者的思维不会这么规矩。如果传入 ?page=../../../../etc/passwd 呢?在Linux系统上,/etc/passwd 是存储用户账户信息的关键文件。经过路径拼接,程序试图去包含 /pages/../../../../etc/passwd,其中的 ../ 会向上回退目录,最终很可能就定位到了根目录下的 /etc/passwd 文件。
更糟糕的是,PHP包含文件时,并不在乎被包含文件的扩展名是不是 .php。它会尝试将文件内容当作PHP代码来解析。如果文件里没有 <?php ... ?> 标签,它就会直接把文件内容原样输出。这就导致了敏感信息泄露:配置文件、数据库连接字符串、日志文件,都能被一览无余。
include 和 require 的主要区别在于错误处理。include 出错时(比如文件不存在),会抛出一个警告(Warning),但脚本会继续执行。require 出错时,则会产生一个致命错误(Fatal Error),脚本会立即停止。从安全角度看,这没有本质区别,漏洞该有的都有。而 include_once 和 require_once 只是加了个“只包含一次”的检查,防止重复包含导致函数重定义等问题,同样无法阻止恶意文件的首次包含。
所以,漏洞产生的根源就两点:1. 文件路径变量用户可控;2. 可控变量未经严格过滤和校验。攻击者利用的,正是这份不该有的“自由”。
3. LFI(本地文件包含)实战:不只是读文件那么简单
本地文件包含(LFI)是实战中最常见的类型。很多人以为LFI就是“读文件漏洞”,能看看 /etc/passwd 就了不起了。这种想法太天真了,LFI的利用深度远超你的想象。
3.1 基础利用:目录遍历与敏感文件读取
这是最直接的利用方式。攻击者通过 ../ 这样的目录遍历符号

:从原理到实战防御&spm=1001.2101.3001.5002&articleId=151879356&d=1&t=3&u=29671c805632482397c0c5d8338594ff)
500

被折叠的 条评论
为什么被折叠?



