Rapportage en Afronding

Er is een verrassende verwantschap tussen het schrijven van een pentest-rapport en het werk van een forensisch patholoog. Niet vanwege de dood en verderf – hoewel sommige netwerken die we in dit boek hebben behandeld daar angstaanjagend dichtbij kwamen – maar vanwege de aard van het verslag zelf. Een forensisch patholoog schrijft niet simpelweg op dat iemand dood is. Dat weet iedereen al. Het gaat om het waarom, het hoe, en het wat nu. Waaraan is het slachtoffer overleden? Welke omstandigheden leidden tot die uitkomst? En wat had er gedaan kunnen worden om het te voorkomen?

Een pentest-rapport volgt precies dezelfde logica. Niemand betaalt je om te horen dat hun netwerk kwetsbaar is – diep van binnen weten ze dat al. Ze betalen je om precies uit te leggen waar het misgaat, hoe een aanvaller dat uitbuit, en wat ze eraan moeten doen. En dat alles in een document dat zowel de CISO als de stagiair op de IT-afdeling kan begrijpen.

Dit is het punt waarop veel pentesters struikelen. Ze zijn briljant in het vinden van kwetsbaarheden, virtuoos in het escaleren van privileges, kunstenaars in lateral movement – en dan produceren ze een rapport dat leest alsof het door een vastgelopen printer is uitgebraakt. Onleesbare muren van terminal output, screenshots zonder context, en aanbevelingen die neerkomen op “fix dit” zonder verdere uitleg.

Laten we het beter doen.


15.1 Proof of Concept Collection

Voordat je ook maar een letter van je rapport typt, moet je bewijs hebben. Zonder bewijs is een pentest-rapport niets meer dan een mening, en opinies zijn in de beveiligingswereld net zoveel waard als een onversleuteld wachtwoord in een Post-it notitie op een monitor.

15.1.1 Screenshots: Timing, Context en Annotatie

Een screenshot is pas bruikbaar als hij drie dingen heeft: het juiste moment, de juiste context, en de juiste annotatie.

Timing is cruciaal. Maak je screenshot op het moment van impact. Niet vijf minuten later wanneer je al drie commando’s verder bent. Het verschil tussen een overtuigend bewijs en een nutteloze afbeelding is vaak een kwestie van seconden. Neem de screenshot terwijl de SQL injection resultaten teruggeeft, terwijl BloodHound het pad naar Domain Admin toont, terwijl Mimikatz de hashes dumpt.

Context betekent dat de screenshot op zichzelf moet kunnen staan. Een plaatje van een terminalsessie met de output NT AUTHORITY\SYSTEM is indrukwekkend voor je collega-pentesters, maar voor een manager is het drie woorden in een zwart venster. Zorg dat je terminal prompt zichtbaar is – met hostname en username – zodat duidelijk is waar je bent en als wie je opereert.

Annotatie maakt het verschil tussen een plaatje en bewijsmateriaal. Gebruik rode kaders, pijlen, en korte labels om de aandacht te vestigen op het relevante deel. Een screenshot van een webpagina met 200 regels HTML is nutteloos. Dezelfde screenshot met een rood kader om de Set-Cookie: session=admin; HttpOnly=false header vertelt een heel verhaal.

IB Tip: IB slaat screenshots op in raw/screenshots/ en maakt ze beschikbaar via de project images dropdown in de LaTeX toolbar. Gebruik \plaatje{bestandsnaam}{onderschrift} in je finding-tekst om ze automatisch in het rapport op te nemen.

15.1.2 Terminal Recordings met asciinema

Screenshots zijn statisch. Soms heb je bewegend bewijs nodig. Niet als flashy presentatie, maar als onweerlegbaar bewijs dat je een bepaalde aanvalsketen daadwerkelijk hebt uitgevoerd, stap voor stap, in real-time.

Asciinema is hiervoor het perfecte gereedschap. Het neemt je terminalsessie op als een lichtgewicht tekstbestand – geen zware video, maar een JSON-gebaseerd formaat dat elke toetsaanslag en elk stukje output vastlegt met milliseconde-precisie.

Start een recording voordat je een complexe aanvalsketen begint:

asciinema rec --title "DCSync Attack via Compromised Workstation" ~/recordings/dcsync.cast

De recording loopt mee terwijl je werkt. Geen extra handelingen, geen vensters die in de weg zitten. Als je klaar bent, druk je exit of Ctrl+D en het bestand staat klaar.

Wat maakt asciinema superieur aan een schermopname?

15.1.3 IB Recordings Feature

IB heeft een ingebouwde recordings-pagina op /dashboard/recordings die je asciinema-opnames integreert in het dashboard. De interface laadt bestanden uit meuk/logs/ en biedt een volledige player met zoekfunctionaliteit.

De recordings-pagina toont een overzicht van alle .cast bestanden met bestandsnaam, grootte en tijdstempel. Klik op een recording en de ingebouwde asciinema player start met afspelen – compleet met Monokai thema, monospace font, en een fullscreen modus voor presentaties.

