2009-04-09 16 views
1

私はいつも、フォーラムやブログのようなWebソフトウェアを書くことに興味がありました。しかし、最近、私はPHPのために "PHP BBCode parser -PEAR"をテストし、いくつかのテストをすると、非効率的な混乱を招くか、XSSの穴があちこちにあるコードが貧弱になることに気づきました。正規表現とXSSの "戦争"

貧弱なBBCodeパーサの前述の例を取り上げて、XSSをどのように避けますか?リンクを扱うための典型的な正規表現を取り上げ、それがどれほど脆弱で、どのように回避するのかを述べることができます。

// Assume input has already been encoded by htmlspecialchars with ENT_QUOTES 
$text = preg_replace('#\[url\](.*?)\[/url\]#i','<a href="\1">\1</a>', $text); 
$text = preg_replace('#\[url=(.*?)\](.*?)\[/url\]#i','<a href="\1">\2</a>', $text); 

取り扱いイメージタグは、これより安全性が低いです。

私はいくつかの具体的な質問があります。主にPHPの実装に特有です。

  1. この例では、uri/url検証式を使用して一致させるほうがよいでしょうか?または、(.*?)とコールバックを使用し、入力が有効なリンクであるかどうかを確認する方が良いでしょうか?上で明らかなように、javascript:alert('XSS!')は上記のURLタグで動作しますが、uri-matchingが行われた場合は失敗します。
  2. コールバック内でurlencode()のような機能はどうでしょうか(これはURI標準が適用される限り)どんな抑止力や問題でもありますか?
  3. フルスタックパーサーを書く方が安全でしょうか?あるいは、ページあたりいくつかの異なるエントリを処理するために、あまりにも重いものを開発し使用するために必要な時間と処理能力はありますか?

私の例は多くのものの一つであり、いくつかよりも具体的であることが分かります。しかし、あなた自身を提供することから面倒ではありません。 私は、原則とベストプラクティス、およびテキスト解析の状況でのXSS保護の一般的な推奨事項を探しています。アウト

答えて

4

テストいくつかの、あなたは非効率的な混乱を得るか、あなたはXSS穴

地獄ええと貧困層のコードを取得します。私はbbcodeの実装にまだ会っていませんでしたが、それはXSSの脆弱性ではありませんでした。

'<a href="\1">\1</a>' 

ない良い:。HTMLエスケープをするために失敗した '<'、 '&' と '"' 文字は

はそれがより良い習慣です、この例では、/のみURIを使用して一致させるには(?*?)とコールバックを使用して、入力が有効なリンクかどうかを確認する方が良いでしょうか?

私はコールバックをとるでしょう。 HTMLエスケープを行う;それはposではないシンプルな文字列の置換だけで安全です。あなたがそれをやっている間にsanitisationをドロップします。

コールバック内でurlencodeのような関数について()は何

ほとんど。実際にはhtmlspecialchars()が必要です。 urlencode()はクエリパラメータをエンコードすることについてのものですが、ここで必要なものではありません。

フルスタックパーサーを書く方が安全でしょうか?

はい。

bbcodeは再帰的なタグベースの言語(正規表現でも解析できないXMLなど)であるため、正規表現解析に実際には適していません。多くのbbcodeホールは、ネストと誤ったネストの問題によって引き起こされます。たとえば:

[url]http://www.example.com/[i][/url]foo[/i] 

<a href="http://www.example.com/&lt;i>">foo</i> 

のようなものとして出て来ることができ、様々なBBコードの実装上の(XSSホールを含むまで)壊れたコードを生成する他の多くのトラップがあります。

私はあなた正規表現できBBコードに似た言語が必要な場合は、あなたに必要な原則とベストプラクティス

を探しています:可能なタグの数を減らす

  • 他のタグの中に入れることができます。任意のネスティングは実際にはサポートされていません
  • '<'と '>' HTMLタグ区切り文字に特殊文字を使用して、実際の山括弧と区別できるようにしてください。私はASCII制御コードを使用しています(ユーザー入力段階で制御文字を以前にフィルタリングしていました)。
  • この2つの制御文字の間のコンテンツで、これらの制御文字で処理される文字列を分割して、タグ内またはタグ境界内にbbcodeスパンを到達させないようにします。
  • タグ境界を越えて到達するbbcodeスパンを外側から操作することはできないため、大きなブロック要素を最初に行い、リンクの内側と最後に太字と斜体で作業します。
  • については、一度に1ブロックずつ処理してください。例えば。ダブル改行で新しい< p>を開始している場合、2つの別々のブロックの間にbbcodeタグを置くことはできません。

まだまだ難しいです。適切なパーサは、水密性がより高い可能性があります。

+0

ええと、あなたの言ったところで私はあなたに同意しますが、私は適切なパーサーを作ることに多くのスキルを持っていません。 XML風の解析のための適切なチュートリアルを知っていますか?私はそれほど複雑ではないがまだ必要なスキルレベルにある良いものを見つけるのは難しいと感じました。 –

+0

あなたのニーズを満たすサードパーティのパーサライブラリが見つからない場合は、手作業で行うことができます:まず、 '\ [[^ \]] + \]'のような文字列をpreg_split-with-PREG_SPLIT_DELIM_CAPTUREタグを選択し、開いているタグのスタックを保持してリストを歩きます。 – bobince

+0

(リスト内の偶数番号のインデックスは、テキスト、奇数番号のタグです。通常、テキストはHTMLエスケープされ、スマイリーが自動配置されることがあります。 – bobince