Zum Inhalt springen
Alle Beiträge

· 7 Min. Lesezeit

Pentest-Bericht mit KI schreiben: von Rohnotizen zum fertigen Report

Mach mit KI aus Pentest-Notizen und Scanner-Ausgaben einen kundenfertigen Bericht: Executive Summary, Findings mit CVSS v4, Remediation und Retest-Notizen.

Das Testen ist der spannende Teil. Bezahlt wird aber der Bericht, und der entsteht meist am Ende des Projekts, geschrieben von jemandem, der müde ist. Diese Anleitung zeigt, wie du mit Odin v1 aus Rohnotizen, Scanner-Ausgaben und beschriebenen Screenshots einen sauberen, kundenfertigen Pentest-Bericht machst, ohne Urteilsvermögen oder Kundengeheimnisse aus der Hand zu geben.

Wobei KI im Pentest-Bericht hilft und wobei nicht

Ein Sprachmodell ist gut in den Teilen des Reportings, die vor allem Schreibarbeit sind: knappe Notizen in ganze Sätze verwandeln, eine einheitliche Struktur über 30 Findings halten, eine Executive Summary schreiben, der auch nicht-technische Leser folgen können, und Remediation-Empfehlungen entwerfen, die zu dem Stack passen, den du beschreibst.

Eine Quelle der Wahrheit ist es nicht. Es hat das Ziel nicht gesehen. Es kann nicht bestätigen, dass ein Finding echt ist, dass deine Einstufung stimmt oder dass ein Reproduktionsschritt funktioniert. Behandle jeden Entwurf wie den ersten Durchgang eines Junior-Testers: nützlich, schnell und reviewbedürftig.

Gängige Assistenten bringen ein zweites Problem mit. Füge „authentifizierter Benutzer kann durch Ändern der ID die Rechnungen anderer Mandanten lesen“ ein, und manche fangen an, über unbefugten Zugriff zu belehren, statt das Finding zu schreiben. Odin v1 antwortet direkt, wenn der Kontext ein Bericht für einen autorisierten Auftrag ist, und genau darum geht es bei der Arbeit. Warum das wichtig ist, erklären wir in unserem Launch-Beitrag.

Bevor irgendetwas deinen Rechner verlässt: schwärzen

Deine Notizen enthalten Hostnamen des Kunden, interne IPs, Benutzernamen, manchmal Session-Tokens oder Passwort-Hashes. Entferne sie, bevor du irgendetwas an irgendeine API schickst.

Ein einfaches Regelset deckt das meiste ab:

  • Ersetze die Domains des Kunden durch Platzhalter wie client.example.com.
  • Ersetze interne und externe IPs durch Dokumentationsbereiche (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24) oder Tokens wie HOST-A.
  • Ersetze echte Benutzernamen durch user1, admin1.
  • Entferne Secrets vollständig. Ein Finding zu einem offengelegten Token braucht Typ und Fundort des Tokens, nicht seinen Wert.
  • Führe eine lokale Mapping-Datei, damit du im finalen Dokument die echten Werte wiederherstellen kannst.

Bei InterOdin werden Prompts und Antworten der API nie gespeichert. Für die Abrechnung bleiben nur Metadaten wie Token-Anzahl, Latenz und Status erhalten, und die Server stehen in Deutschland. Das ist eine gute Grundlage, ersetzt aber das Schwärzen nicht. Welche Daten die Projektumgebung verlassen dürfen, regelt dein Vertrag mit dem Kunden, also prüfe ihn zuerst.

Die Berichtsstruktur, die du anstreben solltest

Die meisten Kundenberichte haben dasselbe Grundgerüst. Gib dem Modell diese Struktur ausdrücklich vor, damit jeder Entwurf in derselben Form landet:

AbschnittZielgruppeInhalt
Executive SummaryManagementScope, Gesamtrisiko, die 3 wichtigsten Probleme, geschäftliche Auswirkungen, Prioritäten
Scope und MethodikBeideZiele, Zeitraum, Testart, Rules of Engagement, Einschränkungen
FindingsEngineersEin Block pro Finding, nach Schweregrad sortiert
Remediation-RoadmapBeideQuick Wins vs. längerfristige Fixes, gruppiert nach Verantwortlichen
Retest-NotizenBeideStatus pro Finding nach dem Zeitfenster für die Behebung