meuk/logs/
  lateral-movement-2024-03-15.cast
  dcsync-dc01-2024-03-16.cast
  kerberoast-svc-accounts-2024-03-16.cast
  bloodhound-collection-2024-03-17.cast

De player wordt geinitialiseerd met 120 kolommen en 30 rijen – ruim genoeg voor de meeste terminalsessies. De fullscreen-modus schaalt automatisch en past de fit mode aan van width naar both, zodat de opname het hele scherm vult.

IB Tip: Organiseer je recordings met een duidelijke naamconventie: activiteit-doelwit-datum.cast. De zoekbalk in IB filtert op bestandsnaam, dus dcsync typen toont direct alle DCSync-gerelateerde opnames.

15.1.4 Network Captures

Voor netwerk-specifieke bevindingen is een packet capture vaak het meest overtuigende bewijs. Een Wireshark capture die laat zien dat LDAP-verkeer onversleuteld over het netwerk gaat, of dat NTLM-hashes in cleartext worden verstuurd, is onweerlegbaar.

Bewaar captures in pcap of pcapng formaat. Filter ze voordat je ze aan het rapport toevoegt – niemand wil door 2 GB aan netwerkverkeer bladeren om drie relevante pakketten te vinden.

# Capture alleen LDAP-verkeer van/naar de domain controller
tcpdump -i eth0 -w ldap_cleartext.pcap host 10.10.10.1 and port 389

# Capture NTLM authenticatie
tcpdump -i eth0 -w ntlm_relay.pcap 'tcp port 445 or tcp port 139'

Voeg de relevante pakketten toe als screenshot aan je finding – een Wireshark scherm met de juiste display filter en de relevante velden uitgelicht.

15.1.5 Logs en Command Output

Elke commando dat je uitvoert en elke output die je terugkrijgt, is potentieel bewijsmateriaal. De vuistregel is simpel: als je twijfelt of je iets moet bewaren, bewaar het.

Gebruik tee om command output tegelijkertijd op het scherm te tonen en naar een bestand te schrijven:

crackmapexec smb 10.10.10.0/24 --shares -u user -p 'P@ssw0rd' | tee smb_shares_output.txt

Gebruik script als je een hele sessie wilt vastleggen inclusief interactieve commando’s:

script -t 2>timing.log session_dc01.txt

En vergeet de tijdstempels niet. Voeg aan het begin van elk logbestand een datum/tijd toe. Dit is niet alleen goed voor je rapport, maar essentieel als er later juridische vragen komen over de timeline van je test.

IB Tip: IB’s Output view (/dashboard/outputs) verzamelt automatisch output van commando’s die via de tasks runner worden uitgevoerd. Gebruik de tasks runner waar mogelijk, zodat command output automatisch wordt bewaard en doorzoekbaar is via het dashboard.


15.2 IB Findings Workflow

Nu je al je bewijsmateriaal hebt verzameld – screenshots geannoteert, recordings opgenomen, captures gefilterd, logs bewaard – is het tijd om bevindingen aan te maken. Dit is waar IB’s findings management zijn waarde bewijst.

15.2.1 Finding Aanmaken voor Netwerk-bevindingen

Navigeer naar /dashboard/findings en je ziet het findings-overzicht. Bovenaan staan vier kaarten: het totaal aantal findings, het aantal templates, het aantal scoped items, en een knop om het rapport te genereren.

Het overzicht is verdeeld in twee kolommen. Links staan de beschikbare templates – voorgedefinieerde finding-types die je kunt gebruiken als basis. Rechts staan je bestaande findings met ID, naam, host, en acties om te bewerken of te verwijderen.

Om een nieuwe finding aan te maken, klik je op Add naast het relevante template. IB opent de Finding Editor met het volgende formulier:

Het formulier slaat de finding op via POST /dashboard/findings/save. Als het id veld gevuld is, wordt een bestaande finding bijgewerkt; anders wordt een nieuwe aangemaakt. Simpel, effectief, zonder poespas.

IB Tip: Het veld “Werk de bevinding uit” ondersteunt LaTeX-opmaak via de ingebouwde LaTeX toolbar. Gebruik \begin{lstlisting} voor code blocks, \plaatje{file}{caption} voor afbeeldingen, en \textbf{} voor vetgedrukte tekst. De toolbar biedt ook een dropdown voor project-afbeeldingen uit raw/screenshots/.

15.2.2 Standaard Templates voor Netwerk-bevindingen

IB wordt geleverd met een set standaard finding templates die je via /dashboard/findings/templates/seed kunt laden. Deze templates bevatten voorgedefinieerde beschrijvingen, impact-analyses, aanbevelingen, en referenties voor veelvoorkomende kwetsbaarheden.

De standaard templates in standard_findings.json zijn primair gericht op web-kwetsbaarheden, maar veel ervan zijn direct relevant voor netwerk-pentests:

