Cyberveiligheid is essentieel

Cyberveiligheid is steeds belangrijker geworden. Elke dag vinden er aanvallen plaats, wordt malware in computers geïnjecteerd, wordt ingebroken in accounts of worden data gestolen. Volgens Wordfence, de firewall plugin van WordPress, werden in 2020 90 miljard kwaadwillende pogingen gedaan om in te loggen op WordPress websites. Wordfence heeft login inbraak pogingen van ruim 57 million unieke IP adressen weten te voorkomen, bij een tempo van 2.800 aanvallen per seconde gericht op WordPress sites. De inbraakpogingen variëren van het raden van wachtwoorden, gebruik van gestolen wachtwoordlijsten, ‘dictionary attacks’ of traditionele brute-force attacks. Zie ook dit Wordfence rapport. In het dashboard van wordfence krijg je een indruk van de dreiging die heerst, wereldwijd maar ook op site-niveau (live traffic).

Het beveiligen van de website is daarom essentieel. Dat begint al bij het instellen van multi-factor authenticatie. Naast een gebruikersnaam en een wachtwoord, dien je na de login ook een code in te voeren die uit een authenticator app op je mobiele telefoon af te lezen is. Inbreken is dankzij twee verschillende methoden van authenticatie (vaststellen van de echtheid van de gebruiker).

Firewall

WordPress heeft diverse plugins voor het instellen van een firewall op je website. Het is absoluut noodzakelijk om een firewall in te stellen. Zoals hierboven aangegeven: maak gebruik maken van de plugin Wordfence Security. Na installatie gaat Wordfence eerst in lerende modus. Na verloop gaat de firewall over naar beschermende modus.

Je kunt in Wordfence bijhouden wie inlogt en welke hacking poging gedaan worden om in te loggen. Je kunt het aantal pogingen om in te loggen met een verkeerd wachtwoord of gebruikersnaam beperken. Veel geprobeerde gebruikersnamen zoals admin kun je blokkeren. Het statische IP adres dat aan je domeinnaam is verbonden kun je op de witte lijst van toegestane IP adressen zetten die niet door de firewall gecontroleerd worden. Gebruik zowel het ipv4 als ipv6 adres. Hiervoor is de IP range nodig (CIDR) die je op IP address guide kunt opvragen.

Http headers en content security policy (CSP)

HTTP response headers bevatten de informatie van de server (van de website) hoe de browser de website moet lezen. Het gaat bijvoorbeeld over de wijze waarop de browser de inhoud in de cache kan opslaan, wat voor soort inhoud geladen mag worden, welke software op de server draait, etc. Een belangrijk doel van de response headers betreft de beveiliging van de website. Doordat de server het beveiligingsbeleid over de website aan de browser instrueert, wordt bepaald hoe de website mag worden gebruikt, waarvoor wel en waarvoor niet. Deze headers dragen sterk bij aan de veiligheid van de website. Met de plugins http headers of GD security headers kun je regelen hoe de browser van de gebruiker de website moet lezen. Mozilla biedt referentiemateriaal met achtergrondinformatie bij de attributen en de op te geven waarden.

Het instellen van een werkende content security policy

Aangezien WordPress met veel inline scripts werkt en het niet makkelijk is om deze scripts aan te passen, is het oppassen met de instellingen bij de directives script-src en style-src. Na veel gepuzzel met de instellingen en lezen op de referentiesite van Mozilla is het gelukt om een instelling te vinden zodanig dat:

  • de scripts in de code van WordPress niet hoeven te worden aangepast;
  • de veiligheid van de site niet in het geding is; en
  • de site snel en bereikbaar is voor verschillende versies van browsers.
Sha256 hash protocol

