Technische Documentatie

Architectuur, services, database, scan-engine en agent-systeem voor beheerders en ontwikkelaars.

Tech Stack

Backend — FastAPI

Python 3.12 met FastAPI. 18 router-modules voor alle pentest-categorieën. Volledig async/await voor parallelle tool-uitvoering. Swagger UI beschikbaar op /docs.

Frontend — Alpine.js + Tailwind

Single-page applicatie zonder build-stap. Alpine.js voor reactieve UI-logica, Tailwind CSS voor styling. WebSocket voor real-time updates zonder polling.

Database — SQLite

Zero-configuratie SQLite opgeslagen in ./results/pentest.db (host-mount). Bevat scans, fasen, bevindingen, terminal-output en agents. Direct opvraagbaar buiten Docker.

Graafanalyse — BloodHound CE

BloodHound Community Edition met Neo4j als graaf-backend. Automatische collector-integratie, optionele API-import en Path Finding voor aanvalspadvisualisatie.

Docker Services

ServiceImagePoortDoel
pentest-api Lokale build (Python 3.12-slim) 8000 FastAPI backend + SPA frontend + alle pentest-tools
pentest-n8n n8nio/n8n:latest 5678 Workflow-automatisering voor notificaties (optioneel)
pentest-bloodhound specterops/bloodhound:latest 8080 BloodHound CE webinterface en API
pentest-neo4j neo4j:4.4 7474 / 7687 Graaf-database backend voor BloodHound
pentest-postgres-bh postgres:15-alpine intern PostgreSQL backend voor BloodHound CE (geen publieke poort)

Scan Engine

De scan-manager (scan_manager.py) orkestreert de 14 fasen en zorgt voor conditionele uitvoering, parallelle checks per fase en fallback chains.

Uitvoeringspatroon

python
# Elke check volgt hetzelfde patroon:
@router.post("/check-name", response_model=CheckResult)
async def my_check(target: TargetBase) -> CheckResult:
    result = CheckResult(check_id="category_check_name",
                         check_name="...", risk_level=RiskLevel.INFO)
    try:
        stdout, stderr, rc = await run(["nxc", "smb", target.dc_ip,
                                        *target.nxc_auth_args()])
        result.add_finding(title, detail, RiskLevel.HIGH, evidence=stdout)
    except Exception as e:
        result.set_error(str(e))
    return result

Fase-orkestratie

  • Parallel per fase — Alle checks binnen één fase draaien gelijktijdig via asyncio
  • Sequentieel per fase — Fasen worden na elkaar uitgevoerd; laterale beweging pas na recon
  • Conditioneel — Exchange-fase start alleen als Exchange tijdens recon gedetecteerd is; SCCM idem
  • Fallback chains — Bevindingen triggeren vervolgaanvallen: bijv. SMB Signing uit + LLMNR aan → relay-setup
  • Timeouts — Elk tool-commando heeft een configureerbare timeout (standaard 5 minuten)

Databaseschema

SQLite opgeslagen in ./results/pentest.db.

Tabel: scans
KolomTypeBeschrijving
idTEXT PKUUID van de scan
labelTEXTGebruikersvriendelijke naam
dc_ipTEXTIP-adres van de domeincontroller
domainTEXTDomeinnaam (bijv. corp.local)
statusTEXTrunning / completed / failed
da_progressREALDA Progress score (0.0–100.0)
finding_countsTEXTJSON: teller per risiconiveau
started_atDATETIMEStarttijdstip van de scan
completed_atDATETIMEEindtijdstip van de scan
agent_idTEXT FKGekoppelde agent (NULL = lokaal)
Tabel: findings
KolomTypeBeschrijving
idINTEGER PKInterne identificatie
scan_idTEXT FKKoppeling aan scans.id
check_idTEXTUnieke check-identifier (bijv. smb_signing_disabled)
risk_levelTEXTcritical / high / medium / low / info
titleTEXTKorte samenvatting van de bevinding
detailTEXTUitgebreide beschrijving met context
evidenceTEXTRuwe tool-output als bewijs
created_atDATETIMETijdstip van bevinding
Tabel: phases
KolomTypeBeschrijving
idINTEGER PKInterne identificatie
scan_idTEXT FKKoppeling aan scans.id
phase_nameTEXTNaam van de fase (bijv. recon, users)
statusTEXTpending / running / completed / failed
started_atDATETIMEStarttijdstip van de fase
completed_atDATETIMEEindtijdstip van de fase
Tabel: terminal_lines
KolomTypeBeschrijving
idINTEGER PKInterne identificatie
scan_idTEXT FKKoppeling aan scans.id
check_idTEXTCheck waarbij de output hoort
lineTEXTRuwe tool-outputregel
created_atDATETIMETijdstip van de outputregel
Tabel: agents
KolomTypeBeschrijving
idTEXT PKUUID van de agent
nameTEXTGebruikersvriendelijke naam
tokenTEXT UNIQUEAuthenticatietoken (uniek per agent)
onlineBOOLEANTrue = actieve WebSocket-verbinding
hostnameTEXTAuto-discovery: hostnaam van de agent-machine
osTEXTAuto-discovery: besturingssysteem
ipsTEXTAuto-discovery: IP-adressen (JSON-array)
domainTEXTAuto-discovery: gedetecteerd domein
dcTEXTAuto-discovery: gedetecteerde domeincontroller