Template Netwerktoepassing
OS Command Injection RCE via webapplicaties op interne servers
SQL Injection (SQLi) Database-toegang via interne webapps
CORS misconfiguratie Cross-origin aanvallen op interne API’s
Server-Side Request Forgery Toegang tot cloud metadata, interne diensten
Broken Access Control Privilege escalation op interne systemen
Cryptographic Failures Onversleuteld verkeer, zwakke certificaten
Security Headers Ontbrekende beveiliging op interne webservers
Vulnerable and Outdated Components Ongepatchte software op netwerksystemen
Path Traversal Bestandstoegang via kwetsbare webdiensten
Insecure Design Architectuurproblemen in het netwerk

Elk template bevat velden voor: - Titel en type (categorie) - CWE nummer (Common Weakness Enumeration) - OWASP Top 10 classificatie - MITRE ATT&CK technique ID - CVSS 4.0 vector en base score - Beschrijving in het Nederlands - Impact analyse - Aanbeveling met gestructureerde stappen - Referenties naar externe bronnen

Voor netwerk-specifieke bevindingen die niet in de standaard templates staan – denk aan Kerberoasting, DCSync, NTLM relay, onbeveiligde SMB shares – maak je een finding aan zonder template (of je maakt je eigen templates aan via Flask-Admin). Het ref veld koppelt een finding aan een template; laat het leeg voor custom findings.

IB Tip: Gebruik de seed-functie aan het begin van elk project om de standaard templates te laden. Dit overschrijft alle bestaande templates, dus doe dit voordat je findings aanmaakt. De seed-knop op de findings-pagina vraagt om bevestiging voordat hij alle templates overschrijft.

15.2.3 CVSS 4.0 Scoring voor Netwerk-kwetsbaarheden

CVSS 4.0 is de nieuwste versie van het Common Vulnerability Scoring System en IB heeft een volledige interactieve calculator ingebouwd. In tegenstelling tot CVSS 3.1 maakt versie 4.0 onderscheid tussen impact op het kwetsbare systeem en impact op downstream systemen – een cruciaal verschil voor netwerk-pentests waar een gecompromitteerde werkstation kan leiden tot volledige domein-compromittatie.

De calculator in IB presenteert elf base metrics verdeeld over drie secties:

Exploitability Metrics: - Attack Vector (AV): Network, Adjacent, Local, Physical - Attack Complexity (AC): Low, High - Attack Requirements (AT): None, Present - Privileges Required (PR): None, Low, High - User Interaction (UI): None, Passive, Active

Vulnerable System Impact: - Confidentiality (VC): None, Low, High - Integrity (VI): None, Low, High - Availability (VA): None, Low, High

Subsequent System Impact: - Confidentiality (SC): None, Low, High - Integrity (SI): None, Low, High - Availability (SA): None, Low, High

Wanneer je alle metrics selecteert, genereert de calculator een CVSS 4.0 vector string in het formaat CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H en berekent de bijbehorende score via de server-side API (/api/cvss4/calculate). De score wordt vertaald naar een severity label:

Score Severity
0.0 None
0.1 - 3.9 Low
4.0 - 6.9 Medium
7.0 - 8.9 High
9.0 - 10.0 Critical

15.2.4 Verschil in Scoring: Remote vs Local, Authenticated vs Unauthenticated

Hier wordt het interessant voor netwerk-pentests. De CVSS-score van exact dezelfde kwetsbaarheid kan dramatisch verschillen afhankelijk van de context.

Voorbeeld 1: Unauthenticated Remote Code Execution Een kwetsbaarheid die zonder authenticatie via het netwerk kan worden misbruikt:

CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H

Attack Vector = Network, Privileges Required = None. Dit is het nachtmerriescenario – iedereen op het netwerk kan dit misbruiken. Score: maximaal.

Voorbeeld 2: Authenticated Local Privilege Escalation Dezelfde impact, maar je moet al op het systeem zitten met geldige credentials:

CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H

Attack Vector = Local, Privileges Required = Low. De score daalt aanzienlijk, ook al is de uiteindelijke impact identiek.

Voorbeeld 3: Adjacent Network Attack met Prerequisites Een aanval die alleen werkt vanuit hetzelfde netwerksegment en specifieke condities vereist:

CVSS:4.0/AV:A/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:L/SI:N/SA:N

Attack Vector = Adjacent, Attack Complexity = High, Attack Requirements = Present. De score zakt verder.

Het verschil tussen deze drie scenario’s is het verschil tussen “dit moet vandaag nog gefixt worden” en “dit nemen we mee in de volgende patch cycle.” Scoor eerlijk. Een overschatte score ondermijnt je geloofwaardigheid net zo effectief als een onderschatte score het risico bagatelliseert.

De Subsequent System Impact metrics zijn bijzonder relevant voor netwerk-pentests. Wanneer je een webserver compromitteert en van daaruit het interne netwerk binnendringt, is de impact op het kwetsbare systeem (de webserver) misschien beperkt, maar de impact op downstream systemen (Active Directory, databases, file shares) kan catastrofaal zijn. CVSS 4.0 laat je dit onderscheid expliciet maken.

IB Tip: De CVSS 4.0 calculator synchroniseert automatisch met de cvss en basescore velden in het finding-formulier. Wijzig je de vector string handmatig, dan updaten de dropdowns zich automatisch. Wijzig je een dropdown, dan wordt de vector string opnieuw gegenereerd en de score herberekend via de server-side API.


