Sur la stratégie de script intersite et de sécurité du contenu
Avez-vous envisagé la sécurité de votre application ce mois-ci? Voici quelques conseils de sécurité pour vous protéger des pirates informatiques et éviter les surprises fantasmagoriques.
Octobre est le mois du Mois national de sensibilisation à la cybersécurité . C'est donc un excellent prétexte pour parler de l'un des plus courants. types d'attaques dirigées contre les applications Web, Cross-Site Scripting et comment l'atténuer à l'aide d'une fonction de sécurité présente dans tous les navigateurs modernes appelée Politique de sécurité du contenu .
Script intersite
Le script inter-sites ou XSS en abrégé, est l'un des problèmes de sécurité les plus courants dans les applications Web de nos jours. Dans XSS, un attaquant parvient à injecter son propre code dans notre application. Ce code sera ensuite exécuté lorsque les utilisateurs visitent la page, ce qui lui permet de voler des cookies ou de consigner toutes les pressions de touche.
Pour en faire la démonstration, nous avons construit une petite application avec un formulaire qui est vulnérable à l'XSS . L'application fonctionne correctement: nous entrons du texte dans l'élément textarea
puis appuyez sur le bouton Soumettre et notre commentaire est ajouté à la liste. Cependant, remarquez ce qui se passe lorsque nous saisissons du code HTML sur le terrain, comme React est génial !
:
:
OWASP XSS .) en tant qu'enfants d'un élément. Si nous voulons vraiment restituer du HTML non échappé, nous devons utiliser un accessoire spécial nommé
dangereusementSetInnerHTML
:
export
default
classe ListOfComments: extension React.Component {
.
render () {
const {comments} =
ce
.props;
return
(
{comments.map ((comment) => (19459015]
<1965 li
clé = {commentaire}
dangereusement SetInnerHTML = {{__html: comment}}
/>
)}}
]
}
Bien qu'il existe des cas d'utilisation valables pour dangereusementSetInnerHTML
tels que le rendu du code HTML assaini provenant de votre serveur, j'essayais de minimiser son utilisation, car il est très facile de faire quelque chose de mal et de s’ouvrir à une attaque.
Politique de sécurité du contenu
Le problème qui sous-tend une attaque XSS est que le navigateur ne sait pas à quelles sources de code faire confiance. Ma balise et votre balise injectée
sont toutes les deux valides, le navigateur les exécutera donc toutes.
La politique de sécurité du contenu est une fonctionnalité de sécurité présente dans tous les navigateurs modernes qui nous permet de répertorier quelles sources sont approuvées par notre application Web, afin que le navigateur puisse bloquer tout le reste. Si votre nom figure sur la liste des invités, vous pouvez participer à la fête. sinon, vous restez à l'extérieur.
Il existe deux façons de déclarer une stratégie de sécurité du contenu: via un en-tête HTTP Content-Security-Policy
lors du traitement de votre page HTML et via un tag . .
Dans notre exemple d'application, nous n'avons pas le contrôle sur les en-têtes HTTP, nous allons donc utiliser une balise . Ajoutons la politique de sécurité du contenu la plus restrictive possible,
par défaut, src 'none'
qui indique en gros au navigateur de ne faire confiance à aucune source, et voyons ce qui se passe:
[19659002] <
html
>
tête
>
[19659000]
<
meta
http-equiv
=
"Politique de sécurité du contenu"
] content
=
"default-src 'none'"
/>
/
</
head
>
</
<19659022]
corps
>
</
body
>
<1945 html
>
Eh bien, tout semble cassé:
Content Security Policy de MDN qui décrit toutes les directives et valeurs possibles que nous pouvons spécifier.
Passons un à un.
Fixing Script Erreurs
La première erreur concerne les scripts bloqués:
Refuse d'évaluer une chaîne en tant que JavaScript, car 'unsafe-eval' n'est pas une source de script autorisée dans la directive suivante relative à la politique de sécurité du contenu: “default-src 'aucun'". Notez que 'script-src' n'a pas été défini explicitement, donc 'default-src' est utilisé comme solution de secours.
Nous n'avons pas fourni de stratégie script-src
le navigateur est donc retourné à ce qui est spécifié comme default-src
(qui est 'aucun'
) et a refusé de charger tous les scripts. Il semble que les personnes hébergeant notre exemple d'application, StackBlitz exécutent notre code via eval
nous devrons donc l'autoriser en tant que source dans notre script [src
directive:
<
meta
http-equiv
=
"Politique de sécurité du contenu"
"default-src 'none'; script-src 'unsafe-eval'"
/>
(Notez que vous ne voudriez pas faire cela dans une application réelle. Permettre à aucun des le unsafe - *
des sources comme unsafe-eval
ou unsafe-inline
est probablement une très mauvaise idée!)
Correction des erreurs de style
La deuxième erreur concerne le blocage des styles:
a refusé de charger la feuille de style 'https://cdn.jsdelivr.net/npm/@progress/kendo-theme-default@latest/dist/all.css' car elle enfreint la directive suivante sur la politique de sécurité du contenu: «default-src none » ». Notez que 'style-src' n'a pas été défini explicitement, donc 'default-src' est utilisé comme solution de secours.
De même, nous n'avons pas fourni de stratégie style-src
de sorte que le navigateur est retombé à de défaut-src
et a refusé de charger tous les styles. Nous pouvons spécifier le chemin exact de la feuille de style, un chemin partiel ou simplement le domaine. Nous spécifierons ici un chemin partiel, de sorte que tous les styles provenant de paquets à l'origine @progress
soient approuvés:
<
meta
http-equiv
=
"Content-Security-Policy"
Correction des erreurs de police
Les dernières erreurs concernent le blocage des polices:
A refusé de charger la police 'data: font / ttf; base64,…' car elle constitue une violation de la directive suivante relative à la politique de sécurité du contenu: «default-src 'none'». Notez que 'font-src' n'a pas été défini explicitement, donc 'default-src' est utilisé comme solution de secours.
Le fichier CSS ci-dessus semble inclure des polices codées en base64 à l'aide du protocole :
, nous devrons donc ajouter une directive font-src
qui autorise cela:
<
meta
http-equiv
=
"Content-Security- Politique "
Trial by Fire
Maintenant, l'application fonctionne à nouveau! Essayons notre attaque initiale en injectant
dans la page:
<
meta
http-equiv
=
"Contenu-Sécurité-Politique-Rapport-Seulement "
content
=
" default-src 'none' "
/>
nous verrions toutes les violations du CSP se dérouler dans le
Nous pouvons aller encore plus loin et utiliser la directive report-uri
pour demander au navigateur d'envoyer toutes les violations à un terminal placé sous notre contrôle, afin que nous pouvons les regrouper dans un tableau de bord ou quelque chose du genre:
<
meta
http-equiv
=
"Contenu-Sécurité-Politique-Rapport-Seulement"
content
=
"default-src 'none'; report-uri / api / csp "
/>
Chaque fois que le navigateur rencontre une violation de notre CSP, il fera une demande POST
à / api / csp
avec contenu qui ressemble à ceci:
{
"csp-report": {
"referrer": "",
[1945925]. ]
"directive violée": "img-src",
"directive-effective": " img-src ",
" politique-originale ":" défaut-src 'aucune'; report-uri / api / csp ",
" disposition ":" rapport ",
" statut-code ": 0,
"script-sample": ""