Utiliser les entêtes HTTP "de sécurité", c'pas d'la tarte - GuiGui's Show
Utiliser les entêtes HTTP "de sécurité", c'pas d'la tarte
TL;DR : HSTS c'est bien si ta conf' TLS est propre ; HPKP c'est du passé ; Expect-CT me semble être en partie aussi pipeau que CAA ; Referrer-Policy est cool au sein d'un intranet / webmail / agrégateur RSS web ou autre ressource web privée et inutile au-delà ; X-Frame-Options, c'est du passé ; X-XSS-Protection et X-Content-Type-Options, ça ne mange pas de pain même si le gain est faible et que ce n’est pas encore normalisé ; Content-Security-Policy est loin d'être simple en pratique, même sur un logiciel qui se veut être simple comme Shaarli, car ça nécessite une parfaite connaissance du code de l'application web et des compromis utilisabilité / sécurité qui me semblent être très vite déconnants.
Toujours à la recherche de la hype en 2020 et m'étant fait tej' par TLS 1.3 et HTTP/2, je me demande quels entêtes HTTP trop stylés ajouter dans la configuration de mes serveurs web.
HTTP Strict Transport Security (HSTS), c'est plié : j'utilise une autorité de certification x509 maison, ce qui est incompatible.
HTTP Public Key Pinning Extension for HTTP (HPKP), c'est compliqué. On a vite fait de faire de grosses erreurs durables (même contre sa volonté, en raison de la fluctuation de ce que les autorités de certification incorporent dans un certificat x509 et en fonction des implémentations logicielles…), ce qui bloque l'accès au site web. Ça serait un deal à examiner si je n'avais pas déployé DANE TLSA, une solution concurrente au même problème qui propose une deuxième chaîne de certification via le DNS. De plus, je ne pense pas qu'un faux certificat x509 émis pour mon petit site de bouseux fasse partie de mon modèle de menaces… Au final, HPKP a été déprécié par son créateur, Google et retiré de Chrome. Affaire classée, donc.
Expect-CT indique au navigateur web de vérifier que le certificat x509 présenté par le serveur est bien publié dans Certificate Transparency, une base de donnée publique dans laquelle les autorités de certification peuvent ajouter (impossible de modifier et de supprimer) tous les certificats qu'elles génèrent… sauf quand elles se font vraiment pirater jusqu'à l'os. C'est là le hic. Je ne suis donc pas convaincu du gain foudroyant apporté par cet entête. De toute façon, j'utilise une autorité de certification maison qui ne publie donc pas dans Certificate Transparency, donc je ne suis pas éligible.
Referrer-Policy indique au navigateur web si, quand un utilisateur clique sur un lien présent sur un site web, il doit dire au site web de destination d'où il vient. On peut interdire toute communication ou demander à ce que seul le domaine soit communiqué et faire des mélanges genre communiquer l'URL complète si la destination du lien est le même site web et ne rien dire si la destination est externe, par exemple. Même possibilité de mélange si le site web de destination propose le même niveau de sécurité (comprendre HTTPS) que le site web source ou non. Je suis mitigé. Je vois très bien l'intérêt de cet entête pour un intranet ou un webmail ou un agrégateur RSS web , par exemple, mais pas pour mes sites web persos… Des extensions pour navigateurs web, comme Smart Referer permettent déjà de configurer l'envoi (ou non) du referrer, et, au moins, ça fonctionne pour tous les sites web consultés par un utilisateur, pas juste pour ceux qui ont mis un entête. L'utilisateur ne devrait pas compter sur l'administrateur d'un site web pour préserver sa vie privée.
X-Frame-Options est déprécié et est remplacé par l'attribut « frame-ancestors » dans la version 2 de Content Security Policy, donc affaire classée.
X-XSS-Protection indique au navigateur web de bloquer les tentatives d'exploitation de failles XSS les plus triviales. Ça ne mange pas de pain. J'ajoute donc cet entête à mes configurations : X-XSS-Protection "1; mode=block".
X-Content-Type-Options indique au navigateur de ne plus faire de MIME sniffing, c'est-à-dire d'interprétation du type d'un fichier quand le serveur web ne le précise pas ou que le navigateur web pense qu'il est erroné. Ça évite des attaques par fichiers malveillants spécifiquement fabriqués pour une attaque. Son utilisation suppose que le site web qui envoie cet entête soit irréprochable sur les types de fichier qu'il envoie. Mais, contrairement à HPKP, il n'y a pas de sanction durable dans le temps si ce n'est pas le cas. Donc ça ne mange pas de pain, donc j'ajoute cet entête à mes configurations : X-Content-Type-Options "nosniff".
Au début, j'envisageais de positionner la valeur « default-src 'none'; frame-ancestors 'none'; script-src 'none'; style-src 'self'; img-src 'self'; form-action 'self'; ». Dans l'ordre, ça dit ce qui suit. Tout ce qui n'est pas défini sera bloqué. Ce site ne peut pas être inclus dans un autre. Le seul CSS autorisé est celui provenant de la même origine (même protocole + nom de domaine + port). Même chose pour les images (comme les miniatures de vidéos ou d'images proposées par shaarli). Les formulaires peuvent uniquement être envoyés à une cible de même origine.
Rien que là, il y a des pièges. Il y a les non-dits, comme le fait que les scripts « inline » (insérés directement dans le XHTML) sont interdits de base sauf mention explicite. Il y a des différences de comportements. Je n'ai pas besoin de préciser « script-src », « font-src », « child-src », « object-src », « manifest-src », « media-src », « worker-src », « connect-src » car, en cas d'absence, un repli sur « default-src » est prévu. En revanche, il n'y a pas de repli pour form-action ou frame-ancestors, donc aucun blocage par défaut. Il y a des subtilités. « plugin-types » est un sous-type de « object-src », par exemple. Il faut donc lire la norme ou sa vulgarisation avec attention, ce qui est jamais top en matière de sécurité.
Ensuite, la définition CSP toute simple ci-dessus ne fonctionne pas avec shaarli.
Le thème par défaut et le plugin QR code (que j'ai tenté de désactiver à plusieurs reprises, mais il semble bien enraciné) utilisent du JavaScript (et, si pas de JS, un clic sur un QR code envoie l'utilisateur sur le site web qrfree.kaywa.com avec le QR code affiché pleine page…). Il faut donc remplacer « script-src 'none'; » par « script-src 'self'; ». Encore pire, le thème et le bookmarklet nécessitent l'usage de Javascript inline. Il faut donc remplacer « script-src 'self' » par « script-src 'self' 'unsafe-inline'; ». Ça enlève une grande partie de l'intérêt de CSP puisqu'un attaquant pourrait justement injecter du JS inline ;
L'affichage des miniatures de vidéo Youtube va chercher la miniature… chez Google Youtube (img.youtube.com) ! Si je voulais autoriser ça, il faudrait remplacer « img-src 'self'; » par « img-src 'self' img.youtube.com; » (attention : dans la syntaxe CSP, il n'y a pas de quote pour entourer et délimiter un nom de domaine). Quid des autres images externes susceptibles d'être chargées dans mon dos ? Il faut que je lise le code source de shaarli en entier ou il faut un « img-src *; » ?! Ça réduit encore l'intérêt de CSP puisque des images malveillantes externes (qui profitent d'une faille de sécurité dans la visionneuse qui la chargera) pourront être chargées par le navigateur ;
Le plugin QR code (encore lui), affiche le QR code en utilisant le schéma « data: ». Si l'on veut qu'il fonctionne, il faut donc remplacer « img-src 'self' » (ou « img-src ; » par « img-src 'self' data: » (ou « img-src data: »;. Là encore, ça retire une partie de son intérêt à CSP puisqu'un attaquant pourra injecter des images en utilisant ce schéma… ;
Si l'on clique sur une vidéo que je mets à disposition, genre celle-ci, il n'est pas possible d'avancer dans la lecture à un moment qui n'est pas encore téléchargé dans la mémoire tampon. Essayer, c'est le "plantage", il faut F5. Pour que ça fonctionne à nouveau, il faut ajouter « media-src 'self'; ». Ça encore, ça passe…
Du coup, pour un shaarli qui semble être fonctionnel, il faut la CSP default-src 'none'; frame-ancestors 'none'; script-src 'self' 'unsafe-inline'; style-src 'self'; img-src * data:; media-src 'self'; form-action 'self';. Si l'on est prêt à sacrifier les miniatures de vidéos Youtube (et sites externes), la CSP suivante suffit : default-src 'none'; frame-ancestors 'none'; script-src 'self' 'unsafe-inline'; style-src 'self'; img-src 'self' data:; media-src 'self'; form-action 'self';. Et tout ça, sans être sûr que j'ai bien identifié tous les problèmes…
CSP est une bonne idée, mais il faut connaître parfaitement son application web. Et même en la connaissant, il faut autoriser de gros trous dans la raquette pour qu'elle fonctionne, ce qui diminue d'autant la sécurité apportée par CSP. Et encore, j'ai travaillé sur une application web qui se veut être simple, qu'est-ce que ça doit être avec n'importe quel CMS, site web pseudo-moderne ou application web Java ! Imagine les ressources externes (police récupérée ici, JavaScript récupéré chez Google, etc.). Imagine l'interférence des CDN (réseaux de distribution de contenus à l'échelle de la planète) et les possibilités de rendre caduque CSP que cela offre.
Bref, hors de question que je me prenne la tête avec CSP.
Sat 08 Feb 2020 10:00:15 PM CET - permalink -
- http://shaarli.guiguishow.info/?vCXH0Q