15.3 Evidence Management

Bewijs verzamelen is een ding. Bewijs organiseren is een heel ander beest. En net als bij elke vorm van bewijsvoering geldt: als je het niet kunt terugvinden, bestaat het niet.

15.3.1 Evidence Uploaden in IB

IB heeft een evidence management systeem dat bestanden direct aan findings koppelt. De API endpoints zijn:

Het systeem accepteert een breed scala aan bestandstypen:

Categorie Toegestane types
Afbeeldingen PNG, JPEG, GIF, WebP
Documenten PDF, plain text, HTML, CSV
Data JSON, XML
Overig ZIP, octet-stream

De maximale bestandsgrootte is 10 MB per upload. Bestanden worden opgeslagen in meuk/flask/db/evidence/<finding_id>/ met een UUID-gebaseerde bestandsnaam om conflicten te voorkomen, terwijl de originele bestandsnaam bewaard blijft in de database voor weergave en download.

# Upload evidence via curl
curl -X POST -F "file=@bloodhound_path_to_da.png" \
  http://127.0.0.1:5000/api/findings/42/evidence

# Lijst evidence voor finding 42
curl http://127.0.0.1:5000/api/findings/42/evidence

# Exporteer alle evidence als ZIP
curl -o evidence_backup.zip \
  http://127.0.0.1:5000/api/findings/evidence/export

15.3.2 Organisatie: Per Bevinding, Per Systeem

De evidence directory structuur in IB is bewust simpel gehouden:

meuk/flask/db/evidence/
  1/
    a4f8e2c1d3b5.png      # BloodHound screenshot
    7c9d1e0f2a3b.txt      # Nmap output
  2/
    b5e3f1a2c4d6.png      # Mimikatz output screenshot
    d8f2a1b3c5e7.pcap     # Network capture
  3/
    ...

Elk finding-ID heeft zijn eigen subdirectory. Dit betekent dat wanneer je een finding verwijdert, alle bijbehorende evidence automatisch wordt opgeruimd dankzij de SQLAlchemy cascade delete (cascade='all, delete-orphan' op de evidence_files relatie).

Voor netwerk-pentests met tientallen systemen is het slim om je finding-namen te structureren per systeem. In plaats van vijf losse findings genaamd “Zwak wachtwoord” maak je findings aan als:

Het locatie veld in het finding-formulier is specifiek bedoeld voor het IP-adres of de hostname. Gebruik dit consistent – het verschijnt in de findings-tabel en maakt het overzicht scanbaar.

15.3.3 Screenshots van BloodHound, Terminal Output, en Meer

Specifieke types evidence die je voor netwerk-pentests wilt bewaren:

BloodHound grafen: - Shortest Path to Domain Admin - Kerberoastable accounts met paden naar privileged groups - Sessions op high-value targets - Dangerous ACL-relaties

Terminal output: - CrackMapExec scans met gemarkeerde succesvolle logins - Impacket tool output (secretsdump, GetNPUsers, GetUserSPNs) - Responder captures met gecrashte hashes - PowerView enumeratie-resultaten

Netwerk-diagrammen: - Netwerktopologie zoals ontdekt tijdens de test - Segmentatie (of het gebrek daaraan) - Firewall-regels die je hebt weten te omzeilen

IB Tip: Gebruik de ZIP-export functie (/api/findings/evidence/export) aan het einde van elk project om een complete backup te maken van al je bewijsmateriaal. Het ZIP-bestand structureert de bestanden per finding-ID met de originele bestandsnamen.


15.4 Notes

De meest onderschatte functie in elke pentest-toolkit is de notitie-functie. Niet de flashy exploits, niet de geautomatiseerde scanners, niet de CVSS-calculator – maar simpele, ouderwetse notities.

15.4.1 Dagelijkse Notities Bijhouden

IB’s Notes blueprint (/dashboard/notes) biedt een minimalistische maar doeltreffende interface voor het bijhouden van dagelijkse notities. Elke notitie heeft een naam en een inhoudsveld, en verschijnt in een overzicht dat je kunt herschikken via drag-and-drop.

Het notes-systeem heeft twee slimme eigenschappen:

1. Volgorde via drag-and-drop Sleep notities in de gewenste volgorde. De volgorde wordt opgeslagen via POST /api/notes/reorder en bepaalt de volgorde waarin notities in het rapport verschijnen. Begin elke dag met een nieuwe notitie – “Dag 1: Verkenning”, “Dag 2: Initial Access”, “Dag 3: Privilege Escalation” – en sleep ze in chronologische volgorde.

2. Rapport toggle Elke notitie heeft een checkbox “Rapport” die bepaalt of de notitie wordt opgenomen in het gegenereerde rapport. Niet alles wat je noteert hoort in het eindproduct. Interne opmerkingen (“Koffie is op, IT-manager zegt dat netwerk altijd zo traag is”) houd je uit het rapport door de checkbox uit te vinken.

