Elk script van een derde partij op uw checkout-, login- of beheerpagina draait met dezelfde rechten als de gebruiker die de pagina laadt. Wordt de host die dat script levert gecompromitteerd, dan krijgt de aanvaller die rechten ook, vergelijkbaar met XSS. De oplossing begint bij weten welke scripts er laden. Daarna verwijdert u wat kan en pint of beperkt u de rest.
Weet wat er draait op de gevoelige pagina's
De OWASP cheat sheet over third-party JavaScript noemt drie risico's: verlies van controle over wijzigingen in uw clientapplicatie, uitvoering van willekeurige code op systemen van gebruikers en lekken van gevoelige informatie naar derden. Tot de voorbeelden behoren het Ticketmaster-incident uit 2018 en het onderzoek van ClearSky naar Magecart en de diefstal van betaalgegevens.
Maak de inventaris pagina voor pagina, te beginnen met checkout, login en beheer. Noteer per script de URL, de businessowner, de reden van bestaan en de manier waarop het binnenkomt. OWASP beschrijft drie routes: code van de leverancier die in de pagina is geplakt, een <script src> die naar de leverancier verwijst en een indirect verzoek via een tag manager.
De tag manager is het minst zichtbaar. Hij kan scripts van meerdere leveranciers teruggeven, en medewerkers kunnen via een webinterface wijzigen wat hij teruggeeft, zonder uw code aan te raken. Wijzigingen gaan live bij de eerstvolgende paginalading en de code is meestal geobfusceerd.
De HTML-broncode toont die scripts niet. Open de developer tools, ga naar het tabblad Network, doorloop de checkout en het inloggen en maak een lijst van elke host die een script levert.
Eerst verwijderen, dan mirroren
Vraag de eigenaar van elk item of het wel op die pagina thuishoort. Een marketingtag op een loginpagina of beheerpaneel heeft zelden een goed antwoord.
Voor scripts die blijven noemt OWASP in-house mirroring als verdediging. U host zelf een gecontroleerde kopie, zodat een derde partij die niet kan wijzigen en de leverancier het IP-adres, de referrer en de cookies van de bezoeker niet meer ontvangt. De prijs is onderhoud: een gemirrorde kopie mist de fixes van de leverancier, dus iemand moet de verantwoordelijkheid nemen voor opnieuw reviewen en verversen.
Verlaten leveranciers vormen een apart probleem. Als het domein dat een script host verloopt omdat de leverancier failliet is gegaan of het project heeft stopgezet, kan iemand het opnieuw registreren en kwaadaardige code publiceren. Een verdwenen leverancier in uw inventaris is op zichzelf al een bevinding.
Pin wat u houdt met Subresource Integrity
Met Subresource Integrity (SRI) geeft de pagina aan aan welke hash een bestand moet voldoen. De browser vergelijkt de download met die hash voordat hij een script uitvoert of een stylesheet toepast, en geeft een netwerkfout als ze verschillen. De SRI-gids van MDN geeft het commando om de hash te genereren:
cat FILENAME.js | openssl dgst -sha384 -binary | openssl base64 -A
Zet sha384- voor de uitvoer en plaats het resultaat in het element:
<script src="https://cdn.example.com/script.js"
integrity="sha384-..."
crossorigin="anonymous"></script>
De markup stelt een paar eisen:
- Het attribuut
crossoriginis verplicht. De browser weigert SRI bijno-cors-verzoeken, dus een tag zonder dit attribuut faalt altijd. - De CDN moet een
Access-Control-Allow-Origin-header sturen. Veel CDN's sturen*. - U kunt meerdere hashes opgeven. De browser gebruikt alleen de hashes van het sterkste aanwezige algoritme (SHA-256, SHA-384, SHA-512 in oplopende volgorde) en accepteert het bestand als er één overeenkomt. Zo kunt u tijdens een upgrade twee versies toestaan. De W3C-specificatie beschrijft hetzelfde gedrag.
SRI past bij bestanden die gelijk blijven totdat u ze zelf wijzigt. Een script dat de leverancier naar believen aanpast, faalt na elke wijziging de controle, en een tag manager-container is zo'n script. Beperk wie erin mag publiceren en houd hem weg van uw meest gevoelige pagina's.
Beperk met Content Security Policy
SRI bepaalt wat een bepaald bestand moet bevatten. Een Content Security Policy (CSP) bepaalt waar scripts überhaupt vandaan mogen komen. De CSP-gids van MDN adviseert de policy mee te sturen in de Content-Security-Policy-header op alle responses, niet alleen op het hoofddocument.
Een startpunt voor een gevoelige pagina somt de hosts op die u daadwerkelijk gebruikt:
Content-Security-Policy: script-src 'self' cdn.example.com; object-src 'none'
Zodra er een script-src- of default-src-directive is, wordt inline JavaScript geblokkeerd tenzij u het expliciet toestaat. MDN raadt aan 'unsafe-inline' te vermijden, omdat het een groot deel van het nut van een CSP tenietdoet. Waar u inline scripts nodig hebt, gebruikt u een nonce: per response gegenereerd, onvoorspelbaar en door een template ingevoegd. Voor statische pagina's stelt MDN hashes voor, waarbij externe scripts dan ook het attribuut integrity nodig hebben.
OWASP stelt ronduit dat een data layer geen sandbox is, omdat tag manager-containers aangepaste JavaScript en HTML kunnen uitvoeren. Beperk de publicatierechten en review wijzigingen zoals u applicatiecode reviewt.
Vind de gaten zonder de site te breken
Met de Integrity-Policy-header blokkeert de browser scripts zonder integrity-attribuut of scripts die in no-cors-modus laden. Begin met de report-only-variant:
Integrity-Policy-Report-Only: blocked-destinations=(script), endpoints=(integrity-endpoint)
Het endpoint heeft een bijbehorende Reporting-Endpoints-header nodig. Overtredingen komen binnen als rapporten van het type integrity-violation, met de URL van het geblokkeerde script. Gepinde scripts verdwijnen uit de rapporten, dus ze vormen geen volledige scriptinventaris.
Als er geen rapporten meer binnenkomen, kunt u volgens MDN veilig blokkeren zonder dat gebruikers er iets van merken. Een tag manager-container die u niet kunt pinnen blijft rapporten genereren, dus pagina's die er een laden blijven op report-only. De headers die uw pagina's sturen, kunt u bekijken met onze HTTP-headerchecker.
Waar u moet beginnen
- Maak de inventaris voor checkout-, login- en beheerpagina's vanuit het tabblad Network en noteer voor elk script de eigenaar, het doel en de leveringsroute.
- Verwijder items die niemand kan verantwoorden, vooral op login- en beheerpagina's, en markeer elke leverancier waarvan het domein verlaten lijkt.
- Mirror bestanden die u wilt beheren en opnieuw wilt reviewen. Pin elk script dat u houdt: genereer SHA-384-hashes, voeg
integrityencrossorigin="anonymous"toe en test op staging. - Zet
Integrity-Policy-Report-Onlyin voor scripts en lees de rapporten. HandhaafIntegrity-Policypas als elk script op de pagina eenintegrity-attribuut heeft, en houd tag manager-pagina's op report-only. - Test op staging een
Content-Security-Policymetscript-srcenobject-src 'none', want die blokkeert inline scripts. Beperk wie in uw tag manager mag publiceren. Voor een externe toets kan een penetratietest deze pagina's meenemen.
