VOORBEELDRAPPORT — gescand tegen onze eigen, expres kapotte testapp. Niet jouw app.
Samenvatting (passive (legacy site))
1 blokker
5 hoog
5 middel
3 ok
0 overgeslagen
Bevindingen
P1
HTTPS and HTTP→HTTPS redirect
MIDDEL
passive
Resultaat: gezakt
Wat we zagen
{
"note": "target submitted over http",
"tls": {
"ok": false,
"error": "[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1029)"
},
"http_redirect_status": 200,
"http_redirect_location": null
}
Fix-prompt (plak in Cursor/Lovable)
Our TLS handshake to your domain failed or the certificate is invalid: {"ok": false, "error": "[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1029)"}. Ensure the production domain has a valid, non-expired certificate (on Vercel/Netlify/Cloudflare this is automatic once the custom domain is verified) and that http:// redirects to https://.
P2
HSTS enabled
MIDDEL
passive
Resultaat: gezakt
Wat we zagen
{
"header": null
}
Fix-prompt (plak in Cursor/Lovable)
Add a Strict-Transport-Security header with max-age at least 15552000 and includeSubDomains on all production responses, e.g. `Strict-Transport-Security: max-age=31536000; includeSubDomains`. On Vercel set it in vercel.json headers; on Netlify in _headers; on Cloudflare via a Transform Rule.
P3
Security headers
HOOG
passive
Resultaat: gezakt
Wat we zagen
{
"csp": null,
"x_content_type_options": null,
"x_frame_options": null,
"referrer_policy": null,
"missing": [
"Content-Security-Policy",
"X-Content-Type-Options: nosniff",
"X-Frame-Options / CSP frame-ancestors",
"Referrer-Policy"
]
}
Fix-prompt (plak in Cursor/Lovable)
Add these response headers on production: Content-Security-Policy; X-Content-Type-Options: nosniff; X-Frame-Options / CSP frame-ancestors; Referrer-Policy. Minimal safe set: `X-Content-Type-Options: nosniff`, `X-Frame-Options: DENY` (or a CSP with frame-ancestors 'self'), `Referrer-Policy: strict-origin-when-cross-origin`, and a Content-Security-Policy that at least restricts default-src. Configure in vercel.json / _headers / Cloudflare Transform Rules.
P4
Exposed sensitive files
OK
passive
Resultaat: geslaagd
Wat we zagen
{
"checked": [
"/.env",
"/.env.local",
"/.env.production",
"/.git/config",
"/.git/HEAD",
"/config.json",
"/appsettings.json"
],
"exposed": []
}
P5
Secrets in client bundle
OK
passive
Resultaat: geslaagd
Wat we zagen
{
"sources": [
"http://127.0.0.1:8788"
],
"found": []
}
P6
Mail authentication (SPF/DMARC)
HOOG
passive
Resultaat: gezakt
Wat we zagen
{
"domain": "127.0.0.1",
"spf": [],
"dmarc": [],
"dmarc_policy": null
}
Fix-prompt (plak in Cursor/Lovable)
Mail-auth gaps for 127.0.0.1: no SPF record; no DMARC record. Your sign-up, magic-link and password-reset emails may be spoofable or land in spam. Publish an SPF TXT record for your sending provider, a DMARC record at _dmarc.127.0.0.1 moving toward `v=DMARC1; p=quarantine; rua=mailto:you@127.0.0.1`, and enable DKIM signing in your email provider (Resend/Postmark/Lettermint/etc).
P7
Backend fingerprint
OK
passive
Resultaat: geslaagd
Wat we zagen
{
"supabase_url": null,
"anon_key_present": false
}
L1
Verouderde server-/platformversie
MIDDEL
passive
Resultaat: gezakt
Wat we zagen
{
"server": "Apache/2.2.15 (CentOS)",
"x_powered_by": "PHP/5.4.16",
"eol_hints": [
"PHP 5",
"Apache 2.2"
]
}
Fix-prompt (plak in Cursor/Lovable)
De server laat in zijn headers een oude, end-of-life versie zien (PHP 5, Apache 2.2). Software die geen updates meer krijgt, heeft bekende, ongepatchte kwetsbaarheden. Werk de server/PHP-versie bij naar een ondersteunde versie en verberg de versie in de Server/X-Powered-By header.
L2
Verouderd CMS (versie zichtbaar)
HOOG
passive
Resultaat: gezakt
Wat we zagen
{
"generator": "WordPress 4.7.1",
"cms": "WordPress",
"version": "4.7"
}
Fix-prompt (plak in Cursor/Lovable)
De site draait op een oude, publiek zichtbare versie van WordPress (4.7). Versies die zo ver achterlopen hebben publiek bekende kwetsbaarheden waarvoor kant-en-klare exploits bestaan. Werk WordPress en de plugins/thema's bij naar de actuele versie en haal de versievermelding (generator-tag, readme.html) weg.
L3
Publieke back-up/databasebestanden
BLOKKER
passive
Resultaat: gezakt
Wat we zagen
{
"checked": [
"/backup.zip",
"/backup.tar.gz",
"/backup.sql",
"/db.sql",
"/database.sql",
"/dump.sql",
"/site.zip",
"/www.zip",
"/wp-config.php.bak",
"/wp-config.php~",
"/config.php.bak",
".env.bak",
"/.env.save"
],
"exposed": [
{
"path": "/backup.zip",
"content_type": "application/zip"
},
{
"path": "/wp-config.php.bak",
"content_type": "application/octet-stream"
}
]
}
Fix-prompt (plak in Cursor/Lovable)
Deze back-up-/databasebestanden zijn publiek te downloaden: /backup.zip, /wp-config.php.bak. Daarin zit vaak je complete database (klantgegevens) en/of je configuratie met wachtwoorden. Verwijder ze onmiddellijk van de server en ga ervan uit dat de inhoud gelekt is: wijzig de betrokken wachtwoorden en sleutels.
L4
Open directory listing
MIDDEL
passive
Resultaat: gezakt
Wat we zagen
{
"checked": [
"/uploads/",
"/files/",
"/backup/",
"/backups/",
"/images/",
"/wp-content/uploads/",
"/sites/default/files/"
],
"listing": [
"/wp-content/uploads/"
]
}
Fix-prompt (plak in Cursor/Lovable)
Deze mappen tonen een openbare bestandslijst: /wp-content/uploads/. Bezoekers kunnen zo door je bestanden bladeren en dingen vinden die niet bedoeld zijn om te delen. Zet directory listing uit (Options -Indexes in Apache, autoindex off in nginx).
L5
Blootgestelde VCS-/editor-metadata
HOOG
passive
Resultaat: gezakt
Wat we zagen
{
"checked": [
"/.svn/entries",
"/.hg/store/00manifest.i",
"/.DS_Store",
"/.git/HEAD"
],
"exposed": [
"/.svn/entries"
]
}
Fix-prompt (plak in Cursor/Lovable)
Versiebeheer- of editor-metadata is publiek bereikbaar: /.svn/entries. Daarmee kan iemand (delen van) je broncode of mappenstructuur reconstrueren, inclusief sleutels die ooit zijn vastgelegd. Blokkeer toegang tot .git, .svn, .hg en .DS_Store op de server.
L6
Publiek bereikbaar beheerpaneel
INFO
passive
Resultaat: gezakt
Wat we zagen
{
"checked": [
"/wp-admin/",
"/wp-login.php",
"/administrator/",
"/user/login",
"/admin",
"/admin/login"
],
"reachable": [
{
"path": "/wp-admin/",
"status": 302
},
{
"path": "/wp-login.php",
"status": 200
}
]
}
Fix-prompt (plak in Cursor/Lovable)
Je inlog-/beheerpagina is publiek bereikbaar: /wp-admin/, /wp-login.php. Dat is normaal, maar wel het doelwit voor geautomatiseerde inlogpogingen. Overweeg two-factor, een inloglimiet (rate limiting) en eventueel IP-beperking of een extra wachtwoord op de map.
L7
Gelekte phpinfo()
HOOG
passive
Resultaat: gezakt
Wat we zagen
{
"checked": [
"/phpinfo.php",
"/info.php",
"/test.php",
"/i.php"
],
"exposed": [
"/phpinfo.php"
]
}
Fix-prompt (plak in Cursor/Lovable)
Er staat een publieke phpinfo()-pagina online (/phpinfo.php). Die toont je volledige serverconfiguratie: paden, modules, versies en soms omgevingsvariabelen met geheimen. Verwijder dit bestand van de server.
L8
WordPress: gebruikers-enumeratie / XML-RPC
MIDDEL
passive
Resultaat: gezakt
Wat we zagen
{
"issues": [
{
"type": "user_enumeration",
"via": "/wp-json/wp/v2/users",
"count": 2,
"sample": [
"admin",
"jan"
]
},
{
"type": "xmlrpc_enabled",
"via": "/xmlrpc.php"
}
]
}
Fix-prompt (plak in Cursor/Lovable)
Op deze WordPress-site geldt: je WordPress-gebruikersnamen zijn publiek op te vragen (via de REST-API), waardoor aanvallers gericht wachtwoorden kunnen gaan raden; en xmlrpc.php staat open, wat misbruikt wordt voor massale inlogpogingen en als DDoS-versterker. Beperk de REST-API user-endpoint, zet xmlrpc.php uit als je het niet gebruikt, en gebruik two-factor plus een inloglimiet.
Webcontroleur is een geautomatiseerde technische scan, geen beveiligingsgarantie of juridisch advies. Deze passieve scan keek alleen naar publiek toegankelijke signalen. Momentopname.