Een passieve externe scan. Elke bevinding bevat de ruwe waarneming die de scanner
heeft gedaan en een commando dat u zelf kunt uitvoeren om het te reproduceren - niets hier is geschreven door een model.
14 controlegroepen:
DNS herleiden en CAA controleren · SPF en DMARC controleren · TLS-certificaat en protocolversies inspecteren · HTTP-naar-HTTPS-omleiding testen · Beveiligingsheaders van de respons lezen · Cookie-attributen controleren · CORS-beleid onderzoeken · Zoeken naar versiebanners · Toegestane HTTP-methoden controleren · Homepage scannen op gemengde inhoud en onveilige formulieren · Zoeken naar blootgestelde configuratie- en versiebeheerbestanden · Controleren op mapoverzichten · robots.txt en security.txt lezen · Controleren op blootgestelde serviceports
Starten…
0%
Over Websitebeveiligingsscan
Veel scanners geven je een lettercijfer en een lijst enge woorden. Deze geeft ook een cijfer, maar elk punt dat eraf gaat hoort bij een bevinding die laat zien welk antwoord hij echt kreeg en met welk commando van één regel je hetzelfde antwoord krijgt. Een bevinding is dus iets wat je kunt controleren, niet iets wat je moet geloven.
Wat het doet
Controleert DNS en CAA, SPF en DMARC, het TLS-certificaat en TLS 1.0/1.1, de doorverwijzing naar HTTPS, beveiligingsheaders, cookie-attributen, CORS, versiebanners, HTTP-methoden, gemengde inhoud, 23 gevoelige paden, mapweergaven, robots.txt, security.txt en 12 servicepoorten.
Elke bevinding bevat de ruwe observatie en een shellcommando om het te reproduceren.
Controles die niet konden worden uitgevoerd, worden gerapporteerd als "niet gecontroleerd" - nooit stilletjes als geslaagd.
Rapporten worden gedownload als Markdown of JSON.
Hoe het werkt
1Voer een domein in waarvoor je verantwoordelijk bent.
2De scan voert passieve probes uit - gewone verzoeken, geen uitbuiting.
3Lees de bevindingen, elk met hun bewijs, en verifieer de bevindingen die ertoe doen.
Geen bevinding is verzonnen
De scanner bevat geen taalmodel. Ernst, impact en oplossing liggen per controle vast, en elke bevinding komt voort uit een echte waarneming. Het rapport op het scherm en de downloads als Markdown en JSON worden uit dezelfde bevindingen opgebouwd, zonder enig model.
Hoe het cijfer wordt berekend
De score begint bij 100 en verliest 34 punten per kritieke bevinding, 13 per hoge, 5 per gemiddelde en 1,5 per lage, met een plafond per ernst (hoog 45, gemiddeld 22, laag 9). Informatieve en geslaagde resultaten kosten niets. Vanaf 90 is het een A, vanaf 75 een B, vanaf 60 een C, vanaf 40 een D, daaronder een F. Eén openliggend .env-bestand of een bereikbare databasepoort brengt een verder schone site van 100 naar 66, een C; twee zulke bevindingen geven 32, een F.
Vals alarm voorkomen
Voordat de scanner paden zoals /.git/HEAD of /backup.sql probeert, vraagt hij een willekeurig adres op dat niet kan bestaan en noteert hoe de site antwoordt. Een pad telt alleen als openliggend wanneer het HTTP 200 geeft, afwijkt van dat niet-gevonden-referentieantwoord en past bij de handtekening van het bestand zelf. Een site die elke URL met zijn startpagina beantwoordt, kleurt dus niet rood van de kritieke bevindingen.
Een schoon rapport is geen certificaat
Dit zijn passieve controles tegen een draaiende site. Ze dekken geen applicatielogica, authenticatie, toegangscontrole of iets achter een login - de plekken waar echte inbreuken meestal beginnen. Controles die niet konden worden afgerond, staan precies hierom vermeld als niet gecontroleerd: een geslaagd resultaat afgeleid van een mislukte verbinding is een vals gevoel van veiligheid, en een scan zonder bevindingen betekent dat er niets is gevonden, niet dat er niets is.
Scan alleen wat van jou is
Scan domeinen die je bezit of waarvoor je schriftelijke toestemming hebt om te testen. De tool wijst hosts af die oplossen naar private of interne adressen, en is per IP snelheidsgelimiteerd, maar de toestemming blijft jouw verantwoordelijkheid.
Vragen
Is dit een actieve aanval?
Nee. Hij doet gewone GET-, HEAD- en OPTIONS-verzoeken, TLS-handshakes (ook pogingen met TLS 1.0 en 1.1), DNS-opvragingen via DNS-over-HTTPS van Cloudflare en eenvoudige TCP-verbindingen naar 12 poorten. Er wordt niets misbruikt, geen formulier verstuurd en niets gewijzigd.
Kan ik elke website scannen?
Alleen die je bezit of waarvoor je bevoegd bent te testen. Infrastructuur van derden scannen zonder toestemming kan onwettig zijn waar jij je bevindt.
Waarom staat er bij een controle "niet gecontroleerd"?
Omdat deze niet kon worden afgerond - meestal omdat er niets antwoordde op die oorsprong. Dit wordt eerlijk gerapporteerd in plaats van geregistreerd als geslaagd.
Kan ik het rapport exporteren?
Ja, als Markdown of JSON, gedurende een uur: het rapport blijft zo lang in de servercache zodat de downloads werken, en verloopt daarna. Geen enkele export gebruikt een model. Het gebruiksrecord bevat het aantal bevindingen en het cijfer, niet het domein.
Welke bestanden en poorten worden getest?
Bestanden: 23 vaste paden, waaronder /.git/HEAD, /.git/config, /.env, /.env.local, /.env.production, /.aws/credentials, /id_rsa, /backup.zip, /backup.sql, /dump.sql, /wp-config.php.bak, /phpinfo.php, /server-status, /actuator/env; elk wordt alleen gemeld als het antwoord overeenkomt met de eigen handtekening van dat bestand. /.well-known/security.txt telt in je voordeel als die gepubliceerd is. Poorten: een gewone TCP-verbinding, nooit een inlogpoging, naar 21 FTP, 23 Telnet, 25 SMTP, 3306 MySQL, 5432 PostgreSQL, 6379 Redis, 27017 MongoDB, 9200 Elasticsearch, 3389 RDP, 5900 VNC, 11211 Memcached, 8080. Een bereikbare databasepoort (MySQL, PostgreSQL, Redis, MongoDB, Elasticsearch) of Telnet krijgt de beoordeling kritiek.
Wat melden de SPF- en DMARC-controles?
Beide records worden uit de openbare DNS gelezen, ook voor een site die geen e-mail verstuurt, want zonder deze records kan iedereen e-mail versturen die van jouw domein lijkt te komen. Geen SPF-record is gemiddeld; een SPF-record met +all, dat elke server op internet toestaat, is hoog. Geen DMARC-record onder _dmarc is gemiddeld; p=none (of geen p=-tag) monitort alleen en is laag; p=quarantine of p=reject slaagt. Een domein dat helemaal geen e-mail verstuurt, kan v=spf1 -all publiceren.
Welke beveiligingsheaders worden gecontroleerd, en welke waarde slaagt?
Zes headers in het antwoord van je homepage. Ontbreken ze, dan zijn HSTS en Content-Security-Policy hoog, X-Content-Type-Options en X-Frame-Options gemiddeld, Referrer-Policy en Permissions-Policy laag. Strict-Transport-Security heeft een max-age van minstens 15552000 (180 dagen) nodig: korter is laag, max-age=0 is gemiddeld. Content-Security-Policy wordt als verzwakt gemeld (gemiddeld) als script-src 'unsafe-inline' toestaat, het beleid 'unsafe-eval' toestaat of default-src of script-src een los jokerteken * bevat. X-Content-Type-Options moet precies nosniff zijn. X-Frame-Options moet DENY of SAMEORIGIN zijn en is niet nodig als de CSP frame-ancestors instelt. Referrer-Policy wordt alleen gemeld bij unsafe-url of no-referrer-when-downgrade. Permissions-Policy hoeft alleen aanwezig te zijn. Bij elke ontbrekende of zwakke header staat een curl -sI-opdracht waarmee je het zelf kunt controleren.
Hoe controleert het cookie-attributen (Secure, HttpOnly, SameSite)?
Het leest elke Set-Cookie-header in het antwoord van je homepage (tot 12 cookies) en controleert bij elke cookie Secure, HttpOnly en SameSite. Ontbreekt Secure of HttpOnly, dan is dat gemiddeld; ontbreekt alleen SameSite, dan is het laag, en SameSite=None zonder Secure wordt apart gemeld omdat browsers die cookie weigeren. Een cookie met alle drie slaagt. De gebruikelijke oplossing is Secure; HttpOnly; SameSite=Lax (in Django: SESSION_COOKIE_SECURE, SESSION_COOKIE_HTTPONLY en SESSION_COOKIE_SAMESITE). De scan is niet ingelogd, dus cookies die pas na het inloggen worden gezet, ziet hij niet. Controleer het zelf met curl -sI https://your-site/ | grep -i set-cookie
Hoe werkt de CORS-controle, en wanneer is die kritiek?
Het stuurt één GET-verzoek naar je homepage met Origin: https://scanner-probe.example en leest Access-Control-Allow-Origin en Access-Control-Allow-Credentials in het antwoord. Geen Access-Control-Allow-Origin-header, of een vaste origin die de test-origin niet terugstuurt, slaagt. De test-origin terugsturen samen met Access-Control-Allow-Credentials: true is kritiek, want elke site die een ingelogde gebruiker bezoekt, kan dan zijn antwoorden lezen. De origin terugsturen zonder credentials is gemiddeld. Een jokerteken * is laag, of gemiddeld als credentials ook zijn toegestaan (browsers weigeren die combinatie). Alleen de homepage wordt getest en er gaat geen OPTIONS-preflight mee, dus test je API-routes apart met curl -sI -H "Origin: https://scanner-probe.example" https://your-site/api/ | grep -i access-control
Wat test de TLS-controle (verloopdatum van het certificaat, TLS 1.0 en 1.1)?
Hij maakt verbinding met poort 443 en valideert de certificaatketen en de hostnaam. Een certificaat dat niet valideert is hoog, een verlopen certificaat wordt daarnaast als kritiek gemarkeerd en een certificaat met minder dan 15 dagen resterend is gemiddeld; anders worden subject, uitgever, verloopdatum en SAN-namen als geslaagd getoond. Het onderhandelde protocol moet TLS 1.2 of TLS 1.3 zijn, alles ouder is hoog. Daarna probeert hij afzonderlijk een TLS 1.0- en een TLS 1.1-handshake: een server die een van beide accepteert krijgt een gemiddelde bevinding, omdat beide door RFC 8996 zijn afgeschaft. Kan de eigen OpenSSL van de scanner de oude versie niet aanbieden, dan wordt niets gemeld in plaats van gegokt. De oplossing in nginx is ssl_protocols TLSv1.2 TLSv1.3; Controleer de datums zelf met echo | openssl s_client -connect your-site:443 -servername your-site 2>/dev/null | openssl x509 -noout -dates
Controleert het of HTTP doorstuurt naar HTTPS?
Ja. Het vraagt http://your-site/ op zonder doorverwijzingen te volgen. Een 301 of 308 naar een https://-adres slaagt. Een 302, 303 of 307 naar HTTPS is laag, omdat browsers een tijdelijke doorverwijzing niet onthouden en elk nieuw bezoek begint met een onversleuteld verzoek. Een pagina die via onversleuteld HTTP wordt geleverd (antwoord 2xx) is hoog. Antwoordt poort 80 helemaal niet, dan is dat informatief, geen fout. De oplossing in nginx is server { listen 80; return 301 https://$host$request_uri; }, voeg daarna Strict-Transport-Security toe. Controleer het zelf met curl -I http://your-site/
Welke HTTP-methoden markeert het (TRACE, PUT, DELETE)?
Het stuurt één OPTIONS-verzoek naar je homepage en leest de Allow-header, of Access-Control-Allow-Methods als Allow ontbreekt. Worden TRACE, TRACK, PUT of DELETE aangeboden, dan is dat gemiddeld; PATCH of CONNECT alleen zijn laag; alleen standaard leesmethoden is geslaagd. Stuurt de server geen van beide headers, dan wordt niets gemeld. Dat een methode wordt aangeboden, bewijst niet dat ze werkt, dus controleer het voordat je iets wijzigt. TRACE kan de headers van het verzoek, cookies inbegrepen, terugsturen naar de aanroeper (Cross-Site Tracing). nginx weigert TRACE standaard; zet bij Apache TraceEnable Off. Beperk PUT en DELETE tot de API-routes die ze nodig hebben, achter authenticatie. Controleer het zelf met curl -X OPTIONS -i https://your-site/
Hoe herkent het directory listing ("Index of /")?
Het vraagt 7 paden op: /, /static/, /assets/, /uploads/, /images/, /files/ en /backup/. Een pad dat HTTP 200 geeft met een pagina waarvan de titel of hoofdkop begint met "Index of /", wordt als gemiddeld gemeld (CWE-548), omdat de lijst bestanden toont die nergens gelinkt zijn, zoals back-ups, exports en oude versies. Doet geen enkel pad dat, dan is de controle geslaagd; is de site onbereikbaar, dan wordt ze als niet uitgevoerd gemeld. De oplossing in nginx is autoindex off; (de standaard, zoek dus naar een expliciete autoindex on), bij Apache Options -Indexes, en haal daarna alles wat gevoelig is uit de webroot. Controleer het zelf met curl -s https://your-site/uploads/ | head -20
Vindt het gemengde inhoud en formulieren die via HTTP verzenden?
Ja, op de homepage. Het leest de HTML zoals die wordt geleverd (er wordt geen JavaScript uitgevoerd) en somt elke script-, link-, iframe- of img-tag op waarvan src of href met http:// begint. Zit er een .js- of .css-bestand tussen, dan is de bevinding middel, omdat een onderweg vervangen script of stylesheet binnen je HTTPS-pagina draait; alleen afbeeldingen en frames is laag; geen enkele is geslaagd (CWE-311). Een formulier waarvan de action met http:// begint, krijgt hoog (CWE-319), omdat alles wat erin wordt getypt, wachtwoorden inbegrepen, onversleuteld wordt verstuurd. De oplossing: zet die URL's om naar https:// of maak ze relatief, en voeg de header Content-Security-Policy: upgrade-insecure-requests toe als vangnet. Controleer het zelf met curl -s https://your-site/ | grep -Eo "(src|href|action)=.http://[^ >]*"
Wat controleert het in robots.txt en security.txt?
robots.txt: het haalt /robots.txt op en leest, als dat HTTP 200 als tekstbestand geeft, de Disallow-regels in de eerste 8000 tekens. Een Disallow-pad met admin, internal, private, backup, config, staging, test, api, secret, dev erin krijgt laag (CWE-200): robots.txt is openbaar en vraagt alleen nette crawlers weg te blijven, dus die paden opsommen maakt ze juist bekend. Bescherm ze met een login en gebruik noindex om pagina's uit zoekmachines te houden. security.txt: het vraagt /.well-known/security.txt op, de plek die RFC 9116 voorschrijft, en telt het in je voordeel als het bestand een Contact:-regel heeft. Een ontbrekend bestand kost geen punten. RFC 9116 vereist ook een Expires:-veld, dat de scan niet controleert, dus publiceer beide, bijvoorbeeld Contact: mailto:security@your-site, Expires: 2027-06-30T23:00:00Z. Controleer het zelf met curl -s https://your-site/.well-known/security.txt
Waar zoekt de CAA-controle naar en hoe voeg ik een CAA-record toe?
Hij vraagt de CAA-records (RFC 8659) op van de ingevoerde hostnaam, via DNS-over-HTTPS van Cloudflare. Vindt hij er een of meer, dan slaagt de controle en toont het bewijs er maximaal 5; vindt hij er geen, dan meldt hij "No CAA record" als laag, want dan mag elke publieke certificaatautoriteit een certificaat voor de naam uitgeven. Een CAA-record noemt de CA's die je echt gebruikt, bijvoorbeeld your-site. IN CAA 0 issue "letsencrypt.org", plus 0 iodef "mailto:security@your-site" om meldingen te ontvangen. Voeg per gebruikte CA een issue-regel toe, en een issuewild-regel als wildcardcertificaten van een andere CA moeten komen. Controleer het zelf met dig CAA your-site
Waarom meldt een scan van www of een subdomein geen CAA, SPF of DMARC?
Elke DNS-controle draait op precies de ingevoerde naam, dus www.example.com wordt opgevraagd als www.example.com, niet als example.com, en de drie records erven verschillend. CAA: een certificaatautoriteit die op www.example.com geen CAA-record vindt, gaat omhoog naar example.com en gebruikt dat (RFC 8659, sectie 3), dus "No CAA record" op een subdomein kan vals alarm zijn. DMARC: ontvangers vallen terug op het beleid van het organisatiedomein, dat met sp= een apart beleid voor subdomeinen kan instellen (RFC 9989, dat RFC 7489 vervangt), dus een ontbrekend record op _dmarc.www.example.com wordt meestal gedekt door _dmarc.example.com. SPF: er is geen overerving (RFC 7208), dus "No SPF record" klopt voor die naam; een hostnaam die geen mail verstuurt, kan v=spf1 -all publiceren. Een DNS-opvraging die mislukt, verschijnt ook als ontbrekend record. Scan ook het kale domein, of controleer met dig CAA example.com en dig TXT _dmarc.example.com