Agent Systeem

Remote agents voeren dezelfde pentest-API uit op een machine in het doelnetwerk. De portal stuurt check-verzoeken naar de agent via een WebSocket-tunnel.

  Portal (uw server)
  ┌──────────────────────────────────┐
  │ agent_manager.py                 │
  │ ├── WebSocket server             │◄──── WS verbinding (outbound vanuit agent)
  │ ├── asyncio.Future routing       │
  │ └── request proxying             │
  └──────────────────────────────────┘
              │  HTTP proxy via WS tunnel
              ▼
  Agent (in doelnetwerk)
  ┌──────────────────────────────────┐
  │ agent.py                         │
  │ ├── Lokale HTTP server (8001)    │
  │ ├── WS → Portal verbinding       │
  │ └── Voert pentest-tools uit      │──► AD domeincontroller
  └──────────────────────────────────┘
  • Agent en portal draaien dezelfde Docker-image — geen aparte agent-binary
  • Alle check-verzoeken van de portal worden via het WebSocket-kanaal naar de agent doorgezet
  • De agent heeft directe netwerktoegang tot AD; de portal heeft die niet nodig
  • Token-rotatie: verwijder de agent in de portal en maak een nieuwe aan

Voorgeïnstalleerde Pentest Tools

ToolVersieGebruik
Impacket0.12.0DCSync, secretsdump, wmiexec, GetUserSPNs, PtH, MS-RPC
NetExec (nxc)latestSMB/LDAP/WinRM enumeratie en uitvoering (opvolger CrackMapExec)
certipy-ad4.8.2ADCS ESC1–ESC13 detectie en exploitatie
BloodHound Python1.7.0AD graafdata collectie
hashcatlatestHash cracking (Kerberoast, AS-REP, NTLMv2, Timeroast)
PetitPotamlatestNTLM coercion via MS-EFSRPC
CoercerlatestMulti-protocol NTLM coercion
pywhiskerlatestShadow Credentials aanvallen
gMSADumperlatestgMSA wachtwoord-extractie
targetedKerberoastlatestACL-gebaseerde Kerberoasting
kerbrutelatestKerberos gebruikersenumeratie en brute force
sprayhoundlatestSlim wachtwoord-spray (BloodHound-aware)
enum4linux-nglatestSMB/NetBIOS enumeratie
ldapdomaindumplatestLDAP domeindata dump
dplootlatestDPAPI en SCCM credential dumps
sccmhunterlatestSCCM-detectie en exploitatie
adidnsdumplatestDNS zone-enumeratie via LDAP
nmaplatestNetwerkscan en poortenumeratie
searchsploitlatestExploit-database zoekfunctie (ExploitDB)

Uitbreidbaar

Een nieuwe check toevoegen is eenvoudig en volgt een vast patroon:

1

Router-bestand aanmaken

Maak routers/my_check.py aan met een FastAPI router en een endpoint dat een CheckResult teruggeeft.

2

Router registreren

Voeg de router toe aan main.py via app.include_router().

3

Toevoegen aan PHASES

Voeg het endpoint toe aan de juiste fase in scan_manager.py's PHASES lijst.

4

DA-score toewijzen

Voeg het check_id toe aan het SCORES-dict in da_progress.py voor gewogen bijdrage aan de DA Progress-balk.