Om het inlezen van scripts door de webbrowser op een veilige manier toe te staan, kun je gebruik te maken van de hash waarden van de inline scripts in combinatie met de het opgeven van de waarden ‘strict-dynamic’ en ‘unsafe-inline’ bij het directive script-src. Voor de hash-waarde maak je gebruik van het SHA-256 protocol. Dit is een berekening waarmee ondubbelzinnig de omvang en inhoud van een bestand (maakt niet uit wat) vastgesteld wordt. Bijvoorbeeld bij het overzetten van bestanden wordt de hash-berekening vergeleken met de opgegeven waarde. Komen deze overeen dan weet de computer dat de bestanden gelijk zijn. Om een voor content security policy doeleinden relevante hash te berekenen, kun je gebruik maken van de informatie in de browser zelf. Eerst stel je de waarden ‘strict-dynamic’ en ‘unsafe-inline’ in onder script-src. Vervolgens open je de foutenconsole in Google Chrome (F12 knop) en kun je aan de hand van de foutmeldingen nagaan wat de vereiste SHA-256 waarde moet zijn. De hash-waarde is ook te berekenen door het script in te lezen in een berekeningsalgoritme die vervolgens de hash-waarde berekent. Let goed op dat witte regels en spaties juist zijn overgenomen.

De waarde van de hash geef je vervolgens op in het script-src directive. Zie ook de  voorbeeldinstelling op securityheaders.com van de site adagia.eu. De hash-waarden zijn verkregen door eerst de instellingen op te zetten zonder de hash-waarden (deze ken je nog niet), vervolgens voeg je de hash-waarden toe en herkent de browser aan de in de header opgegeven hash-waarden dat deze overeenkomen met de hash-waarden van het in te lezen script of stijl. Klopt dit, dan wordt het script verwerkt.

Instellingen van content security policy bij A+ score van security headers voor adagia.eu

Een schermafdruk van de instellingen voor het content security policy voor adagia.eu

Configuratie van de apache webserver via htaccess

Een andere wijze om de security headers te implementeren is niet via een plugin, maar door direct in het .htaccess bestand (in directory web/wordpress) de wijzigingen op te nemen. Dit is handig wanneer plugins met elkaar interfereren. De ene plugin overschrijft dan de andere plugin. Wanneer je toegang hebt tot het besturingssysteem kun je de configuratie beter zelf aanpassen in het .htaccess bestand.

Hieronder heb ik een voorbeeld opgenomen van de instellingen die leiden tot een A+ kwalificatie volgens de site securityheaders.com.

# BEGIN HttpHeaders
<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
<FilesMatch "\.(php|html)$">
Header set X-Frame-Options "SAMEORIGIN"
Header set X-XSS-Protection "1; mode=block"
Header set X-DNS-Prefetch-Control "on"
Header set Content-Security-Policy "script-src 'self' 'sha256-Mt9khi0ZVvj+PrnxIVDN8hcwtdhMyA1k2mF25t7mad8=' 'sha256-hg+ivHNeEa6KAxtgsoGYuGRCpc+F/K9I87/N0eMVdts=' 'sha256-DQ9mpMPE5RhaW/KBgMEeMjRPLOdNQ9UEJUegyN0eYFE=' 'sha256-Cy/64Jv549vuHOsF8iS+skDw9LJUFa9nwZQLKWnFdmM=' 'sha256-r7KyHynNXX/FtjqOoC7OlklgO55joq+lWSfFCDReHuc=' 'sha256-zlv5L5pkEmtAIf5fvwoBWD2LVyqIve2ZO5DkEJdJ364=' 'sha256-MNQyMQUn42P7xYfcq6Knvnbi8n9Nq8FvhZtxvpNxcUM=' 'sha256-HldxyrN+1DCrYBRCz/+OONW7zhiB2PpEfnXNkZdFS6w=' 'sha256-cV4D8LTYyOphegTrBJUtOokGj0t8tFyt0TQ6CgkIA5M=' 'sha256-8//zSBdstORCAlBMo1/Cig3gKc7QlPCh9QfWbRu0OjU=' 'sha256-8caDTiD0WrC0oWvdVtAbTLxzJRqpayFg5S5n5bvQaas=' 'sha256-Yg75owfrteSqLnol7/NnqyR35W0p+BMrxGAOZ2QD4iw=' 'sha256-mQ7s7u7sisWwARE9ZSRSaclJacast+6d0TfH6QAbPLY=' 'sha256-YTksDt8qhRAAKgGVH3Q1C6WBMvuj8awlJsGscz8SOlg=' 'sha256-2quGLRQoiqhB7WLIqRtkYnQVH/Naye0O7uDKOhlpN1I=' 'sha256-ESkq7gT1Dn7qbtECN0JrEWYNwz5pBLYQQ6y6vpmDKFQ=' 'unsafe-eval' https://www.youtube.com; script-src-elem 'self' 'unsafe-inline' https://www.youtube.com; object-src 'none'; frame-ancestors 'self'; base-uri 'none'; frame-src https://www.youtube.com https://www.youtube-nocookie.com; worker-src 'none'; child-src 'none'; media-src 'self'; manifest-src 'none'; img-src 'self' https://globalleadership.org https://*.leadershipnow.com https://leadershipnow.com https://*.kinstacdn.com https://*.wordpress.com https://*.aitrends.com https://*.sciencedaily.com https://*.smartdatacollective.com https://*.ytimg.com https://*.amazonaws.com https://www.dataquest.io https://*.wp.com data:; font-src https://fonts.gstatic.com https://fonts.googleapis.com https://s.w.org 'self' data:; connect-src 'self'; form-action 'self'; upgrade-insecure-requests"
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS
Header set Referrer-Policy "strict-origin"
Header set Expect-CT 'max-age=2592000, enforce, report-uri="https://adagia.report-uri.com/r/d/ct/enforce"'
Header set Permissions-Policy "camera=(), geolocation=(self)"
Header set Cross-Origin-Embedder-Policy 'require-corp; report-to="https://adagia.report-uri.com"'
</FilesMatch>
</IfModule>
# END HttpHeaders