Jeder Finding-Block sollte enthalten: Titel, Schweregrad, CVSS-v4-Vektor, betroffene Assets, Beschreibung, Auswirkung, Reproduktionsschritte, Nachweise, Remediation, Referenzen.

Eine Prompt-Vorlage für ein Finding

Hier ein realistischer Satz Rohnotizen aus einem autorisierten Webanwendungstest (bereits geschwärzt):

text
target: app.client.example.com (in scope per RoE section 2)GET /api/v2/invoices/{id} returns invoice JSONlogged in as user1 (tenant A), changed id 10442 -> 10443got invoice for tenant B, includes name, billing address, line itemsids sequential, tried 50 in a row, all returned 200no rate limit seenburp request saved as req-17.txtscreenshot 17: tenant B invoice in user1 session

Und ein Prompt, der daraus ein Finding macht:

text
You are writing one finding for a penetration test report for an authorizedengagement. Use only the facts in the notes. If something is missing, write[NEEDS TESTER INPUT] instead of guessing.
Output Markdown with these headings: Title, Severity, CVSS v4.0 vector,Affected assets, Description, Impact, Reproduction steps, Evidence,Remediation, References.
Rules:- Propose a CVSS v4.0 base vector and explain each metric choice in one line.- Reproduction steps must be numbered and reproducible by the client's  developers in their own test environment.- Remediation must be specific to the endpoint, then general.- Neutral, factual tone. No blame.
Notes:<paste notes>

Was du zurückbekommst: einen Titel in der Art von „Insecure Direct Object Reference in Invoice API Exposes Other Tenants' Data“, eine Beschreibung der fehlerhaften Autorisierungsprüfung auf Objektebene, einen Absatz zur Auswirkung, also der mandantenübergreifenden Offenlegung personenbezogener Daten und Rechnungsdaten, nummerierte Schritte mit zwei Testkonten in verschiedenen Mandanten und eine Remediation, die vorschreibt, die Mandantenzugehörigkeit bei jedem Objektzugriff serverseitig zu erzwingen, mit dem Hinweis, dass ein Wechsel zu zufälligen IDs allein kein Fix ist. Als Referenzen tauchen meist die OWASP API Security Top 10 (API1, Broken Object Level Authorization) und CWE-639 auf.

Für den Vektor kannst du etwa Folgendes erwarten:

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

dazu eine Zeile pro Metrik mit Begründung, zum Beispiel „PR:L, weil ein normales authentifiziertes Konto erforderlich ist“. Berechne den finalen Score immer selbst im offiziellen CVSS-v4.0-Rechner von FIRST und prüfe jede Metrik gegen das, was du tatsächlich beobachtet hast. Das Modell kann über Metriken argumentieren, aber für den Score in deinem Bericht bist du verantwortlich.

Ein Python-Skript, das aus Notizen ein Finding entwirft

Dieses Skript liest eine Notizdatei, wendet eine kleine Schwärzungstabelle an, schickt das Ergebnis an odin-v1 und schreibt einen Markdown-Entwurf. Es nutzt das offizielle OpenAI SDK mit der Base-URL von InterOdin (siehe die Anleitung zum OpenAI SDK).

python
import osimport reimport sysfrom pathlib import Path
from openai import OpenAI
SYSTEM = """You write findings for penetration test reports on authorizedengagements. Use only facts from the notes. Mark gaps as [NEEDS TESTER INPUT].Output Markdown with headings: Title, Severity, CVSS v4.0 vector, Affectedassets, Description, Impact, Reproduction steps, Evidence, Remediation,References. Explain each CVSS metric choice in one line."""
# Local mapping: real value -> placeholder. Keep this file out of the report.REDACTIONS = {    "portal.realclient.internal": "app.client.example.com",    "10.20.30.40": "192.0.2.10",    "j.doe": "user1",}
TOKEN_PATTERN = re.compile(r"(eyJ[\w-]+\.[\w-]+\.[\w-]+)|(Bearer\s+\S+)")

def redact(text: str) -> str:    for real, placeholder in REDACTIONS.items():        text = text.replace(real, placeholder)    return TOKEN_PATTERN.sub("[REDACTED-TOKEN]", text)

def main(notes_path: str) -> None:    notes = redact(Path(notes_path).read_text(encoding="utf-8"))
    client = OpenAI(        base_url="https://api.interodin.com/v1",        api_key=os.environ["INTERODIN_API_KEY"],    )    resp = client.chat.completions.create(        model="odin-v1",        messages=[            {"role": "system", "content": SYSTEM},            {"role": "user", "content": f"Notes:\n{notes}"},        ],    )
    out = Path(notes_path).with_suffix(".finding.md")    out.write_text(resp.choices[0].message.content, encoding="utf-8")    print(f"Draft written to {out}")

