web-dev-qa-db-ja.com

ユーザー入力CSSのサニタイズ

ユーザー入力によって入力されたCSSをサニタイズする方法を知っている人はいますか? CSSを介したクロスサイトスクリプティングが心配です。ユーザーが入力したHTMLをクリーンアップするためにwp_filter_ksesを使用していますが、ユーザーが入力したスタイルについても同様の解決策が必要です。これまでのところ、私は以下の醜く不完全な関数を使っていますが、もっと完全なものが欲しいのです。

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

私が見つけた最良のアプローチはCSSTidyを私のプラグインに組み込むことでした。私はカスタムCSS機能を持っているJetPackからページを取りました。

JetPackのCSSTidy実装は、関数filter_attrとしてJetpack_Safe_CSSクラスに含まれています。 JetPackが解析前にユーザーがCSSをdiv要素内に入れた理由を完全に理解することはできませんでしたが、試行錯誤の末、CSSTidyはCSSファイルを解析できないことがわかりました。そのレッスンは私が文字通りJetPackからコードを切り取ったことを学びました。

私はCSSTidyをダウンロードし、CSSTidy PHPファイルを含むディレクトリを作成しました。次に、必要に応じてclass.csstidy.phpをコードに要求し、新しいcsstidyオブジェクトを初期化します。 CSSを 'div'要素でネストし、CSSTidyで解析してから、プレーンCSSをcsstidyオブジェクトから取り出します。これまでのところ何千ものインストールでこれほど良い(私のプラグインのCSS機能を実際に使用するユーザーの数はわからないだろうが)。

私はこれが私の最初の質問であるとは思わなかったかもしれませんが、最も技術的で洗練された、あるいは強力な方法ではなく、最も単純で最も簡単な方法を探していました。 WordPressのエクスペリエンスを可能な限り変更しないようにします。これが私が "ソース"に最も近いものとしてJetPackに目を向けた理由です。私はJetPackがAutomattic(WordPress自身の開発者)によって開発されているのでほぼ標準的であると考えます。私の唯一の後悔は... CSSTidyは2007年に放棄されたということです、それで私は私がいつか別の解決策を見つける必要があると思います。

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];

(コードまたはそれは起こらなかった)

2
radiok

CSSをフィルタリングするには、 これ のような本当のCSSパーサーが必要です。正規表現や単純な文字列の置き換えは安全ではありません。

3
fuxia

Jetpackは実際にはCSSをサニタイズするわけではありません。単にクリーンアップするだけで、一部の脆弱性を排除するという副作用がありますが、全部ではありません。

攻撃者はまだ@importを使用してサニタイズされていないCSSをインポートすることができます。古いIEブラウザにXSSを導入するためのexpression()。ブラウザをだましてCSSをHTMLとして解釈させ、XSSの機会を広げるための@charset。 SSRF攻撃などを仕掛けるために、任意のプロトコルでURLを設定する.

完全に消毒したい場合は、 r2085-meta のようにする必要があります。

包括的なテストケース に対してサニタイズを実行して、すべてがクリーンになっていることを確認する必要があります。

CSSTidyは、本当に放棄されていません。最初の作者の一人は PHP class をフォークし、Jetpackチームと他の人はそれを合理的に最新の状態に保つために貢献しました。あなたがそれに慣れていないなら、しかし、 Caja は別の選択肢です。

1
Ian Dunn
wp_filter_nohtml_kses()

"文字をエスケープするため、正しく機能していないようです。したがって、属性セレクタを書くことはできません。これを行うための"単純な "方法がないようです。

0
Nico