În prezent lucrez la îmbunătățirea securității unui site Drupal 8 prin implementarea unei politici de securitate a conținutului. Deoarece acest lucru este încă nou pentru mine, aș dori să primesc câteva informații despre strategia mea.
Configurare de bază relevantă
- Drupal 8, cu un patch personalizat care face
ckeditor.js
transmiteți non-urile la încărcarea pluginurilor sale, CKEditor fiind folosit doar de utilizatorii autentificați
- Kit de securitate, corecţionat pentru a oferi un cârlig de modificare pentru directivele CSP (https://www.drupal.org/project/seckit/issues/2844205#comment-14217383).
- Cod personalizat pentru a face modificări HTML-ului redat și configurației CSP din modulul Security Kit
Considerații preliminare
As dori sa nu folosesc „nesigur în linie”
pentru scripturi, dacă este posibil, dar în cele din urmă m-am gândit că acest lucru ar funcționa numai pentru anumite browsere.
De asemenea, aș dori să am un CSP adecvat pentru diferite situații (diferite browsere, autentificat vs neconectat).
Asta mă duce la această idee pt script-src
:
- folosind
nonce
și „strict-dinamic”
pentru browsere care acceptă CSP v3 și pagini necachabile
- utilizarea hash-urilor pentru browsere care acceptă CSP v3 și pagini care se pot stoca în cache
- folosind
„nesigur în linie”
împreună cu o listă bazată pe domenii pentru toate celelalte browsere
Motivul principal pentru a avea o distincție de browser este că nu am putut găsi o modalitate de a crea directivele CSP compatibile cu versiunea inversă fără o cantitate nerezonabilă de modificări la modulele de bază și contrib.
Ce am făcut până acum pe site-ul meu local de testare
Am adăugat o logică care folosește a nonce
și „strict-dinamic”
pentru browserele bazate pe Chrome pentru utilizatorii autentificați, pentru care paginile nu sunt stocate în cache, asigurându-se că nonces-urile sunt noi și unice pentru fiecare solicitare. Această logică se bazează pe șirul User Agent (care știu că este nesigur, dar nu văd o soluție mai bună).
Deci, practic, pentru browserul bazat pe Chrome, utilizatorii conectați vor primi un antet CSP cu acele politici CSP legate de script („nesigur în linie”
în script-src va fi ignorat de browserele care acceptă „strict-dinamic”
):
script-src 'self' 'unsafe-inline' *.googletagmanager.com *.google-analytics.com 'nonce-SECURENONCE' 'strict-dynamic';
script-src-attr 'unsafe-inline';
Utilizatorii anonimi vor primi un CSP care arată aproximativ astfel:
script-src 'self' 'unsafe-inline' *.googletagmanager.com *.google-analytics.com 'sha256-HASH_1' 'sha256-HASH_2' 'sha256-HASH_3' 'sha256-HASH_4' 'sha256-HASH_5' .. .;
script-src-attr 'unsafe-inline';
Browserele care nu sunt bazate pe Chrome primesc un antet CSP care arată astfel:
script-src 'self' 'unsafe-inline' *.google-analytics.com *.googletagmanager.com;
Am adăugat și logică, care, pe baza criteriilor de selecție de mai sus, adaugă fie nonce
atribute fiecărei etichete de script (pagini fără cache) sau coduri hash pentru fiecare etichetă de script (pagini stocate în cache). Acest lucru îmi permite, de asemenea, să am CKEditor să funcționeze bine în backend.
Se pare că funcționează bine pe diferitele browsere cu care am testat: Brave, Chrome, Edge, Firefox și Safari. Doar cei trei primii au un CSP pe care l-aș considera sigur (verificat și cu https://csp-evaluator.withgoogle.com/).
Este o abordare validă să ai:
- CSP-uri diferite pentru utilizatorii autentificați vs utilizatori anonimi?
- CSP-uri diferite pentru browsere diferite (sau diferite „browsere raportate” de fapt)?