php - 是否可以绕过 file_get_contents 参数的附加文件后缀?

标签 php security code-injection

考虑以下代码

<?php
// warning: this code is unsafe and for demonstrational purposes only,
// do not use in a production environment
$filename = $_GET['filename']; 
$extension = 'txt';
$path = '/absolute/path';
$fullFilename = sprintf('%s/%s.%s', $path, $filename, $extension);
echo file_get_contents($fullFilename);

我们都知道(至少我希望如此),前置绝对路径绝不是防止离开给定路径的充分手段 - 人们可以简单地插入一个或多个“../ "s 到查询字符串以到达文件系统上的任何路径。

我的问题是:与给定的示例类似,$_GET['filename'] 是否也可以以绕过给定扩展名后缀的方式进行操作,即回显 .txt 以外的文件?我特别想到某些控制字符会绕过附加的文件扩展名,其方式与 ../ 使用前缀的方式相同。

我尝试在查询字符串中添加一些控制字符(例如用于删除的 ASCII 代码 127),或使用 &&|>< 连接两个文件名,但一切都无济于事,我想知道是否存在这种可能性。

(顺便说一句,我想补充一点,提出这个问题并不是为了利用系统。这纯粹是我最近想到的一个假设问题。)

最佳答案

当然,nullbyte\0(如果您想在查询字符串中测试,则为 %00)将具有 file_get_contents() 当字符串命中时停止处理它。

因此,如果 $_GET['filename']../../../../../etc/passwd%00 (例如如 your_page.php?filename=../../../../etc/passwd%00),file_get_contents() 永远不会看到结尾 .txt(它会看到它,但不会处理它)。

遗憾的是,sprintf 在构建字符串时不会去除空字节。我不确定其他控制字符,但如果有的话 - 我总是建议删除空字节。不过,更直观的方法是构建允许字符的白名单,并对输入执行 preg_match()

再进一步,您可以使用 PHP 的 realpath()在构建的字符串上,它将确定真正被访问的完整路径。 因此,传递给 realpath()/absolute/path/../../../../etc/passwd\0.txt 将返回 /etc/passwd.然后,您可以对返回的值进行进一步验证(例如,扩展名是否仍为 .txt 或者是否位于指定/所需的目录中)。

关于php - 是否可以绕过 file_get_contents 参数的附加文件后缀?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12731547/

相关文章:

security - 使用 shell 脚本进行 CGI 编程

ios - 注入(inject) III : Interposable conflict with BitCode

.net - 将代码注入(inject)正在运行的 WPF 应用程序的最佳方法

python - 如何向第三方模型注入(inject)多对多关系?

PHP 输出包含两个空格,即使没有找到结果

security - HTTP 摘要认证

java - 沙盒 Java/Groovy/Freemarker 代码 - 防止执行特定方法

php - MySQL varchar 在 PHP 中具有换行符和有效的 LIKE 子句

php - 什么是 php v8js 中的扩展?

javascript - 当我运行 npm start 时,我在 ubuntu 16.04 中收到 npm 错误