web-dev-qa-db-ja.com

strip_tags()はスクリプト攻撃に対して脆弱ですか?

既知のXSSまたはそれを通過させる他の攻撃はありますか

_$content = "some HTML code";
$content = strip_tags($content);

echo $content;
_

manual には警告があります:

この関数は、他のユーザーに表示されるテキストを投稿するときに悪意のあるユーザーが悪用する可能性のあるスタイルやonmouseover属性など、acceptable_tagsを使用して許可するタグの属性を変更しません。

ただし、これは_allowable_tags_パラメータの使用にのみ関連しています。

許可されたタグが設定されていない場合、strip_tags()は攻撃に対して脆弱ですか?

Chris Shiflett は安全だと言っているようです:

成熟したソリューションを使用する

可能であれば、独自のソリューションを作成する代わりに、成熟した既存のソリューションを使用してください。 strip_tags()やhtmlentities()などの関数が適しています。

これは正しいです?可能であれば、出典を引用してください。

HTMLピュリファイア、htmlspecialchars()などについて知っています。-HTMLをサニタイズするための最良の方法を探していますではありません。この特定の問題について知りたいだけです。これは出てきた理論的な質問です here

リファレンス: strip_tags() PHPソースコード の実装

49
Pekka

その名前が示すように、_strip_tags_はすべてのHTMLタグを削除する必要があります。それを証明できる唯一の方法は、ソースコードを分析することです。次の分析は、ホワイトリストタグの2番目の引数なしのstrip_tags('...')呼び出しに適用されます。

まず最初に、HTMLタグに関するいくつかの理論:タグは_<_で始まり、その後に非空白文字が続きます。この文字列が_?_で始まる場合、それは 解析されるべきではありません です。この文字列が_!--_で始まる場合、コメントと見なされ、次のテキストも解析されません。コメントは_-->_で終了します。このようなコメント内では、_<_や_>_などの文字を使用できます。属性はタグで使用でき、それらの値はオプションで引用文字(_'_または_"_)で囲むことができます。そのような引用が存在する場合は、それを閉じる必要があります。それ以外の場合、_>_が検出された場合、タグは閉じられません。

コード_<a href="example>xxx</a><a href="second">text</a>_は、Firefoxでは次のように解釈されます。

_<a href="http://example.com%3Exxx%3C/a%3E%3Ca%20href=" second"="">text</a>
_

PHP関数 _strip_tags_ext/standard/string.cの行4036 で参照されています。この関数は- 内部関数php_strip_tags_ex

2つのバッファが存在し、1つは出力用、もう1つは「HTMLタグ内」用です。 depthという名前のカウンターは、山かっこ(_<_)の数を保持します。
変数_in_q_には、引用符文字(_'_または_"_)が含まれている場合は含まれ、そうでない場合は_0_が含まれます。最後の文字は変数lcに格納されます。

関数には5つの状態があり、3つは関数の上の説明で説明されています。この情報と関数本体に基づいて、次の状態を導出できます。

  • 状態0は出力状態です(どのタグにもありません)。
  • 状態1は、通常のhtmlタグ内にいることを意味します(タグバッファーには_<_が含まれています)。
  • 状態2は、phpタグ内にいることを意味します
  • 状態3:出力状態から来て、_<_および_!_文字を検出しました(タグバッファーに_<!_が含まれています)
  • 状態4:HTMLコメント内

タグを挿入できないように注意する必要があります。つまり、_<_の後に空白以外の文字が続きます。 4326行目 は、次に説明する_<_文字を使用してケースをチェックします。

  • 引用符内にある場合(例:_<a href="inside quotes">_)、_<_文字は無視されます(出力から削除されます)。
  • 次の文字が空白文字の場合、_<_が出力バッファーに追加されます
  • hTMLタグの外の場合、状態は_1_( "HTMLタグ内")になり、最後の文字lcは_<_に設定されます
  • それ以外の場合、HTMLタグ内にある場合、depthという名前のカウンターがインクリメントされ、文字は無視されます。

タグが開いているときに_>_が満たされた場合(_state == 1_)、_in_q_は_0_(「引用符で囲まれていない」)となり、stateは_0_(「タグにない」)。 タグバッファは破棄されます。

属性チェック(_'_および_"_などの文字の場合)は、破棄されたタグバッファーで行われます。したがって、結論は次のとおりです。

タグのホワイトリストのないstrip_tagsは、タグの外側に含めても安全です。タグは許可されません。

「外部タグ」とは、_<a href="in tag">outside tag</a>_のようにタグ内にないことを意味します。ただし、_<_のように、テキストには_>_および_>< a>>_を含めることができます。結果は有効なHTMLではありませんが、_<_、_>_、および_&_、特に_&_は、エスケープする必要があります。 htmlspecialchars() でそれを行うことができます。

ホワイトリスト引数なしの_strip_tags_の説明は次のようになります。

返された文字列にHTMLタグが存在しないことを確認します。

48
Lekensteyn

特にPHPソースコードを確認していないため、今後のエクスプロイトを予測することはできません。ただし、ブラウザが一見無効なタグ(_<s\0cript>_)。したがって、将来、誰かが奇妙なブラウザの動作を利用できるようになる可能性があります。

それはさておき、HTMLの完全なブロックとしてブラウザに直接出力を送信することは決して安全ではありません:

_echo '<div>'.strip_tags($foo).'</div>'
_

ただし、これは安全ではありません。

_echo '<input value="'.strip_tags($foo).'" />';
_

_"_を介して引用を簡単に終了し、スクリプトハンドラーを挿入できるためです。

Stray _<_を_&lt;_に常に変換する方がずっと安全だと思います(引用符でも同じです)。

10
Matthew

このオンラインツール によると、この文字列は「完全に」エスケープされますが、結果は別の悪意のあるものになります!

<<a>script>alert('ciao');<</a>/script>

文字列では、「実際の」タグは<a></a>です。これは、<script>だけがタグではないためです。

私が間違っているか、古いバージョンのPHPが原因であると思いますが、環境で確認することをお勧めします。

5
Ludovico Grossi

タグを取り除くことは完全に安全です-あなたがしているすべてがテキストをhtml本文に出力することである場合。

Mysqlまたはurl属性に入れるのは必ずしも安全ではありません。

2
kemus