機密情報が提供されないように、PHP WebアプリケーションでJavaScriptインジェクションが発生するのを防止または阻止するために必要な対策は何ですか(PHP、HTML / XHTML、およびJavaScriptのベストプラクティス)。
5 に答える
良い最初のステップは、リンクされた質問GertGにリストされている方法を適用することです。これは、、、、およびを含むmysql_real_escape_string
、入力をクレンジングするためにさまざまな状況で使用できるさまざまな関数を詳細にカバーしています。htmlentities()
htmlspecialchars()
strip_tags()
addslashes()
より良い方法は、可能な限り、ユーザー入力をデータベースに直接挿入しないようにすることです。ホワイトリスト入力検証を採用する:オプションの範囲が限られている状況では、クライアント側に面したフォームから入力を取得するのではなく、ハードコードされた値から挿入用に選択します。基本的に、これは、悪意のある/不正な形式の/悪意のある入力を排除/対抗しようとするのではなく、受け入れる特定の値のみを持つことを意味します。
例:アイテムのドロップダウンがあるフォームがある場合は、このドロップダウンからの入力を挿入に使用しないでください。悪意のあるクライアントは、オプションが限られていると思われる場合でも、フォームの送信で送信された情報を編集できることに注意してください。代わりに、ドロップダウンでサーバー側コードの配列内のインデックスを参照するようにします。次に、その配列を使用して、挿入するものを選択します。このように、攻撃者が悪意のあるコードを送信しようとしても、実際にデータベースにアクセスすることはありません。
明らかに、これはフォーラムやブログのような自由形式のアプリケーションでは機能しません。それらのために、あなたは「最初のステップ」のテクニックに頼らなければなりません。それでも、ホワイトリスト入力の検証によって改善できるさまざまなオプションがあります。
可能な限り、SQLの相互作用にパラメーター化されたクエリ(バインド変数を使用したプリペアドステートメント)を使用することもできます。これにより、すべての入力が単なる値であることがデータベースサーバーに通知されるため、インジェクション攻撃による潜在的な問題の多くが軽減されます。多くの場合、これは自由形式のアプリケーションにも適用できます。
デフォルトでは、htmlに出力する値をhtmlspecialchars()で処理します。
htmlspecialchars()を使用しない理由は、それ自体にhtmlが含まれているhtml文字列に出力する必要がある場合のみです。その場合、この文字列が完全に安全なソースからのものであることを確認する必要があります。そのような自信がない場合は、慎重に制限されたタグ、属性、および属性値のセットのみを許可するホワイトリストhtmlフィルターを通過させる必要があります。属性値には特に注意する必要があります。特にsrc、hef、styleなどの属性では、すべてが属性値として渡されることを決して許可しないでください。
htmspeciachars()を使用せずにhtmlに何かを出力するWebアプリ内のすべての場所を知っておく必要があります。これらの場所が本当に必要であることを確認し、すべての自信にもかかわらず、これらの場所は潜在的な脆弱性であることに注意してください。
これがあまりにも注意深いと思っている場合:「なぜこの変数をhtmlspecialchar()する必要があるのですか?この変数には整数だけが含まれていて、貴重なCPUサイクルがすべて失われていることがわかっていますか?」
これを覚えておいてください:あなたは知らない、あなたはあなたが知っていると思うだけです、CPUサイクルは世界で最も安いものであり、それらのほとんどすべてはデータベースやファイルシステム、あるいはメモリアクセスを待つことによって無駄になります。
また、ブラックリストのhtmlフィルターは絶対に使用しないでください。Youtubeがその間違いを犯し、誰かが突然、最初のものだけ<script>
が削除され、コメントに2番目のものを入力すると、訪問者のブラウザに任意のJavascriptを挿入できることに気付きました。
同様に、SQLインジェクションを回避するには、mysql_real_escape_string()を使用して、SQLクエリに接着するすべての値を処理するか、PDOプリペアドステートメントを使用することをお勧めします。
htmlとしてフォーマットする必要があるものを渡さない場合は、次を使用します。
strip_tags() <- Eliminates any suspicious html
次に、データベースに保存する前に、以下を実行してクリーンアップします
mysql_real_escape_string()
ajaxがテキストボックスまたはwysiwygを介してユーザーが入力したhtmlを保存している場合は、HTMLPurifierを使用してjavascriptを削除しますが、htmlタグは許可します。
私は提供された他の回答に完全には同意しませんので、私の推奨事項を投稿します。
XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheetを読むことをお勧めします
HTMLインジェクション: ユーザーが送信したコンテンツを表示する場合は常に、一重引用符で囲む場合はENT_QUOTESを指定するときに、 htmlspecialcharsまたはhtmlentitiesで適切にクリーンアップする必要があります。一重引用符でカプセル化せず、常に属性を二重引用符でカプセル化することをお勧めします(省略しないでください)。これは、次のようなものに適用されます。
<input value="<?php echo htmlspecialchars($var); ?>" />
<textarea><?php echo htmlspecialchars($var); ?></textarea>
<p><?php echo htmlspecialchars($var); ?></p>
<img width="<?php echo htmlspecialchars($var); ?>" />
Javascriptインジェクション:
ユーザーコンテンツをイベントやjavascriptにエコーしないことがベストプラクティスです(ただし、常に実用的であるとは限りません)。ただし、そうする場合、リスクを減らすためにできることがいくつかあります。整数IDのみを渡します。タイプ指定子などが必要な場合は、出力する前にホワイトリストや条件付きチェックを事前に使用してください。おそらく、適切な場合にのみ、ユーザーコンテンツを英数字に強制します。preg_replace("/[^A-Za-z0-9]/", '', $string);
ただし、ここで許可する内容には十分注意してください。コンテンツが引用符で囲まれている場合にのみコンテンツを含めてください。htmlspecialchars/htmlentitiesはここでは保護されないことに注意してください。htmlエンティティに変換されている場合でも、実行時に解釈されます。これは、次のようなものに適用されます。
<a href="www.stackoverlow.com/?id=<?php echo (int)$id; ?>">Click</a>
href, src, style, onClick, etc.
intまたはその他の非常に限定された文字セット(実行していることがわかっている場合)に強制されていない限り、スクリプトタグの本文などの他の領域にユーザーコンテンツをエコーしないでください。
SQLインジェクション:プリペアドステートメントを 使用し、ユーザーコンテンツをそれらにバインドし、ユーザーコンテンツをクエリに直接挿入しないでください。さまざまな基本ステートメントタイプのヘルパー関数を使用して、プリペアドステートメントのクラスを作成することをお勧めします(そして、主題については、すべてのデータベースステートメントを機能化します)。プリペアドステートメントを使用しないことを選択した場合は、mysql_real_escape_string()または同様のもの(addslashes()ではない)を使用してください。整数データ型の強制/チェック、型の条件付きチェックなど、データベースに格納する前に、可能な場合はコンテンツを検証します。適切なデータベース列の型と長さを使用します。ここでの主な目標はSQLインジェクションを防ぐことですが、オプションでここでもhtml/javascriptインジェクション保護を行うことができます。
その他のリソース 私は、すでに公開されている簡単な解決策を見つけることを期待して、オンラインでいくつかの調査を行いました。OWASP ESAPIを見つけましたが、かなり古いようです。phpバージョンへのリンクはいくつかの場所で壊れています。ここで見つけたと思います。ESAPI PHPですが、やはりかなり古く、私が望んでいたほど単純ではありません。ただし、便利な場合があります。
全体として、onClick属性でhtmlentitiesを使用するなど、保護されていると思い込まないでください。適切な場所で適切なツールを使用し、間違った場所で物事を行わないようにする必要があります。
この質問には、すでにいくつかの回答がユーザーによって受け入れられ、評価されています。
代わりに私も答えを投稿しています、これがうまくいくことを願っています。
これは私がテストしたものです。
1) Use strip_tags() //Prevent html injection
2) mysqli_real_escape_string //suspicious element
3) preg_replace("/[\'\")(;|`,<>]/", "", $value); //This will replace match
好きなことを試すことができます。