De toggle werkt via POST /api/notes/<id>/toggle-rapport en visueel verandert de notitie van kleur – notities die in het rapport worden opgenomen krijgen een groene rand.

15.4.2 Markdown en LaTeX Support in IB Notes

Het inhoudsveld van notities ondersteunt LaTeX-opmaak via dezelfde LaTeX toolbar die ook in de finding editor zit. De toolbar in “note” modus biedt toegang tot:

Dit is bijzonder handig omdat je notities – zodra je de “Rapport” checkbox aanvinkt – direct als subsecties in het rapport verschijnen. De gen_rapport() functie in IB itereert over alle notities met rapport=True, gesorteerd op volgorde, en voegt ze toe aan de “Verkenning & ontdekking” sectie van het LaTeX-document:

for notitie in notities:
    notes = notes + '\\subsection{' + (notitie.naam or '') + '}\n'
              + (notitie.uitwerken or '') + '\n\n'

Je notities worden letterlijk subsecties in het rapport. Dit betekent dat als je je notities al in LaTeX-opmaak schrijft – met \begin{lstlisting} voor code en \plaatje{}{} voor afbeeldingen – ze naadloos in het rapport passen zonder extra bewerking.

15.4.3 Van Notities naar Findings

De workflow in IB is ontworpen om een vloeiende overgang te maken van ruwe notities naar gestructureerde findings:

  1. Tijdens de test: Schrijf notities. Elke ontdekking, elke observatie, elk commando dat iets oplevert. Gebruik de chronologische dagstructuur.
  2. Aan het einde van elke dag: Bekijk je notities. Welke observaties zijn findings? Maak voor elk potentieel rapport-waardige ontdekking een finding aan.
  3. Na de test: Gebruik de “Rapport” toggle om te bepalen welke notities als verkenningssecties in het rapport verschijnen. De findings sectie wordt apart gegenereerd op basis van de templates.

Deze scheiding – notities voor het narratief, findings voor de kwetsbaarheden – zorgt ervoor dat je rapport zowel het verhaal vertelt (hoe ben je binnengekomen, welke stappen heb je gezet) als de concrete bevindingen documenteert (wat is kwetsbaar, hoe erg is het, wat moet er gebeuren).

IB Tip: Schrijf je notities in de tegenwoordige tijd alsof je het nu doet: “Scan het 10.10.10.0/24 netwerk met nmap. Poort 445 staat open op 14 systemen.” Dit leest natuurlijker in het rapport en geeft de lezer het gevoel mee te kijken terwijl de test plaatsvindt.


15.5 Rapport Generatie

Dit is waar de magie gebeurt. Of beter gezegd: waar alle voorgaande magie wordt omgezet in een document dat iemand daadwerkelijk wil lezen.

15.5.1 IB’s pandoc/LaTeX Pipeline

IB’s rapportgeneratie is een pipeline die LaTeX-templates omzet via HTML naar Markdown, en uiteindelijk via pandoc naar het gewenste uitvoerformaat. Het klinkt als een Rube Goldberg-machine, en eerlijk gezegd – dat is het ook een beetje. Maar het werkt.

De gen_rapport() functie in findings.py doorloopt de volgende stappen:

Stap 1: Data verzamelen

bevindingen = db_bevindingen.query.group_by(db_bevindingen.ref).all()
notities = db_notes.query.filter_by(rapport=True).order_by(db_notes.volgorde.asc()).all()

Findings worden gegroepeerd op ref (template-ID) zodat meerdere instanties van dezelfde kwetsbaarheid samen worden gepresenteerd. Notities worden gefilterd op de rapport-toggle en gesorteerd op volgorde.

Stap 2: LaTeX genereren Voor elke finding-groep wordt het findings_nl.html template gerenderd. Dit template genereert LaTeX-code met: - Een \subsection per finding (of per template als er meerdere instanties zijn) - Een \bevindingkop met ID, OWASP-categorie en CWE-nummer - De template-beschrijving - Per-instantie uitwerkingen als \subsubsection - Risico-inschatting, impact, aanbeveling, en referenties - Een \newpage tussen bevindingen

De notities worden via het notes.html template toegevoegd aan de verkenningssectie, met cross-references naar de bijbehorende findings via \uitwerking{bev<id>}.

Stap 3: LaTeX naar HTML De gegenereerde LaTeX wordt getransformeerd naar HTML via een reeks regex-vervangingen:

LaTeX HTML
\section{...} <h1>...</h1>
\subsection{...} <h2>...</h2>
\subsubsection{...} <h3>...</h3>
\begin{lstlisting} <pre>
\begin{itemize} <ul>
\plaatje{file}{caption} <img src="..." alt="..." />
\textbf{...} <strong>...</strong>
\footnote{...} [^voetnootN]
\label{...} <span id="...">
\newpage <div style="page-break-after: always">

Stap 4: HTML naar Markdown via pandoc De HTML wordt naar schijf geschreven als rapport/tex.html en vervolgens converteert pandoc het naar Markdown:

md = pandoc('rapport/tex.html', '-o', 'rapport/tex.md')

