Arbitrary file upload is surprisingly common among web applications, which can be abused to upload malicious files and then compromise the server. Usually, the attacker will select a payload based on whatever server-side programming language is supported. So if the vulnerable app is in PHP, then clearly PHP is supported, therefore an easy choice would be using a PHP payload such as Metasploit’s PHP meterpreter. However, the PHP meterpreter does not share the same performance as, say, a Windows meterpreter. So in reality, what happens is you will probably want to upgrade to a better shell, which involves extra manual work during the process. So why limit your payload options? For this type of scenario, you should use the
PhpEXE mixin. It serves as a payload stager in PHP that will write the final malicious executable onto the remote file system, and then clear itself after use, so it leaves no traces.
To use the
PhpEXE mixin, some typical exploitable requirements should be met:
- You must find a writeable location on the web server.
- The same writeable location should also be readable with a HTTP request.
Note: For an arbitrary file upload bug, there is usually a directory that contains uploaded files, and is readable. If the bug is due to a directory traversal, then a temp folder (either from the OS or the web app) would be your typical choice.
First include the mixin under the scope of your
MetasploitModule class like the following:
Generate the payload (with the PHP stager) with
p = get_write_exec_payload
If you’re working on a Linux target, then you can set
unlink_self to true, which will automatically clear the executable:
p = get_write_exec_payload(:unlink_self=>true)
On Windows, you probably cannot clear the executable because it will probably still be in use. If it’s not possible to automatically clean up malicious files, you should always warn the user about where they are, so they can do it manually later during the penetration test.
At this point you can upload the payload generated by
get_write_exec_payload, and then call it by using a GET request. If you do not know how to send a GET request, please refer to the following article: How to Send an HTTP Request Using HttpClient