web-dev-qa-db-ja.com

PHPでユーザー入力をサニタイズする最良の方法はどれですか?

ユーザー入力をサニタイズする最良の方法は何ですか?

これらは、ユーザーがデータを送信するときに行うことです。

  1. substr制限値を超えた場合。
  2. htmlspecialchars() + ent_quotes + UTF-8
  3. str_replace '<' '>'ユーザー入力

他に何をする必要がありますか?

31
user2615947

「サニタイズ」は役に立たず、誤解を招く用語です。ここには2つの異なる動物があります。

  1. 出力のエスケープ。これは出力段階の問題です。可変文字列を取り、それらを周囲の構文を持つより大きな文字列に注入する場合、注入された文字列を処理して、その構文の要件に準拠させる必要があります。その処理が正確に何であるかは、コンテキストに依存します。HTMLにテキストを入れる場合、HTMLを作成する時点でそのテキストをHTMLエスケープする必要があります。 SQLクエリにテキストを入れる場合は、クエリの作成時にテキストをSQLエスケープする必要があります。(*)

  2. 入力の検証。これは入力ステージの問題であり、ユーザー入力がデータ項目の受け入れ可能な値の範囲内であることを確認します。これは主にビジネスルールの問題であり、フィールドごとに考慮する必要がありますが、ほとんどすべての入力フィールド(主に制御文字をチェックする)に対して行うのが理にかなっている検証の種類があります。

入力の検証は、出力のエスケープで誤りを犯した場合の被害を軽減できるという点で、セキュリティに影響を与えます。しかし、ユーザーがsome構文などの特殊な文字を常に使用できるようにする必要があるため、唯一のテキスト処理手段として入力検証に依存するだけでは十分ではありません。 fish & chipsに関するWebページと、データベースにO'Reillyという顧客を表示できるようにする必要があります。

「サニタイズ」はこれら2つの概念を混同し、一貫して機能することができない同じ段階でそれらに取り組むことを推奨します。一般的なアンチパターンは、すべての入力をHTMLエスケープすることです。ただし、その入力処理フェーズで各入力要素がHTMLに出力される(そしてonly HTMLに出力される)かどうかはわかりません。これを行う場合:

  • 最終的に、データベース内のHTMLエンコードされた素材になり、エンティティの参照が邪魔にならない限り、切り取って処理することはできません。

  • 電子メールを送信したり、CSVを書き込んだりするなど、HTML以外のデータからコンテンツを作成する必要がある場合は、見苦しいテキストが含まれています。

  • 他のソースからデータベースのコンテンツを取得した場合、HTMLエスケープされない可能性があるため、ページに直接出力すると、XSSの脆弱性が依然として残ります。

概念としての「サニタイズ」は、火によって破壊され、その後溺死し、小さな断片に切り分けられ、再びいくつかの火によって破壊されるべきです。