Stap 5: Markdown opschonen en frontmatter toevoegen Het resulterende Markdown-bestand wordt nabewerkt: escaped brackets worden hersteld, en een YAML frontmatter wordt toegevoegd met titel, subtitel, auteur en datum.

Het eindresultaat staat in rapport/tex.md – een compleet rapport in Markdown dat via pandoc naar PDF, DOCX, of elk ander formaat kan worden geconverteerd.

15.5.2 Template Structuur

De rapport-structuur die IB genereert ziet er als volgt uit:

---
title: "Pentest Rapport"
subtitle: "Rapportage"
author: Incompetent Bastard
date: today
---

# Verkenning & ontdekking
  ## [Notitie 1: Dag 1 Verkenning]
  ## [Notitie 2: Dag 2 Initial Access]
  ...cross-references naar findings...

# Bevindingen
  ## [Finding: SQL Injection in zoekfunctie]
    ### [ID | OWASP Categorie | CWE]
    [Beschrijving uit template]
    [Uitwerking per instantie]
    ### Risico
    ### Impact
    ### Aanbeveling
    ### Referenties
    ---page break---

  ## [Finding: Zwakke wachtwoorden]
    ...

De scheiding tussen “Verkenning & ontdekking” en “Bevindingen” is fundamenteel. Het eerste deel vertelt het verhaal van je test – hoe ben je te werk gegaan, wat heb je gevonden. Het tweede deel is de catalogus van kwetsbaarheden met alle technische details.

15.5.3 Executive Summary vs Technische Details

IB genereert primair het technische rapport. De executive summary – dat cruciale eerste hoofdstuk dat bepaalt of de rest van het rapport gelezen wordt – moet je zelf schrijven. Dit is geen tekortkoming; dit is by design.

Een executive summary laat zich niet automatiseren. Het vereist menselijk oordeel: wat is het overkoepelende risico? Wat is de rode draad door alle bevindingen? Welke business impact heeft dit? Kan een aanvaller bij klantgegevens? Kan de productie platgelegd worden?

Structuur van een effectieve executive summary:

  1. Scope en aanpak (2-3 zinnen): Wat is er getest, wanneer, en hoe?
  2. Algeheel risiconiveau (1 zin): Eenvoudige classificatie – Kritiek, Hoog, Gemiddeld, Laag.
  3. Belangrijkste bevindingen (3-5 bullet points): De showstoppers, in begrijpelijke taal.
  4. Positieve observaties (2-3 bullet points): Wat ging er goed? Dit bouwt goodwill.
  5. Aanbeveling op hoofdlijnen (1-2 zinnen): Wat moet er nu gebeuren?

Schrijf deze samenvatting alsof je doelgroep geen technische kennis heeft. Niet “NTLM relay naar Domain Admin via unconstrained delegation” maar “Een aanvaller op het interne netwerk kan binnen 15 minuten volledige controle over alle systemen krijgen, zonder dat er een wachtwoord nodig is.”

15.5.4 Walkthrough: Compleet Rapport Genereren

Laten we het hele proces doorlopen, van begin tot eind.

1. Notities zijn geschreven Drie dagen pentest, drie notities met de “Rapport” checkbox aangevinkt: - “Dag 1: Netwerk verkenning en service discovery” - “Dag 2: Initieel compromitteren via Kerberoasting” - “Dag 3: Lateral movement en domain compromise”

2. Findings zijn aangemaakt Vijf findings gekoppeld aan templates, elk met host, CVSS-score, en uitwerking: - Kerberoastable service accounts (CVSS 7.5 - High) - Onveilige SMB shares (CVSS 5.3 - Medium) - Ontbrekende LAPS (CVSS 6.8 - Medium) - Cleartext credentials in scripts (CVSS 8.1 - High) - Geen netwerksegmentatie (CVSS 7.2 - High)

3. Evidence is geupload Screenshots, terminal recordings, en BloodHound exports gekoppeld aan de findings.

4. Rapport genereren Navigeer naar /dashboard/findings en klik op Generate report. IB opent een nieuw tabblad met de HTML-preview van je rapport, en schrijft tegelijkertijd drie bestanden: - rapport/findings_nl.tex – Het ruwe LaTeX-document - rapport/tex.html – De HTML-tussenvorm - rapport/tex.md – Het uiteindelijke Markdown-rapport

5. Naar PDF converteren Vanaf de command line:

cd rapport/
pandoc tex.md -o pentest_rapport.pdf \
  --pdf-engine=xelatex \
  --template=eisvogel \
  -V geometry:margin=2.5cm

Of naar DOCX voor organisaties die de voorkeur geven aan Word:

pandoc tex.md -o pentest_rapport.docx \
  --reference-doc=template.docx

15.5.5 Import en Export

IB ondersteunt het importeren en exporteren van findings in JSON-formaat. Dit is bijzonder handig voor:

De export (GET /api/findings/export) genereert een JSON-document met schema versie, timestamps, catalogi (OWASP, CWE, MITRE ATT&CK), standaard finding templates, en project findings inclusief alle metadata.

