C'mon See My Vulns
PHP eval(), LD_PRELOAD RCE
Last updated
PHP eval(), LD_PRELOAD RCE
Last updated
Government of Rhiza has been creating some tools to make the slave labor more efficient. Laura scanned all IPs addresses from Rhiza's ASN and found one of these tools. Your goal is to get into the server to be able to collect the IP addresses that connects to it. Once collected, we can find out the approximate location of these machines.
We are given the following source code:
The eval()
function being used on unsanitised user input. This should already ring some alarm bells.
There is also an info.php
page. We can take a look at the disable_functions
configuration to see which functions are disabled. Functions that can execute OS commands, like exec
, system
, etc. are not allowed.
The open_basedir
setting restricts which files PHP can read/write to. We can see that we are restricted to /var/www/html
.
Now that we know which functions are not allowed, let's look at what we are allowed to do. For the purposes of testing our POST requests, I used an API client called Postman.
List files:
Read arbitrary files:
Write arbitrary files:
Of course, the files we can work with will be restricted by the open_basedir
setting. Yet, we know that the flag is in /root
.
However, from the docker file, we know that there is a readflag
binary. This will allow us to get the flag contents.
We could bypass the restrictions using a custom .so
file, and changing the LD_PRELOAD
environment variable. This only requires that we are able to upload arbitrary files, set environment variables, and call the mail()
function.
Here's a reference: https://www.programmersought.com/article/20535983859/
The basic theory is this:
1. When we set the LD_PRELOAD
environment variable to our custom .so
file, our library takes precedence and gets loaded first, overriding the standard functions.
2. mail()
runs /usr/sbin/sendmail
through /bin/sh
. When this happens, functions like getuid()
are called.
3. If we override getuid()
, we can execute arbitrary code.
Create a hack.c
file as follows:
Compile the shared library:
Open a Python HTTP server and create a ngrok
tunnel to transfer the file.
Transfer the hack.so
to a writeable directory with file_put_contents
and fopen
:
Use the LD_PRELOAD
environment variable to force the loading of our custom getuid()
function. Then, call mail()
- this will run /usr/sbin/sendmail
through /bin/sh
, which calls the getuid()
function.
Note that all three have to be done in one request - the environment variable will only exist for the duration of the current request.
From the Docker logs, we could see that /bin/sh
was indeed executed.
Check that it worked:
We see that the success
file has been created, so our exploit was successful.
Now, it's time to modify the payload to achieve our goals. We will call the provided readflag
binary, and store the results in output.txt
.
Now, after running the above steps again, we should have the flag in output.txt
.
Using file_get_contents
, we can get the output.