1

I'm taking a course on software security and have been presented with the following scenario:

PHP CODE RUNNING ON SERVER:

<?php 
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=response.txt");
    readfile($_GET['file']."/remove/this.txt");
?>

I need to know if this can be exploited to get an arbitrary file on the server (other than */remove/this.txt).

I tried using null byte (%00) but it's not working (the apache server is running PHP 5.3 on Ubuntu).

I also tried to get creative with php://filter, php://input, etc and nothing. The problem here is that the last part of the instruction is the resource.

Path truncation doesn't seem to work either. For now the only thing I can do is read URL's using ?var=...

Lorenzo Wills
  • 11
  • 1
  • 5
  • I just analyzed the implementation. If there's any NUL-byte in the string, it'll fail. Apart from that, there's no chance. The only thing where you could have had a chance is with `php://filter`; the dumb part about it is that the `/resource=` part needs to be at the end of the string... The only critical thing is that an attacker could access servers usually not exposed to the external network. (via e.g. `http://`) – bwoebi Sep 30 '14 at 17:24
  • @bwoebi exactly, you understood the problem perfectly, thought I'm not ready to give up yet. For example, I was playing around and found out that in Windows "\\localhost -xxx/whatevertext" yields the same result as "\\localhost"; this doesn't solve anything for us obviously, but my point is that if we look hard and get creative we just might find something. – Lorenzo Wills Sep 30 '14 at 17:39
  • Did you try [`expect://`](http://php.net/wrappers.expect)? Maybe it’s installed. – Gumbo Sep 30 '14 at 17:53
  • @Gumbo very clever, but it's giving me the following: "Warning: readfile(): Unable to find the wrapper "expect" - did you forget to enable it when you configured PHP?" – Lorenzo Wills Sep 30 '14 at 18:03
  • 1
    @LorenzoWills https://github.com/php/php-src/commit/32b5f8a1a3552f48d6e91c17b6d9d441c665a44d ... that commit introduced that check, but it is 5.4 (and newer) only. You say you're running php 5.3, so, the NUL-byte thing should work I'd think?? – bwoebi Sep 30 '14 at 18:36
  • @bwoebi it was fixed in 5.3.4 and my server is running 5.3.10. [PHP 5.3.4 Release Notes](http://php.net/releases/5_3_4.php) – Lorenzo Wills Sep 30 '14 at 18:54
  • @LorenzoWills okay, then seems php 5.3 and 5.4 got different fixes. sorry for being wrong ;-) – bwoebi Sep 30 '14 at 19:01
  • On the contrary @bwoebi, thanks for your help – Lorenzo Wills Sep 30 '14 at 19:53

1 Answers1

2

I just ran a simple test and can say there isn't a single character exploit for this that would chop off the last filename part. Example:

<pre>
<?php

for($i=0;$i<=255;$i++){
    $chr = chr($i);

    readfile("B.txt{$chr}A.txt");
}

Created a file called A.txt that is the standard file and B.txt that is the target file. Put something noticeable in each file so you know when it was read (I already had the files for something else and there was a different list of like 100 items in each).

There wasn't a single character exploit on my system which is RHEL6. The obvious exploit would be if the file remove/this.txt existed elsewhere and you could redirect to a different directory.

Jonathan Kuhn
  • 15,279
  • 3
  • 32
  • 43
  • Yes, I did the same, even with two chars, here's the code: – Lorenzo Wills Sep 30 '14 at 17:51
  • Code is too long. Anyway, I think the solution, if any, will not rely on breaking the path... perhaps something like a php://filter where the last argument can be ignored – Lorenzo Wills Sep 30 '14 at 17:57
  • I did fine [this post](http://stackoverflow.com/questions/20726247/php-security-exploit-list-content-of-remote-php-file) that covers a few options. – Jonathan Kuhn Sep 30 '14 at 18:08
  • nice post and discussion, but no solutions there for this – Lorenzo Wills Sep 30 '14 at 18:56
  • Just another thing found, [this article](http://www.ush.it/2009/02/08/php-filesystem-attack-vectors/) covers a few more options. I couldn't get any of them to work, but offers a few more ideas. – Jonathan Kuhn Sep 30 '14 at 19:07
  • yes thank you, that was one of the first I read when looking for a solution. They made a path truncation attack which doesn't work on newer versions of PHP. – Lorenzo Wills Sep 30 '14 at 19:15