De import (POST /api/findings/import of via de upload-form op de findings-pagina) accepteert hetzelfde JSON-formaat en maakt automatisch findings en templates aan. Bestaande templates worden herkend op basis van standard_code; nieuwe templates worden aangemaakt als ze niet bestaan.

IB Tip: Exporteer je findings regelmatig – niet alleen aan het einde van het project. De JSON-export is een volledige snapshot van je werk en dient als backup als de SQLite database corrupt raakt.


15.6 Communicatie

Je rapport is af. Het is technisch correct, goed gestructureerd, en voorzien van overtuigend bewijsmateriaal. Nu komt het moeilijkste deel: het communiceren van je bevindingen aan mensen die misschien helemaal niet willen horen wat je te zeggen hebt.

15.6.1 De Debrief Meeting

Plan de debrief meeting zodra het rapport af is. Niet over twee weken, niet na de volgende sprint planning – nu. De urgentie van bevindingen neemt niet af met de tijd, maar het geheugen van je publiek wel.

Structureer de meeting als volgt:

Eerste 5 minuten: Context en scope. Herinner iedereen aan wat er getest is en waarom. Dit is geen verdediging van je werk, maar een framing van de discussie.

Volgende 15 minuten: De drie tot vijf belangrijkste bevindingen. Niet alle veertig. De showstoppers. Voor elke bevinding: wat is het, waarom is het erg, en wat moet eraan gedaan worden. Gebruik de IB HTML-preview om live door de bevindingen te lopen – het is visueler dan een PDF.

Volgende 10 minuten: Vragen en discussie. Bereid je voor op de klassiekers: “Kan dit echt in de praktijk?” (Ja, daarom heet het een proof of concept.) “Maar we hebben toch een firewall?” (Die hebben we omzeild, zie bevinding 3.) “Hoeveel kost het om alles te fixen?” (Minder dan een breach, dat is zeker.)

Laatste 5 minuten: Vervolgstappen. Wie doet wat, wanneer, en hoe weten we dat het gefixt is?

15.6.2 Risico in Business Taal Uitleggen

De grootste uitdaging in pentest-rapportage is niet het technische schrijven – het is de vertaling. Technisch jargon naar business impact. CVSS-scores naar euro’s en reputatieschade.

Slechte vertaling: > “We hebben via AS-REP roasting een TGT verkregen voor svc_backup, waarna we via constrained delegation een TGS voor de CIFS service op DC01 hebben aangevraagd en met behulp van DCSync de krbtgt hash hebben gedumpt.”

Goede vertaling: > “We hebben een onbeveiligd service-account gevonden waarmee we binnen twee uur volledige controle over al uw systemen konden overnemen – inclusief toegang tot alle e-mail, alle bestanden, en alle gebruikersaccounts. Een kwaadwillende medewerker of een aanvaller die toegang heeft tot uw netwerk zou hetzelfde kunnen doen.”

Beide beschrijvingen zijn waar. De eerste is nuttig voor het IT-team dat het moet fixen. De tweede is nuttig voor het management dat moet besluiten of het gefixt wordt. Je rapport heeft beide nodig.

15.6.3 Remediation Prioritering

Niet alle kwetsbaarheden zijn gelijk geschapen, en niet alle fixes zijn even dringend. Help je klant door een duidelijke prioritering te geven:

Onmiddellijk (binnen 48 uur): - Actief misbruikte kwetsbaarheden - Unauthenticated remote code execution - Default credentials op kritieke systemen - Cleartext wachtwoorden in bereikbare locaties

Kort termijn (binnen 2 weken): - Authenticated privilege escalation - Ontbrekende patches voor bekende CVE’s - Onveilige netwerkconfiguraties - Zwakke wachtwoordbeleid

Middellang termijn (binnen 3 maanden): - Architectuurverbeteringen (segmentatie, LAPS) - Monitoring en detectie verbeteren - Security awareness training - Proces- en procedure-aanpassingen

Lang termijn (binnen 6-12 maanden): - Zero Trust implementatie - Volledige PKI-uitrol - Identity governance programma - Continuous security testing

15.6.4 Herbeoordeling Plannen

Een pentest zonder herbeoordeling is als naar de dokter gaan, horen dat je hoge bloeddruk hebt, en vervolgens nooit meer terugkomen. De herbeoordeling – of retest – is waar je verifieert dat de gevonden kwetsbaarheden daadwerkelijk zijn opgelost.

Plan de retest vier tot zes weken na het opleveren van het rapport. Dit geeft het IT-team voldoende tijd om de kritieke en hoge bevindingen te verhelpen, maar niet genoeg tijd om het rapport in een la te laten verdwijnen.

Tijdens de retest: 1. Test elke bevinding opnieuw op exact hetzelfde systeem 2. Documenteer of de fix effectief is 3. Controleer of de fix geen nieuwe kwetsbaarheden heeft geintroduceerd 4. Lever een kort retest-rapport op met status per bevinding: opgelost, gedeeltelijk opgelost, niet opgelost

