Files
Sec-Interview/Chapter13/13-5.md
T
2025-09-25 03:54:33 +08:00

34 lines
1.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
### PHP 的 %00 截断的原理
当 PHP 脚本在调用某些文件操作函数(如 `include()``require()``file_get_contents()` 等)时,底层会调用 C 语言的库函数。在 C 语言中,字符串是以**空字节(null byte)**作为结束符的,即十六进制的 `0x00`。当 C 语言函数读取到 `0x00` 时,就会认为字符串已经结束
而 PHP 脚本在处理用户输入时,并不会像 C 语言那样将 `%00` 解析为空字节,它会将其当作普通的字符串。但是,当这个字符串被传入底层 C 语言函数进行文件操作时,C 语言会截断这个字符串,只处理 `%00` 之前的部分
假设服务器上有一个 PHP 脚本,其代码如下:
```php
<?php
$file = $_GET['file'];
include($file . ".php");
?>
```
这段代码的本意是让用户通过 `file` 参数指定一个文件名,然后脚本会在文件名后面自动加上 `.php` 后缀,再包含这个文件
现在,如果攻击者想要利用这个漏洞来包含一个图片文件 `shell.jpg`(其中包含恶意 PHP 代码),他可以构造一个带有 `%00` 截断的 URL
```
http://example.com/index.php?file=shell.jpg%00
```
当 PHP 脚本接收到这个 URL 时:
1. **PHP 层**
- `$file` 的值是 `shell.jpg%00`
- `$file . ".php"` 拼接后的字符串是 `shell.jpg%00.php`
2. **C 语言底层**
-`include()` 函数将 `shell.jpg%00.php` 这个字符串传递给底层的 C 语言文件操作函数时,C 语言会把 `%00` 识别为空字节(`\0`
- 根据 C 语言的字符串处理规则,它会认为字符串在 `shell.jpg` 处就已经结束了
- 最终,操作系统实际打开的文件名是 `shell.jpg`,而不是 `shell.jpg.php`
这样一来,攻击者就成功绕过了 `.php` 后缀的限制,实现了对 `shell.jpg` 的文件包含,从而执行了图片中的恶意代码