PHP サイトでの xss 攻撃を回避するためのベスト プラクティスは何ですか
質問
マジッククオートがオンになり、グローバル登録がオフになるように PHP を設定しました。
ユーザー入力から派生して出力するものについては、常に htmlentities() を呼び出すように最善を尽くしています。
また、私は時々データベースを検索して、添付された xss で使用される一般的なものを探します。
<script
他に何をすべきか、また、やろうとしていることが確実に実行できるようにするにはどうすればよいですか いつも 終わり。
解決
入力をエスケープすることは、XSS 防止を成功させるためにできる最善の策ではありません。また、出力をエスケープする必要があります。Smarty テンプレート エンジンを使用している場合は、次を使用できます。 |escape:'htmlall'
すべての機密文字を HTML エンティティに変換する修飾子 (私は独自のものを使用します) |e
上記のエイリアスである修飾子)。
入出力セキュリティに対する私のアプローチは次のとおりです。
- ユーザー入力を変更せずに保存します (入力時に HTML エスケープは行わず、PDO プリペアド ステートメントを介して DB 認識のエスケープのみが行われます)
- 使用する出力形式に応じて、出力時にエスケープします (例:HTML と JSON には異なるエスケープ ルールが必要です)
他のヒント
私の意見では、入力中は何もエスケープすべきではなく、出力時にのみエスケープすべきです。(ほとんどの場合)そのデータがどこに行くのかを知っているとは想定できません。たとえば、後で送信する電子メールに表示されるデータを取得するフォームがある場合は、別のエスケープが必要です (そうしないと、悪意のあるユーザーが電子メール ヘッダーを書き換える可能性があります)。
言い換えれば、データがアプリケーションから「出る」最後の瞬間にのみエスケープできます。
- リスト項目
- XML ファイルへの書き込み、XML のエスケープ
- DB への書き込み、エスケープ (その特定の DBMS の場合)
- メールを書く、メールのために逃げる
- 等
簡単に言えば:
- データがどこに行くかわからない
- データは実際には複数の場所に存在する可能性があり、両方ではなく異なるエスケープ メカニズムが必要になります。
- データが間違ったターゲットにエスケープされるのは本当に良くありません。(例えば。「Tommy\'s bar に行く」という件名のメールを受け取ります。)
Esp #3 は、入力層でデータをエスケープした場合 (または再度エスケープ解除する必要がある場合など) に発生します。
追伸:私は、magic_quotes を使用しないというアドバイスを二番目に考えます。それらは純粋に悪です。
XSS を行う方法はたくさんあります (「 http://ha.ckers.org/xss.html)そして捕まえるのは非常に難しいです。
私は個人的に、これを現在使用しているフレームワーク (Code Igniter など) に委任しています。完璧ではありませんが、私の手作りのルーチンよりも多くのことをキャッチできるかもしれません。
これは素晴らしい質問です。
まず、保存(データベースへの保存など)の安全性を確保する場合を除き、入力時にテキストをエスケープしないでください。その理由は、入力内容を保持して、状況に応じてさまざまな方法や場所で表示できるようにするためです。ここで変更を加えると、後のプレゼンテーションが損なわれる可能性があります。
データを提示するときは、そこにあるべきではないものをフィルターで除外します。たとえば、JavaScript が存在する理由がない場合は、それを検索して削除します。それを行う簡単な方法は、 ストリップタグ 関数を使用し、許可している HTML タグのみを表示します。
次に、持っているものを htmlentities または htmlspecialchars に渡して、そこにあるものを ASCII 文字に変更します。これは、コンテキストと取得したい内容に基づいて実行します。
また、Magic Quotes をオフにすることをお勧めします。これは PHP 6 から削除されており、使用するのは悪い習慣であると考えられています。詳細はこちら http://us3.php.net/magic_quotes
詳細については、こちらをご覧ください http://ha.ckers.org/xss.html
これは完全な答えではありませんが、始めるのに十分であれば幸いです。
リクはこう書きます:
ユーザー入力から派生して出力するものについては、常に htmlentities() を呼び出すように最善を尽くしています。
ジョエルのエッセイを参照してください。 コードが間違っているように見える これについての助けを求めて
頼りにしています PHPTAL そのために。
Smarty やプレーンな PHP とは異なり、デフォルトですべての出力をエスケープします。これを忘れてもサイトが脆弱になることがないため、これはセキュリティにとって大きな利点です。 htmlspecialchars()
または |escape
どこかで。
XSS は HTML 固有の攻撃であるため、HTML 出力はそれを防ぐのに最適な場所です。HTML を受け入れない別のメディアにデータを出力する必要がある可能性がありますが、独自のリスクがあるため、データベース内のデータを事前にフィルタリングしようとしないでください。
テンプレートライブラリ。 少なくとも、それがテンプレート ライブラリが行うべきことです。XSSを防ぐには 全て 出力はエンコードする必要があります。これはメインのアプリケーション/制御ロジックのタスクではなく、出力メソッドによってのみ処理される必要があります。
コード全体に htmlentities() を散りばめると、全体的な設計が間違ってしまいます。そして、あなたが示唆しているように、1つまたは2つのスポットを見逃している可能性があります。だからこそ、唯一の解決策は厳密な HTML エンコーディングです。 -> いつ 出力変数は html/xml ストリームに書き込まれます。
残念ながら、ほとんどの PHP テンプレート ライブラリは独自のテンプレート構文を追加するだけで、出力エンコーディング、ローカリゼーション、HTML 検証などの重要なことには関心がありません。おそらく他の誰かがphp用の適切なテンプレートライブラリを知っているでしょうか?
ほとんどのサイトでは、すべてのユーザー入力をエスケープするだけで十分です。また、セッション ID が URL に含まれていないことを確認して、セッション ID が盗まれないようにしてください。 Referer
別のサイトへのリンク。さらに、ユーザーにリンクの送信を許可する場合は、次のことを確認してください。 javascript:
プロトコルリンクは許可されます。これらは、ユーザーがリンクをクリックするとすぐにスクリプトを実行します。
XSS 攻撃が心配な場合は、出力文字列を HTML にエンコードすることが解決策です。すべての出力文字を HTML 形式にエンコードすることを覚えていなければ、XSS 攻撃を成功させる方法はありません。
個人的には、magic_quotes を無効にします。PHP5 以降ではデフォルトで無効になっており、すべてをエスケープするわけではなく、PHP6 からは削除されるため、まったく存在しないものとしてコーディングすることをお勧めします。
次に、フィルタリングしているユーザーデータの種類に応じて、次に何をするかが決まります。単なるテキストの場合、例:名前、それから strip_tags(trim(stripslashes()));
または、範囲を確認するには正規表現を使用します。
特定の範囲の値が予想される場合は、有効な値の配列を作成し、それらの値のみを通過させます (in_array($userData, array(...))
).
数値をチェックしている場合は、 is_numeric を使用して整数を強制するか、特定の型にキャストすることで、代わりに文字列を送信しようとする人を防ぐことができます。
PHP5.2+ を使用している場合は、以下を検討してください。 フィルター() そして、電子メールアドレスを含むさまざまなデータタイプをフィルタリングできる拡張機能を利用します。ドキュメントは特に優れているわけではありませんが、改善されています。
HTML を処理する必要がある場合は、次のようなことを考慮する必要があります。 PHP入力フィルター または HTML ピュリファイアー. 。HTML Purifier は、HTML の適合性も検証します。入力フィルターがまだ開発中かどうかはわかりません。どちらでも、使用できるタグのセットと許可される属性を定義できます。
何を決定するにせよ、ユーザー (あなた自身も含む!) から PHP スクリプトに入力されるものを決して信用しないことを常に覚えておいてください。
これらの答えはどれも素晴らしいものですが、根本的に XSS に対する解決策は、文字列操作による HTML ドキュメントの生成をやめるということです。
入力をフィルタリングすることは、どのようなアプリケーションにとっても常に良いアイデアです。
htmlentities() とその友達を使用して出力をエスケープすることは、適切に使用されている限り機能するはずですが、これは文字列を mysql_real_escape_string($var) で連結して SQL クエリを作成するのと HTML に相当します。これは機能するはずですが、作業を検証できるものは限られています。いわば、パラメータ化されたクエリを使用するようなアプローチと比較します。
長期的な解決策は、アプリケーションが内部でページを構築し、おそらく DOM などの標準インターフェイスを使用してから、ライブラリ (libxml など) を使用して XHTML/HTML/などへのシリアル化を処理することです。もちろん、これが普及して十分な速度になるまでには程遠いですが、それまでの間は文字列操作を介して HTML ドキュメントを構築する必要があり、これは本質的にリスクが高くなります。
この関数を使用すると、考えられる多くの xss 攻撃を取り除くのに役立つことがわかりました。http://www.codebelay.com/killxss.phps
「マジック クオート」は、XSS の最悪の欠陥のいくつかに対する緩和策であり、入力時にすべてをエスケープすることで機能しますが、これは仕様上間違っています。これを使用したい唯一のケースは、XSS に関して不注意に書かれていることが知られている既存の PHP アプリケーションを絶対に使用しなければならない場合です。(この場合、「マジック クオート」があっても深刻な問題に直面しています。) 独自のアプリケーションを開発する場合は、「マジック クオート」を無効にし、代わりに XSS セーフな慣行に従う必要があります。
クロスサイト スクリプティングの脆弱性である XSS は、アプリケーションが [X]HTML、CSS、ECMAscript、またはその他のブラウザーで解析された出力に外部ソース (ユーザー入力、他の Web サイトから取得した文字列など) からの文字列を適切にエスケープせずに含めた場合に発生します。小なり ([X]HTML)、一重引用符または二重引用符 (ECMAscript) などの特殊文字は決して表示されません。これに対する適切な解決策は、出力言語の規則に従って常に文字列をエスケープすることです。[X]HTML のエンティティ、ECMAscript のバックスラッシュなどを使用します。
何が信頼できず、エスケープする必要があるかを追跡するのは難しい場合があるため、HTML のような言語では、「マークアップ付きのテキスト」ではなく「テキスト文字列」であるすべてのものを常にエスケープすることをお勧めします。一部のプログラミング環境では、互換性のない文字列型をいくつか導入することで作業が容易になります。「文字列」(通常のテキスト)、「HTML 文字列」(HTML マークアップ)など。この場合、「文字列」から「HTML 文字列」への直接の暗黙的な変換は不可能になり、文字列を HTML マークアップにできる唯一の方法は、エスケープ関数に渡すことです。
「グローバルの登録」は、無効にすることは間違いなく良いアイデアですが、XSS とはまったく異なる問題を扱います。
HttpOnly を使用するセッション Cookie (またはすべての Cookie) を作成します。その場合、ほとんどのブラウザは JavaScript から Cookie 値を非表示にします。ユーザーは引き続き Cookie を手動でコピーできますが、これによりスクリプトへの直接アクセスが防止されます。StackOverflow にはベータ版の段階でこの問題がありました。
これは解決策ではなく、壁にレンガがまた一つ残っただけです
- ユーザー入力を信用しない
- すべてのフリーテキスト出力をエスケープする
- magic_quotes は使用しないでください。DBMS 固有のバリアントがあるかどうかを確認するか、PDO を使用してください
- 悪意のあるスクリプトによるセッションのハイジャックを避けるために、可能な場合は HTTP のみの Cookie の使用を検討してください。
少なくともデータベースに入るすべてのデータを検証する必要があります。また、データベースから出てくるすべてのデータも検証してみてください。
mysql_real_escape_string は SQL インジェクションを防ぐのに適していますが、XSS はさらに扱いにくいです。可能であれば、preg_match、stip_tags、または htmlentities を使用する必要があります。
PHP アプリケーションで XSS を防止するための現在の最良の方法は、HTML Purifier (http://htmlpurifier.org/) です。小さな欠点の 1 つは、ライブラリがかなり大きいため、APC のような演算コード キャッシュと併用するのが最適であることです。これは、信頼できないコンテンツが画面に出力される場所で使用します。htmlentities、htmlspecialchars、filter_input、filter_var、strip_tags などよりもはるかに徹底しています。
既存のユーザー入力サニタイズ ライブラリを使用してクリーンアップする 全て ユーザー入力。を置かない限り、 多く かなりの労力を費やしても、自分で実装しても同じように機能することはありません。
最良の方法は、コードをバインドできるクラスを使用することです。これにより、データを手動でエスケープすることを心配する必要がなくなります。
誤報を発生させないサイトに SQL インジェクション/xss インジェクションの徹底した防止を実装することは困難です。CMS でエンドユーザーが使用する可能性のあるもの <script>
または <object>
別のサイトのアイテムにリンクしているもの。
すべてのユーザーに NoScript を使用して FireFox をインストールさせることをお勧めします ;-)