IB Tip: Gebruik de export/import functionaliteit om findings van het originele project te importeren in een nieuw IB-project voor de retest. Zo heb je alle originele bevindingen als referentiepunt.


15.7 Het Rapport dat Niemand Leest

En dan nu een moment van oprechte eerlijkheid, want als we het daar niet over hebben, dan liegt dit hele hoofdstuk.

Het meest deprimerende aspect van pentest-rapportage is dit: de gemiddelde levensduur van een pentest-rapport, gemeten vanaf het moment van oplevering tot het moment waarop het voorgoed in een digitale la verdwijnt, is ongeveer drie werkdagen. Twee daarvan zijn het weekend.

Je hebt weken besteed aan het testen. Dagen aan het schrijven. Uren aan het perfectioneren van screenshots, het tunen van CVSS-scores, het formuleren van aanbevelingen die zowel technisch accuraat als bestuurlijk begrijpelijk zijn. En dan stuurt iemand het PDF’tje door naar een gedeelde schijf waar het rustig gaat composteren naast de pentest-rapporten van 2019, 2020, 2021, 2022 – die overigens allemaal exact dezelfde bevindingen bevatten.

Want dat is het werkelijke schandaal. Het zijn niet de kwetsbaarheden zelf die het probleem zijn. Het is de systemische onwil om er iets aan te doen. Organisaties besteden duizenden euro’s aan een pentest, ontvangen een rapport met de bevinding dat hun halve netwerk openstaat, knikken beleefd in de debrief meeting, archiveren het rapport onder “compliance”, en bestellen volgend jaar dezelfde pentest opnieuw. Het is alsof je elk jaar een brandweerman betaalt om je te vertellen dat je huis in brand staat, hem beleefd bedankt, en vervolgens de voordeur weer dichtdoet.

Het compliance-circuit is hier bijzonder giftig. Organisaties die een pentest laten uitvoeren omdat het moet – van de auditor, van de verzekeraar, van de regelgever – zijn zelden geinteresseerd in de resultaten. Ze zijn geinteresseerd in het rapportje. In het stempel. In het vinkje op de checklist. “We hebben een pentest laten doen” is het doel, niet “we hebben ons netwerk beveiligd.” Het verschil tussen die twee zinnen is het verschil tussen security en security theater, en de meeste organisaties zitten stevig in het theater.

En wij – de pentesters, de rapportschrijvers, de professionele inbrekers – zijn medeplichtig. Elke keer dat we een rapport opleveren zonder op te volgen, elke keer dat we dezelfde bevinding voor het derde jaar op rij opschrijven zonder te escaleren, elke keer dat we “ja, het is opgelost” accepteren zonder te verifieren, zijn we de tandarts die zijn patient na een routinecontrole naar huis stuurt zonder te vragen of die eigenlijk weleens flost.

Dus hier is de ongemakkelijke waarheid: je rapport is niet af als het geschreven is. Het is af als de kwetsbaarheden zijn opgelost. En als ze niet worden opgelost, dan heb je niet gefaald als pentester – maar als communicator. En misschien moeten we daar wat eerlijker over zijn.

IB Tip: Plan de retest. Zet het in het contract. Maak het onderdeel van de offerte. Niet als optie, maar als vereiste. Een pentest zonder retest is een diagnose zonder behandeling.


15.8 Referentietabel

Topic IB Feature Route / Locatie
Findings Findings Management /dashboard/findings
Templates Standaard finding templates /dashboard/findings/templates/seed
CVSS CVSS 4.0 calculator Ingebouwd in Finding Editor
Evidence Evidence upload & management /api/findings/<id>/evidence
Notes Notes blueprint /dashboard/notes
Recordings Asciinema recordings player /dashboard/recordings
Rapport pandoc/LaTeX pipeline /dashboard/findings/rapport
Export JSON findings export /api/findings/export
Import JSON findings import /dashboard/findings/import
Evidence ZIP Evidence export als ZIP /api/findings/evidence/export

Samenvatting

Rapportage is het punt waarop al je technische briljantie wordt vertaald naar iets dat daadwerkelijk verandering teweegbrengt – of in een la belandt en vergeten wordt. Het verschil tussen die twee uitkomsten hangt niet af van hoe goed je kunt hacken, maar van hoe goed je kunt schrijven, communiceren, en opvolgen.

IB biedt de gereedschappen om dat proces te stroomlijnen: finding templates met OWASP, CWE en MITRE ATT&CK classificaties; een CVSS 4.0 calculator die de ernst van kwetsbaarheden consistent scoort; evidence management dat bewijsmateriaal aan findings koppelt; een notes-systeem dat je dagelijkse observaties omzet in rapportsecties; en een pandoc pipeline die alles samenvoegt in een professioneel document.

Maar gereedschappen zijn middelen, geen doelen. Het doel is niet een mooi rapport. Het doel is een veiliger netwerk. En dat vereist dat je rapport niet alleen gelezen wordt, maar ook uitgevoerd. Dat is uiteindelijk de echte test – niet of je binnen kon komen, maar of je ervoor hebt gezorgd dat de volgende keer de deur dicht is.