Voor de duidelijkheid: elke browser heeft een ontwikkelaarsconsole (functieknop F12) die de foutmeldingen aanduidt bij het weergeven van de pagina. Zie het voorbeeld hieronder. Op regel 250 is een foutmelding bij het lezen van een inline script. Dit komt doordat in het content security policy is opgegeven dat inline scripts zonder een hash waarde niet uitgevoerd mogen worden. Veilig dus maar wel vervelend. Om het script toch te laten uitvoeren, moet de sha256 hash waarde worden bepaald.

Rapportage via report-uri

In dit filmpje laten we zien hoe je het inline script kunt vinden en hoe je de hash waarde kunt bepalen op de site van report-uri. Je zult echter ook zien dat niet van alle blokkeringen de sha256 hash waarde in de console weergegeven wordt. Dan zul je de waarde moeten bepalen door het bestand zelf te openen. De bestanden zijn te vinden bij de webhosting provider of natuurlijk door in te loggen op het gebruikerssysteem van de NAS via SSH. Zoek naar de css bestanden, open deze, kopieer de gegevens en voer deze in op de site van report-uri. Je kunt de betreffende bestanden ook vinden via de thema-editor onder menu weergave/thema’s.

Afronding CSP

Zoals je ziet, vergt het enkele pogingen om te komen tot de definitieve security content policy instellingen. Zo kun je frame-ancestors op ‘none’ zetten maar dan kun je in WordPress niet de customizer functie goed gebruiken: je ziet dan niet hoe de instellingen de weergave direct op het scherm beïnvloeden. Zet je frame-ancestors op ‘self’, dan laat het scherm wel direct zien hoe de webpagina eruit komt te zien.

Met de rapportage functie van Report URI kun je rapporten laten opmaken over de effectiviteit van de security content policy of de Expect-CT header. Je moet hiervoor een account aanmaken en vervolgens configureer je het account op basis van je rapportage instellingen in de headers. Zo test je of de website door de instellingen van de policies blokkades opwerpt voor bezoekers.

Je kunt de beveiliging van je site controleren op Scan je site nu. Doel is natuurlijk om een A+ label te verkrijgen! Wil je de effectiviteit van de content security opties verder doorlichten, dan kan dit op CSP Evaluator of Mozilla Observatory.

