是否可以绕过file_get_contents参数的附加文件后缀? [英] Can an appended file suffix to a parameter for file_get_contents be bypassed?

查看:416
本文介绍了是否可以绕过file_get_contents参数的附加文件后缀?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码

<?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);

我们都知道(至少我希望如此),绝对路径绝对不是足够的表示要避免离开给定的路径-只需在查询字符串中插入一个或多个 ../ 即可到达文件系统上的任何路径。

We all know (at least I hope so) that prepending an absolute path is by no way an adequate mean to prevent leaving the given path - one can simply insert one or more "../"s to the query string to reach any path on the file system.

我的问题是:与给定的示例类似,也可以在 $ _ GET ['filename'] 中进行操作这样也可以绕过给定扩展名后缀的方式,即回显了.txt以外的文件?我特别想到某些控制字符以与 ../ 相同的方式绕过前缀。

My question is: Analogously to the given example, can $_GET['filename'] also be manipulated in such a way that the given extension suffix can be bypassed as well, i.e. a file other than .txt is echoed? I'm especially thinking of certain control characters that bypass the appended file extension in the same fashion as ../ does with the prefix.

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

I tried adding some control characters (e.g. ASCII code 127 for delete) to the query string or concatenating two filenames by using &&, | or >, but all to no avail and I wondered if there exists such a possibility at all.

(顺便说一句,我想补充一点,这个问题并不是出于开发系统的目的而提出的。这纯粹是我最近想到的一个假设问题。) / p>

(Btw, I'd like to add the note that this questions is not asked for the purpose to exploit a system. It's purely a hypothetical question that came across my mind recently.)

推荐答案

当然, nullbyte \ 0 (如果要在查询字符串中进行测试,则为%00 ),将具有 file_get_contents()遇到字符串时停止处理。

Sure, the nullbyte, \0 (or %00 if you want to test in a query-string), will have file_get_contents() stop processing the string when it hits it.

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

So, if $_GET['filename'] is ../../../../../etc/passwd%00 (such as your_page.php?filename=../../../../etc/passwd%00), file_get_contents() will never see the ending .txt (it will see it, but won't process it).

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

Sadly, sprintf does not strip the nullbyte when building your string. I'm not sure about other control characters, but if anything - I would always recommend to strip the nullbyte. However, a more intuitive approach would be to build a whitelist of allowed characters and perform a preg_match() against the input.

单单,可以使用PHP的 realpath() 放在生成的字符串上,它将确定实际访问的完整路径。
因此, / absolute / path /../../../../ etc / passwd\0.txt 传递给 realpath()将返回 / etc / passwd 。然后,您可以对返回的值进行进一步的验证(例如,扩展名是否仍然是 .txt 还是位于指定/必需的目录中)。

Going one-up on that one, you can use PHP's realpath() on the built string and it will determine the full path that is really being accessed. So, /absolute/path/../../../../etc/passwd\0.txt, passed to realpath() will return /etc/passwd. You can then do further validation on the returned value (such as, is the extension still .txt or is it within a specified/required directory).

这篇关于是否可以绕过file_get_contents参数的附加文件后缀?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