Can an appended file suffix to a parameter for file_get_contents be bypassed?

亡梦爱人 提交于 2019-12-11 01:37:55

问题


Consider the following code

<?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.

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.

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.

(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.)


回答1:


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.

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).

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.

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).



来源:https://stackoverflow.com/questions/12731547/can-an-appended-file-suffix-to-a-parameter-for-file-get-contents-be-bypassed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!