Van de gangbare browsers is Mozilla Firefox het lastigst met het opsporen en adresseren van de foutmeldingen. Sommige foutmeldingen verwijzen niet naar een regel in de geladen html code maar naar een bestand dat niet benaderd kan worden. Zoals op deze site bijvoorbeeld het bestand onloadwff.js, een bestand dat te maken heeft met de lastpass extensie. Via de CSP headers is deze melding niet op te lossen; wel door de extensie uit te schakelen.

Subresource integrity

Deze website adagia.eu maakt ook gebruik van stijlbestanden die de website vooraf laadt:

 <link rel="stylesheet" id="ao_optimized_gfonts" href="https://fonts.googleapis.com/css?family=Roboto%3A300%2C400%2C500%2C700%7CRoboto+Slab%3A400%2C700&amp;display=swap" crossorigin="anonymous">

Aan de link kun je zien dat er gebruik wordt gemaakt van een content delivery network (CDN). De lettertypen worden geladen via google. Een CDN wordt voornamelijk ingezet voor stijlbestanden (css), javascript (js) en lettertype/font bestanden. Lekker snel en praktisch omdat je de bestanden niet zelf hoeft op te slaan, bij te houden, aan te passen, etc. En natuurlijk spaart het bandbreedte uit: je maakt je website sneller hierdoor.

Wat is subresource integrity?

Het heeft wel als nadeel dat je de CDN provider vertrouwt bij het laden van de inhoud. Mogelijk kan er toch met de inhoud geknoeid zijn: een zeer laag risico want het gaat om een gerenommeerde provider en miljoenen sites maken er gebruik van. Maar toch. Subresource Integrity (SRI) maakt het mogelijk om de integriteit van het CSS of JS bestand te controleren. Stel dat de CDN site gecompromitteerd is, dan zou een aanvaller de inhoud van het bestand kunnen aanpassen en miljoenen sites kunnen besmetten met een XSS aanval.

Met SRI wordt de sha256 hash waarde van het bestand gekoppeld aan het uit te voeren script. Als de browser vaststelt dat de opgegeven waarde niet overeenkomt met de waarde van het via de CDN ontvangen bestand, dan blokkeert de browser de uitvoering van het bestand. Hoe doe je dit? In de link tag voer je een integrity variabele op met de sha256 hash waarde van het bestand: zie ook de aangepaste link hieronder.

<link rel="stylesheet" id="ao_optimized_gfonts" href="https://fonts.googleapis.com/css?family=Roboto%3A300%2C400%2C500%2C700%7CRoboto+Slab%3A400%2C700&subset=latin%2Clatin-ext&ver=3.0.8" integrity="sha256-oq9GY76............JnqII/TeDUvGbjT8=" crossorigin="anonymous">
Bijzonderheden

Subresource Integrity is dus een veilige manier om te borgen dat de juiste bestanden ingeladen worden! Een check op de sha256 waarde kun je het beste opvragen via de developer console in de browser. Wanneer niet de bij het bestand behorende sha256 waarde is opgegeven, geeft de console de juiste waarde aan. Er zit wel een addertje onder het gras: Google maakt gebruik van user agent sniffing. Dat betekent dat afhankelijk van de (browser) client die het (css) bestand opvraagt, een ander css bestand wordt teruggestuurd. Met andere woorden, één sha256 waarde volstaat niet.

COEP header

Met behulp van een COEP header kan de webbrowser garanderen dat het laden van een cross-origin bron, zoals de fonts van googleapis, met toestemming van google(apis) geladen mogen worden. Wanneer de require-corp waarde is ingesteld, dan kan de pagina alleen van de betreffende bron laden wanneer deze bron het laden toestaat via een:

  • CORS  (Cross Origin Resource Sharing) header die cross-origin toelaat (kan ook via ACAO access-control-allow-origin * header); of
  • CORP (Cross Origin Resource Policy) header die het laden van sub resources van haar site toestaat.

In het htaccess configuratie bestand ziet de COEP header van deze site er zo uit:

 Header set Cross-Origin-Embedder-Policy 'require-corp'

0 reacties

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *

Deze website gebruikt Akismet om spam te verminderen. Bekijk hoe je reactie-gegevens worden verwerkt.