Pdf.js: la micro-optimisation du style de la couche de texte a entraîné l'exigence de style-src « unsafe-inline » dans la politique de sécurité du contenu

Créé le 13 févr. 2017  ·  11Commentaires  ·  Source: mozilla/pdf.js

https://github.com/mozilla/pdf.js/commit/cb5f9df0c8932fe0db9f783ede7893b7efcadcdb a commencé à générer automatiquement des chaînes de style, ce qui est interdit par une politique de sécurité du contenu standard. Ce serait bien d'avoir une solution de repli ou peut-être de reconsidérer l'approche.

Pour reproduire, utilisez style-src 'self' dans CSP :

    <meta http-equiv="Content-Security-Policy" content="style-src 'self'" />
2-performance 4-text-selection

Commentaire le plus utile

Au cas où quelqu'un d'autre rencontrerait cela et voudrait une solution, voici mon correctif actuel qui ramène cela à l'ancienne façon de le faire afin que style-src: 'unsafe-inline' puisse être évité :

https://github.com/GrapheneOS/pdf.js/commit/021d2fddb03883054ef4399d1d3df87e0c6ab9ca

Il peut certainement être optimisé un peu, mais comme cela n'a pas d'importance pour mon utilisation, je garde le correctif aussi minimal que possible pour faciliter la maintenance. Je pense que s'attendre à ce que quelqu'un qui souhaite résoudre ce problème de sécurité se soucie d'optimiser les performances est un peu en arrière. L'optimisation des performances aurait dû être limitée à ce qui peut être fait sans rompre l'hygiène de sécurité de base. Il peut même être plus rapide d'aborder cela d'une manière différente comme je l'ai mentionné ci-dessus. Le message de validation pour l'optimisation mentionne à quel point il était difficile de mesurer une différence, mais la régression de sécurité est assez facile à mesurer.

La raison pour laquelle j'utilise pdf.js en premier lieu est la sécurité. Il permet de réutiliser le rendu du navigateur durci / en bac à sable avec tout le rendu spécifique au PDF dans un langage sécurisé en mémoire (JavaScript). Dans le cadre de cela, j'utilise CSP pour atténuer l'injection de code/style dynamique qui pourrait augmenter considérablement la surface d'attaque pour ressembler à une page Web, ce qui est très contraire aux objectifs. Je pense que beaucoup d'autres personnes ont un cas d'utilisation similaire pour pdf.js pour éviter les bibliothèques de rendu PDF natives dangereuses. Éviter les styles unsafe-inline fait partie de la garantie qu'un bogue ne peut pas entraîner l'injection accidentelle de styles arbitraires, ouvrant ainsi une grande surface d'attaque au moteur de rendu. Pour un cas d'utilisation où il est intégré à un site Web réel, c'est encore plus important, car beaucoup de choses maléfiques peuvent être faites avec CSS.

Je considère cela au même niveau que s'attendre à ce que les binaires / bibliothèques natifs aient SSP, ASLR (PIE), _FORTIFY_SOURCE=2 , -fstack-clash-protection et d'autres atténuations de base. C'est une hygiène de sécurité de base par rapport à des choses plus avancées comme le CFI basé sur le type, le piégeage des désinfectants entiers, ShadowCallStack, etc. où je m'attends à ce que des projets plus importants y réfléchissent et y travaillent peut-être déjà, mais cela ne fait pas partie du strict minimum. Une politique CSP de base avec JavaScript/CSS statique constitue à mon avis une hygiène de sécurité de base.

Tous les 11 commentaires

... ou peut-être reconsidérer l'approche.

Le PR #7632 était nécessaire pour améliorer les performances du mode enhanceTextSelection en particulier, qui fait partie du problème #7584, donc à mon avis, je ne pense pas qu'il faille même envisager de revenir en arrière.

Je suggère seulement de prendre d'autres voies pour l'optimiser. Par exemple, pourquoi utiliser 4 attributs de remplissage et les appliquer ensuite avec style au lieu de les fusionner ?

Pourrait également toujours utiliser l'approche du tableau statique pour définir des propriétés de style individuelles au lieu de tout faire via style . Les propriétés font-family et font-size pourraient être fusionnées comme padding .

Je suggère seulement de prendre d'autres voies pour l'optimiser. Par exemple, pourquoi utiliser 4 attributs de remplissage et les appliquer ensuite avec style au lieu de les fusionner ?

En général, il n'y a aucune garantie qu'un textDiv besoin des quatre valeurs de remplissage mises à jour avec enhanceTextSelection , et le code actuel fournit un moyen simple de gérer ce cas (très courant).

Pourrait également toujours utiliser l'approche du tableau statique pour définir des propriétés de style individuelles au lieu de tout faire via le style.

Le raisonnement général derrière la mise à jour de tout en même temps en utilisant style , était d'essayer d'éviter d'invalider inutilement le DOM lors de la création/mise à jour des textDiv s car cela semblait être l'un des principaux contributeurs à mauvaise performance du mode enhanceTextSelection .

En général, il n'y a aucune garantie qu'un textDiv particulier ait besoin des quatre valeurs de remplissage mises à jour avec EnhanceTextSelection, et le code actuel a fourni un moyen simple de gérer ce cas (très courant).

Cela ne veut pas dire que padding ne peut pas être utilisé efficacement. Il n'a pas besoin de créer de nouvelles chaînes pour les parties qu'il ne met pas à jour et le résultat final sera plus petit. Il peut remplacer un seul ensemble d'attributs style par un seul ensemble style.padding et " 0 " peut être réutilisé.

