9

私はサイトに取り組んでおり、ユーザーがカスタム CSS を入力して公開できるようにしたいと考えています。

ただし、CSS を介して大量の XSS 攻撃を実行できるため、CSS を解析し、解析した CSS を実行することにより、HTML Purifierの動作と同様に、CSS 出力を「クリーン」にする方法を見つけたいと考えています。ホワイトリストに対して、解析およびホワイトリストに登録された CSS に基づいて新しいスタイルシートを出力します。

このような図書館はすでにありますか?そうでない場合、カスタム実装を作成するために使用できる CSS 解析ライブラリはありますか?

4

1 に答える 1

4

独自の CSS パーサーとフィルターを作成することになると思います。そのため、私はそのようなことをしたことがありませんが、次のことを検討します。

  • ユーザーが使用できる受け入れ可能な CSS プロパティの (ホワイト) リストを作成します。のように: color, font-family.
  • background値を簡単に解析できるように、少なくとも最初はなどの省略形を許可しない方がよいと思います。彼らが明示的に書くことを要求しますbackground-color, background-image.
  • URL が必要な場合は、相対 URL のみを許可し、URL に似ていないものはすべて破棄します。パーサーとバリデーターを改善できるように、とにかくこれらの問題をログに記録してください。
  • 構文解析は非常に厳密に行い、有効な CSS であってもパーサーが理解できないものはすべて破棄してください。つまり、独自の CSS サブセットを作成します。

解析するとき、最も難しい部分は、複雑な CSS セレクターの解析です。ただし、ここでも独自のサブセットを課すことができます。

ここにいくつかの(疑似)コードがあります。おそらくそれはあなたを助けるでしょう:

<?php

function tokenizeCSS() {
    return array(
        array(
            'selector'   => '#foo .bar',
            'properties' => array(
                'background-color' => 'transparent',
                'color'            => '#fff',
            ),
        );
    );
}

function colorValidator($color)
{}

/**
 * This is basically the white list. Keys are accepted CSS properties
 * and values are the validator callbacks.
 */
$propertyValidators = array(
    'background-color' => 'colorValidator',
    'color'            => 'colorValidator',
);

$filteredRules = array();

foreach (tokenizeCSS() as $rule) {
    if (! validSelector($rule['selector'])) {
        continue;
    }

    foreach ($rule['properties'] as $property => $value) {
        /**
         * Check property is in white list
         */
        if (! isset($propertyValidators[$property]) {
            continue;
        }

        /**
         * Check property is valid
         */
        if (! $propertyValidators[$property]($value)) {
            continue;
        }

        /**
         * Valid rule
         */
        $filteredRules[$rule['selector']][$property] = $value;
    }
}
于 2009-09-02T07:52:39.007 に答える