web-dev-qa-db-fra.com

Désinfecter les CSS entrés par l'utilisateur

Quelqu'un a-t-il une idée de la façon de nettoyer le CSS entré via l'utilisateur? Je suis préoccupé par le script intersite via CSS. J'utilise wp_filter_kses pour nettoyer le code HTML entré par l'utilisateur, mais j'ai besoin d'une solution similaire pour les styles entrés par l'utilisateur. Jusqu'ici, j'utilise la fonction laide et incomplète suivante, mais j'aimerais quelque chose de plus complet.

function sanitizeCSS ( $css ) {
    $css = str_replace( '/-moz-binding/', '', $css );
    $css = str_replace( '/expression/', '', $css );
    $css = str_replace( '/javascript/', '', $css );
    $css = str_replace( '/vbscript/', '', $css );
    return $css; 
}
6
radiok

La meilleure approche que j'ai trouvée consistait à incorporer CSSTidy à mon plugin. J'ai pris une page de JetPack qui a une fonctionnalité CSS personnalisée.

L'implémentation CSSTidy de JetPack est contenue dans la classe Jetpack_Safe_CSS en tant que fonction filter_attr. Je ne pouvais pas entièrement comprendre pourquoi JetPack imbriquait l'utilisateur qui saisissait CSS dans un élément 'div' avant l'analyse, mais après quelques essais et erreurs, j'ai appris que CSSTidy n'était pas vraiment capable d'analyser un fichier CSS. Cette leçon apprise, j'ai littéralement déchiré le code de JetPack.

J'ai téléchargé CSSTidy, créé un répertoire contenant les fichiers CSSTidy PHP. J'ai ensuite besoin de class.csstidy.php si nécessaire dans mon code et d'initialiser un nouvel objet csstidy. Emboîtez le CSS à valider dans un élément 'div', analysez-le dans CSSTidy, puis extrayez le CSS brut de l'objet csstidy. Jusqu'ici tout va bien avec des milliers d'installations (bien que je ne sache jamais combien d'utilisateurs utilisent réellement la fonctionnalité CSS de mon plugin).

Je n'ai peut-être pas remarqué que c'était ma question initiale, mais je recherchais l'approche la plus simple, la plus facile, pas l'approche la plus technique, sophistiquée ou puissante. J'apprécie le moins possible de modifier l'expérience WordPress. C'est pourquoi je me suis tourné vers JetPack comme la chose la plus proche de "source". Je considère JetPack comme presque canonique car il est développé par Automattic (les développeurs de WordPress lui-même). Mon seul ... regret? ... est que CSSTidy ait été abandonné en 2007, alors j'imagine que je devrai trouver une autre solution à un moment donné.

require_once( 'csstidy/class.csstidy.php' );
$csstidy = new csstidy();
$csstidy->set_cfg( 'remove_bslash', FALSE );
$csstidy->set_cfg( 'compress_colors', FALSE );
$csstidy->set_cfg( 'compress_font-weight', FALSE );
$csstidy->set_cfg( 'discard_invalid_properties', TRUE );
$csstidy->set_cfg( 'merge_selectors', FALSE );
$csstidy->set_cfg( 'remove_last_;', FALSE );
$csstidy->set_cfg( 'css_level', 'CSS3.0' );
$csstovalidateindiv = 'div {' . $csstovalidate . '}';
$csstovalidateindiv = preg_replace( '/\\\\([0-9a-fA-F]{4})/', '\\\\\\\\$1', $csstovalidateindiv );
$csstovalidateindiv = wp_kses_split( $csstovalidateindiv, array(), array() );
$csstidy->parse( $csstovalidateindiv );
$csstovalidateindiv = $csstidy->print->plain();
$csstovalidateindiv = str_replace( array( "\n", "\r", "\t" ), '', $csstovalidateindiv );
preg_match( "/^div\s*{(.*)}\s*$/", $csstovalidateindiv, $matches );
if ( !empty( $matches[1] ) ) $cssvalidated = $matches[1];

(code ou ça ne s'est pas passé)

2
radiok

Vous aurez besoin d’un véritable analyseur syntaxique CSS comme celui-ci pour filtrer le CSS. Les expressions régulières ou les simples remplacements de chaînes ne sont pas assez sûrs.

3
fuxia

Jetpack ne nettoie pas vraiment les CSS, il les nettoie, ce qui a pour effet secondaire de supprimer certaines vulnérabilités, mais pas toutes.

Un attaquant peut toujours utiliser @import pour importer des feuilles de style CSS non normalisées. expression() pour introduire XSS aux anciens navigateurs IE; @charset pour amener le navigateur à interpréter le CSS en HTML, ouvrant ainsi des opportunités XSS; définir des URL avec des protocoles arbitraires pour lancer des attaques SSRF, etc.

Si vous voulez une désinfection complète, vous devrez faire quelque chose comme r2085-meta .

Vous devez exécuter votre désinfection contre scénarios de test complets pour vérifier que tout est nettoyé.

CSSTidy n'est pas vraiment abandonné, cependant; l'un des auteurs originaux a ajouté le PHP class , et l'équipe Jetpack et d'autres ont apporté des contributions pour le tenir raisonnablement à jour. Si vous ne vous sentez pas à l'aise avec cela, cependant, Caja est une autre option.

1
Ian Dunn
wp_filter_nohtml_kses()

ne semble pas fonctionner correctement car il échappe au caractère ", vous ne pouvez donc pas écrire de sélecteurs d'attributs. Il semble qu'il n'existe pas de méthode" simple "pour ce faire.

0
Nico