Le raisonnement général derrière la mise à jour de tout en même temps à l'aide de style était d'essayer d'éviter d'invalider inutilement le DOM lors de la création / mise à jour des textDivs, car cela semblait être l'un des principaux contributeurs aux mauvaises performances du mode EnhanceTextSelection.

Cela ne se passe-t-il pas dans un fragment, pas dans le DOM réel ?

Cela ne signifie pas que le rembourrage ne peut pas être utilisé efficacement.

@thestinger est d' accord, cela aidera à résoudre le problème si des références avec des données de performance étaient disponibles.

Je ne suis pas vraiment en mesure de mesurer une différence entre les différentes approches ici. Les différentes approches peuvent cependant être microbenchmarkées hors contexte.

Je pense que le conflit avec unsafe-inline peut être réduit sans perte de performances en ajustant cela, puis l'optimisation peut être rendue conditionnelle si le garder est important.

C'est facile pour moi de simplement annuler ce commit, donc ce n'est pas une priorité pour moi, mais je vais essayer de trouver quelqu'un pour y travailler. Ce serait formidable d'avoir des tests pour les trucs CSP afin qu'ils ne puissent pas se casser à l'avenir (des optimisations comme celle-ci pourraient encore se produire si elles sont importantes, elles auraient juste besoin d'être conditionnelles).

Il existe peut-être une solution qui permet l'optimisation telle quelle tout en prenant en charge les sites Web utilisant le CSP.

Il existe trois façons de définir le style en ligne sous forme de chaîne :

  • element.setAttribute('style', someStyle) , qui ne fonctionne pas lorsqu'il y a un CSP qui n'autorise pas les entrées non sécurisées
  • element.style = someStyle , qui n'est pas pris en charge dans IE (testé sur IE 11, je ne l'ai pas testé sur Edge donc il pourrait être cassé là aussi)
  • element.style.cssText = someStyle , qui est pris en charge à partir du niveau 2 du DOM, donc même IE le prend en charge (vérifié sur IE 11)

Plunker pour montrer les trois méthodes : https://plnkr.co/edit/T8xrUmR5eSuqDukSEVuw?p=preview

Je serais plus que disposé à faire une pull request en changeant element.setAttribute('style', ...) en element.style.cssText = ... si vous êtes d'accord sur cette solution.

Cela ressemble à un bug du navigateur si element.style.cssText = someStyle fonctionne sans unsafe-eval :

Au cas où quelqu'un d'autre rencontrerait cela et voudrait une solution, voici mon correctif actuel qui ramène cela à l'ancienne façon de le faire afin que style-src: 'unsafe-inline' puisse être évité :

https://github.com/GrapheneOS/pdf.js/commit/021d2fddb03883054ef4399d1d3df87e0c6ab9ca

Il peut certainement être optimisé un peu, mais comme cela n'a pas d'importance pour mon utilisation, je garde le correctif aussi minimal que possible pour faciliter la maintenance. Je pense que s'attendre à ce que quelqu'un qui souhaite résoudre ce problème de sécurité se soucie d'optimiser les performances est un peu en arrière. L'optimisation des performances aurait dû être limitée à ce qui peut être fait sans rompre l'hygiène de sécurité de base. Il peut même être plus rapide d'aborder cela d'une manière différente comme je l'ai mentionné ci-dessus. Le message de validation pour l'optimisation mentionne à quel point il était difficile de mesurer une différence, mais la régression de sécurité est assez facile à mesurer.

La raison pour laquelle j'utilise pdf.js en premier lieu est la sécurité. Il permet de réutiliser le rendu du navigateur durci / en bac à sable avec tout le rendu spécifique au PDF dans un langage sécurisé en mémoire (JavaScript). Dans le cadre de cela, j'utilise CSP pour atténuer l'injection de code/style dynamique qui pourrait augmenter considérablement la surface d'attaque pour ressembler à une page Web, ce qui est très contraire aux objectifs. Je pense que beaucoup d'autres personnes ont un cas d'utilisation similaire pour pdf.js pour éviter les bibliothèques de rendu PDF natives dangereuses. Éviter les styles unsafe-inline fait partie de la garantie qu'un bogue ne peut pas entraîner l'injection accidentelle de styles arbitraires, ouvrant ainsi une grande surface d'attaque au moteur de rendu. Pour un cas d'utilisation où il est intégré à un site Web réel, c'est encore plus important, car beaucoup de choses maléfiques peuvent être faites avec CSS.

Je considère cela au même niveau que s'attendre à ce que les binaires / bibliothèques natifs aient SSP, ASLR (PIE), _FORTIFY_SOURCE=2 , -fstack-clash-protection et d'autres atténuations de base. C'est une hygiène de sécurité de base par rapport à des choses plus avancées comme le CFI basé sur le type, le piégeage des désinfectants entiers, ShadowCallStack, etc. où je m'attends à ce que des projets plus importants y réfléchissent et y travaillent peut-être déjà, mais cela ne fait pas partie du strict minimum. Une politique CSP de base avec JavaScript/CSS statique constitue à mon avis une hygiène de sécurité de base.

Corrigé par la pull request ci-dessus.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

syssgx picture syssgx  ·  29Commentaires

snorp picture snorp  ·  95Commentaires

StevenHarlow picture StevenHarlow  ·  29Commentaires

collinanderson picture collinanderson  ·  29Commentaires

dotnetCarpenter picture dotnetCarpenter  ·  39Commentaires