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 Pollute and execute access logs.
@jeremy How does that achieve code exec here?
@oj You control the values entered into the access logs, you control the filename, you execute the access log filename effectively as an include.
@jeremy shell_exec doesn't include any files, and file_exists doesn't interpret the file either. Am I missing something?

@oj It's been awhile since I've done this. So it's quite possible that I'm missing something.

file_exists merely verifies the presence of the file.

shell_exec should execute any valid PHP within the file. Enter <?php opening block, functions, anything else you want to include in the access logs, escape and close the PHP block, then arbitrarily attempt to execute the block of code using the pwnme() function to execute command injection, establish a reverse shell, or nearly anything else you like. It's admittedly a sloppy approach.

However, also, like I said, it's been awhile, so my memory might be a bit foggy.

@jeremy shell_exec() is basically like system(). It runs a command on the underlying OS, it doesn't include or interpret any files like include() or require().
@oj LOL... derp.
@jeremy We've all been there :)
@oj So, if you can determine which OS is being run from server banners, and assuming that your inputs are not sanitized and no WAF is in place, then why wouldn't you simply execute a system-level reverse shell?
@jeremy I'm not interested in what commands you might run.. I want to know how you would get command exec in the first place.

@oj
Ahh, you're gonna make me dust it off. LOL... OK.

1. Attempt to determine OS from banners.
2. Determine valid path and most-likely binary available in target OS to establish command exec. Or host a binary matching your target OS on the attacking machine.
3. Select and execute the chosen binary with no parameters/args.

Remote Code Execution would probably be preferable, to grant you further control over the target binary.

Does this answer your question?

@jeremy No. It still doesn't say how you are going to execute anything.
@oj It seems like this was answered. file_exists tests for the existence of the file. shell_exec, then executes that file at the system level. If you are allowed to control the target binary by remotely hosting it, then you can craft anything you desire, while requiring no arguments.
@jeremy Nope, still not. You can't upload files (as per the question). shell_exec() is invoked with "rm {$filename}", not directly with just what you give it. You haven't indicated what string you would pass in to get past file_exists() that also works as a way to execute commands.

@oj

I was thinking something like:

% wget 'http://127.0.0.1/[insert filename here]'

...but when you said above that you weren't interested in what commands I might run, I decided not to demonstrate syntax.

In the meantime, someone else already posted similar solutions.

@jeremy but you can't invoke wget.