LetsDefend: Malicious WordPress Plugin

Overview

Malicious WordPress Plugin is a medium-difficulty challenge from LetsDefend. The challenge requires the analysis of a pcap to determine the source of a compromise and actions performed by the attacker.


Scenario

Our WordPress website has been hacked; however, it’s yet unclear how exactly. The most likely explanation is that a plugin that was installed on the website had a remote code execution vulnerability. By taking advantage of this flaw, the attacker gained illegal access to the server’s operating system.


Q1

What is the IP address of the WordPress server?

We can’t investigate this intrusion properly without knowing the IP address of the WordPress server’s IP address.

To get started, we’ll make a simple HTTP traffic filter.

GET request to a WordPress site.

The resulting packets clearly show WordPress traffic, as highlighted above. In this case, the destination of the GET request is our WordPress server.

We can check the corresponding IP in the Destination column.

Answer 192.168.204.128

Q2

Two attackers were attempting to compromise our environment. What is the IP address of the first attacker based on time?

We can start off by filtering out any irrelevant traffic.

To do this, we’ll filter for only traffic with the destination of the WordPress server.

While we’re at it, let’s filter for only HTTP traffic. This will filter out a ton of noise because we won’t see all the TCP traffic.

Note: The TCP traffic can contain important information, but for now we just need to get a broad picture of events, so we’re ignoring it.

Filtering for WordPress Server as destination IP and only HTTP traffic

The conversations window is found within the Statistics dropdown.

Packet count after filtering

With these simple filter’s, we’ve filtered out nearly 99% of the traffic! We can always go back and cast a wider net.

With our filter applied, we can start by inspecting the HTTP traffic from the top two hosts we discovered in the “Conversations” statistics pane.

Glancing through these results it becomes fairly clear that there was a directory fuzzing tool in use by one of the IPs we discovered. The combination of unusual filenames and rapid queries makes this a fairly certain conclusion. Investigating the User Agent also confirms that the WPScan tool was being used.

Suspicious traffic and user-agent of one of the top two IPs

Answer 192.168.204.132

Q3

What are the versions of the Apache and PHP servers deployed in our environment?

Answer Format: ApacheVersion_PHPversion

To get this information we will need to check a response from the webserver.

We’ll need to change our query, but we can simply change the ip.dst to ip.src in our current filter.

With the filter applied, inspect the HTTP layer information to find the versions.

Server information, as seen in Wireshark

Answer 2.4.58_8.2.12

Q4

During enumeration, the attacker tried to identify users on the site. How many users got enumerated?

To start we’ll change our filter back to ip.dst so that we only see requests going to the WordPress server.

We could also include a filter to limit our results to only traffic coming from the IP we identified in Q2.

We’re looking for user enumeration, so let’s start by checking for a login page.

POST requests to wp-login

We can see there were three post requests to the wp-login endpoint.

To get an idea of what kind of enumeration activity took place, we can filter for results containing one of the discovered usernames.

A packet containing the discovered username

Within the, results we can see the URL /wordpress/author/. If we follow the HTTP stream of this request we can see requests for authors by ID numbers.

Requests to WordPress/?author

When we filter for requests to this endpoint we see what looks like an attacker enumerating users via the author id.

Enumeration activity

If we look at the responses to these requests we can see which ones were successful and which ones resulted in an error. One way to easily view this information is to add a filter to include the relevant frame numbers.

Filter to include the response packet

The answer to this question is the number of valid users discovered. So by checking the responses to these queries and counting the successful ones we can reach the answer.

Answer 3

Q5

After enumeration, a brute force attack was launched against all users. What is the name of the page used for the brute force attack? Answer Format: pagename.extension

Since we know we’re looking for a brute force attack we can start by filtering for traffic from the malicious IP address. We’ll also filter for POST requests.

POST requests from the malicious IP address

Our results show hundreds of requests to a new endpoint. Examining the HTTP Form data also reveals usernames within the XML fields. This appears to be the endpoint targeted by the brute force attack.

Answer xmlrpc.php

Q6

The attacker successfully gained access to one of the accounts. What are the username and password for that account? Answer Format: username:password

We need to see which one of the credentials resulted in a successful login, so we’ll need to adjust our wireshark filter again.

If we follow the HTTP stream for one of the previously mentioned requests (that includes a username in the payload) we can see the response contains the string “Incorrect username or password”.

WordPress response to failed brute force attempt

We’ll create a filter to ignore this value since we only care about successful authentications.

To further finetune our results, we can filter for the request URI. This ensures wireshark will only return packets that are in response to requests to the targeted endpoint.

((frame contains “http://192.168.204.128/wordpress/xmlrpc.php”) && !(xml.cdata == “Incorrect username or password."))

We can see that there is one XML response from the server, checking the source packet we get the username/password of the login.

Packets filtered for the target endpoint and excluding packets containing failure text

Answer demomorgan:demomorgan

Q7

There was a vulnerable plugin that the attacker exploited. What is the name of the plugin?

We can start by creating a filter for frames that contain the term “plugin”

To further narrow our search, we’ll further filter for http packets.

These filters have narrowed our packet count down to 44. A quick glance through the Info column, and we can see an IP address and terminal commands within http requests. That can’t be good.

Filter for frames containing the term 'plugin' and extremely suspicious queries

Answer canto

Q8

What is the CVE number associated with that plugin?

For this question, we’ll need to do some research.

CVEdetails.com is a good resource for this type of question.

Answer CVE-2023-3452

Q9

What is the C2 server IP address of the attacker?

We can find the C2 Server IP in the web requests to the vulnerable plugin we examined in Q7.

Answer 172.26.211.155

Q10

What is the name of the function that the attacker tested the exploit with?

We’ll start by pivoting and filtering for the newly discovered IP address.

With that filtered, we still have a bit of a mess so let’s filter for HTTP traffic to see if anything stands out.

Once filtered, we only get 16 packets.

HTTP packets filtered for the C2 IP

TCP stream of the first connection to the C2 IP

Answer phpinfo()

Q11

What is the name and version of the attacker’s server?

To find the attacker’s server information we’ll analyze HTTP layer details.

With our previous TCP Stream still filtered, we can analyze an HTTP packet from the malicious IP.

Server information of the C2

Answer Python/3.10.12

Q12

What is the username that was logged on during the attack, including the domain?

Back in Q7, we discovered commands being run in GET requests.

One of those commands was whoami.

So for this question, we’ll go back to that filter and follow the stream of that request.

Filter for canto plugins, note the whoami command

The TCP stream of the request.

Answer desktop-2r3ar22\administrator

Q13

The attacker attempted to upload a reverse shell. What is the IP address and port number?

If we analyze the other requests to /admin.php that we discovered in Q10 we discover the code for the reverse shell the attacker attempted to upload.

Traffic discovered in Q10

Reverse shell, seen in the HTTP stream

Answer 172.26.211.155:1234

Q14

What command posed an obstacle during the process of the reverse shell?

For this question, we can filter for the newly discovered IP/Port pair. Once filtered, we can look through the traffic and find an error message for an unknown command. The error can be seen more than once in the traffic, indicating this is the command that gave the attacker trouble.

Commandline error in network traffic

Answer uname