if __name__ == "__main__":    main(sys.argv[1])

Führe es pro Finding aus: python draft_finding.py notes/finding-17.txt. Gib den geschwärzten Text vor dem ersten echten Lauf einmal im Terminal aus, damit du genau siehst, was gesendet wird.

Scanner-Ausgaben und Screenshots

Scanner-Exporte sind voller Rauschen. Statt einen kompletten Report einzufügen, filtere ihn zuerst (nur die Plugin-IDs oder Templates, die du von Hand bestätigt hast), und lass das Modell dann zusammengehörige Probleme gruppieren. Zehn Zeilen „fehlender Security-Header“ gehören meist in ein Finding mit niedrigem Schweregrad und einer Liste betroffener Hosts, nicht in zehn Findings.

Odin akzeptiert nur Text, Bilder und PDFs lassen sich also nicht hochladen. Für das Reporting funktioniert das gut: Beschreibe jeden Screenshot in deinen Notizen in ein, zwei Zeilen („Screenshot 17: Rechnung von Mandant B in der Session von user1 sichtbar, Rechnungsnummer und Adresse angezeigt“). Das Modell verweist dann namentlich auf den Nachweis, und die echten, geschwärzten Bilder setzt du selbst ins finale Dokument.

Für große Projekte hat odin-v1 ein Kontextfenster von 1.000.000 Tokens, du kannst beim Schreiben der Executive Summary also alle geschwärzten Findings auf einmal übergeben. Für schnelle, repetitive Aufgaben wie das Vereinheitlichen von Finding-Titeln oder das Umformatieren von Referenzlisten ist odin-flash schneller und günstiger.

Executive Summary und Remediation-Roadmap

Sobald die Findings geprüft sind, erzeugst du die Zusammenfassung aus den Findings selbst, nicht aus deinen Rohnotizen:

text
Below are the reviewed findings from an authorized external and webapplication test. Write an executive summary for non-technical management:max 300 words, overall risk rating, the three issues that matter most and whyin business terms, and a prioritized next-steps list. Do not add findings.

Bitte dann um eine Remediation-Roadmap, die die Fixes nach Verantwortlichen (Entwicklung, Infrastruktur, Identity) und nach Aufwand gruppiert. Kunden handeln auf Basis von Roadmaps deutlich eher als auf Basis von Schweregrad-Tabellen.

Retest-Notizen

Ergänze nach dem Zeitfenster für die Behebung pro Finding einen kurzen Retest-Block: Datum, was erneut getestet wurde, Ergebnis (behoben, teilweise behoben, nicht behoben) und Nachweis. Ein nützlicher Prompt ist: „Hier sind das ursprüngliche Finding und meine Retest-Notizen. Schreib einen Retest-Statusblock mit höchstens 80 Wörtern und markiere jede Abweichung zwischen den ursprünglichen Reproduktionsschritten und dem, was ich erneut getestet habe.“ Der letzte Teil fängt Retests ab, die stillschweigend etwas anderes getestet haben.

Checkliste vor der Abgabe

  • Jedes Finding wurde von einem menschlichen Tester mit Nachweis bestätigt.
  • Jeder CVSS-Score wurde im offiziellen Rechner berechnet.
  • Es sind keine [NEEDS TESTER INPUT]-Markierungen mehr übrig.
  • Platzhalter wurden nur im finalen Dokument auf die echten Werte zurückgeführt.
  • Nichts außerhalb des vereinbarten Scopes taucht im Bericht auf.

Wenn du mehr davon automatisierst, zum Beispiel mit einem Skript, das den kompletten Bericht aus einzelnen Finding-Dateien zusammensetzt, zeigt unser Beitrag zum Security-Tooling mit Claude Code auf Odin, wie so ein Projekt abläuft. Wer als Tester noch am Anfang steht und im Lab übt, findet vielleicht CTF-Training mit einem KI-Coach hilfreich.

Loslegen

Erstelle einen API-Key in der Konsole, setze ihn als INTERODIN_API_KEY und folge dem Quickstart. Halte jedes Projekt innerhalb seines schriftlich vereinbarten Scopes und seiner Rules of Engagement sowie innerhalb der Acceptable Use Policy.