(*:どちらの場合も、暗黙的に処理を行うメソッドを選択する方が賢明です。間違ってしまうことはありません。デフォルトで出力をエスケープするHTMLテンプレート言語を使用し、パラメーター化されたクエリを使用するデータアクセスレイヤーを使用するか、オブジェクトリレーショナルマッピング。他の種類のエスケープの場合も同様です。手動のXMLエスケープよりも標準に準拠したXMLシリアライザーを優先し、標準のJSONシリアライザーを使用してJavaScriptにデータを渡します。

制限値を超える場合はsubstrが見つかりました。

長すぎる入力文字列を切り捨てることを意味しますか?これは、ビジネスルールに入力の長さを制限する正当な理由がある入力検証の形式としては問題ありません。ただし、入力文字列が長すぎる場合は、ユーザーにエラーを返すことをお勧めします。これは、フィールドによっては、静かにデータを破棄することが適切でない場合があるためです。

htmlspecialchars()+ ent_quotes + UTF-8

これは出力エスケープです。入力ではなく、HTMLにドロップした時点で値に対して実行します。ネイティブのPHPテンプレートを使用している場合は、ショートカットを定義して、すばやく入力できるようにすることができます。次に例を示します。

function h($s) {
    echo htmlspecialchars($s, ENT_QUOTES, 'utf-8')l
}
...

<p>Hello, <?php h($user['name']); ?>!</p>

str_replace <>ユーザーが入力

何のために? HTMLエスケープが正しく行われている場合、これらの文字は完全に問題ありません。ビジネスルールで特に明記されていない限り、フィールドに含めることは非常に有効です。これは、SOのコメントボックスに両方の文字を入力するのが有効だからです。

もちろん、特定のフィールドの入力検証でそれらを許可しないこともできます。電話番号には使用しないでください。

49
bobince

私はOWASP PHP= Filtersを使用しています。これらは非常に使いやすく効果的です。

https://www.owasp.org/index.php/OWASP_PHP_Filters

ソースコードは非常に読みやすいです。そこには苦痛なレッスンがたくさんあります。

11
mgjk

これは何年も前の問題であるため、サイトが他のサイトに存在する可能性のあるリンクを維持または対処していないため、いくつかの変更があり、外部リンクが折りたたまれます。

したがって、PHPは少し進んで、多くの人々が入力のサニタイズについて質問しますが、filter_varの使用は根本的に薄いですが、完璧ではありません。私の読書、バイナリセーフ。

つまり、PHP filter_varと組み合わせて使用​​する必要がある場合にHTML5を使用しない限り、メールアドレスを取得できます。 HTML5入力を使用しない入力をサニタイズするルーチンHTML5に準拠していないブラウザーの下位互換性のためのコードを記述することは、完全に無意味であり、リソースと時間の無駄です。

セキュリティのもう1つの問題は、$ _ GETと$ _POSTの値が揮発性で、外部から適切なデータに変更または変更される可能性があることです。そのため、これらを使用してクリーンな入力をそれらに戻すサニタイズルーチンは、トラブル... $ _REQUEST配列の方が安全です。一度安全な配列に設定すると、変更できなくなります。したがって、安全な配列に入力とfilter_varを入力して、安全な配列に入力します。

入力をサニタイズする方法は次のようなものです...

$someSafeArray = array(
        "thefield"=>FILTER_SANITIZE_STRING,
        "theNumberfield"=>FILTER_SANITIZE_NUMBER,
        "theEmailfield"=>FILTER_SANITIZE_EMAIL
        );
foreach( $someSafeArray as $fld=>&$val)
    $val = filter_var( trim( $_REQUEST[$fld] ), $val );

したがって、これは(キーから)すべてのフィールドを返し、サニタイズされた入力がセーフ配列のそれらのキーの値に入れられます。

つまり、ホワイトリスト(配列)のキーを使用して、有効なフィールドとして指定した入力のみを取得します。どんな入力も受け入れる「ダイナミック」フォームプロセッサを提供している人が多すぎます。コード/フォームが処理するように設計されているデータストリームのみを受け入れる必要があります。

受信フォームが正しいハッシュを再計算してサーバーによってフォームが発行されたことを確認する値でページをソルトします。EMPTYフィールド。読み取り専用で、ハッシュフィールドのように非表示になっている少なくとも1つの空白フィールドを含めますが、意図は特定することです。フォームがプッシュされているかどうかにかかわらず、ボットはすべてのフィールドにデータを入力して、ページを開いてクラックしようとします。

SOのようないくつかのダミーフィールドでページをベイトする...

<input name="userlogin" type="hidden" value="" readonly />
<input name="empty" type="hidden" value="" readonly />

フォームがいずれかの入力の値フィールドに何かが含まれる状態でサーバーに到着した場合、フォームの処理を中止してユーザーIPをログに記録し、ボットまたはハッカーであることからブロックすることもできます。

インジェクションはSQLの問題だけでなく、PHPページの問題でもあるため、どのフィールドを受け入れ、saltbaitをフォームに含めるかについて注意してくださいホワイトリストを使用して操作します。

GETの使用を停止して制御パラメーターを渡し、セッションCookieを使用して、スクリプトへの入力を減らします。GETタイプのURLを使用すると、破壊的な戦術でのみ使用でき、URLやその他のものに変数を突っ込んでいるユーザーを監視できます。ハックしようとします。

Filter_var関数が導入される前に、データベースを必要とせずにページをソルトしていたため、このようなプロセスを使用してきましたが、いわゆる専門家から繰り返し言われたことは不可能でした。私が言わなければならない唯一のことは、「ボイラープレートの外側で考えることができるかどうかです(ボックス)」、そしてハッキングの試みを阻止するのに十分なほど単純で、フォームページを保護します。

4
Mark Giblin

個人的には、<>をstr_replaceすることはありません (ストリップタグhtml特殊文字htmlエンティティエンコーディングmysql_real_escape_string など、ユーザー入力。

考慮する必要があるのは、データの表現方法です。

  • フロントエンドで出力されるのでしょうか?
  • データベースに入りますか?
  • フロントエンドのJavascriptで使用されますか?
  • ファイルの取り込みにいかがですか?

フロントエンドに入る場合は、htmlentitiesとstrip_tags imoを使用して、不要なコードを実行しないようにする必要があります。

また、スラッシュを取り除くことは非常に重要な考慮事項です。最近、WP Platinum SEO pluginでXSSをキャッチしました。これを$ _GET ['s']パラメータを通じてすべてにエンコードすることにより、JavaScriptコードを実行できます。エスケープされた16進コード(\\ x41 = A)。

データベースにデータを入力する場合は、PDOで準備されたクエリおよび mysql_real_escape_string を確認してください。これにより、データベース入力がかなり安全になります。

ユーザー入力を使用してファイルをリクエストする場合は、それが Poison Null Byte 攻撃の影響を受けないことを確認してください。私の意見では、ファイルインクルードのすべてのスラッシュを常に削除して、場所にアクセスできないようにします。望ましい。また、php.iniファイルで allow_url_include/allow_url_fopen をオフにすることをお勧めします。

これが役に立てば幸いです!

0
DarkMantis