2009-08-21 8 views
27

PHPによる$ _GET -variablesのデータのサニタイズ方法は?GETによるPHPによるユーザのデータのサニタイズ

GETの変数をstrip_tagsで1つだけ消毒します。 最後にPostgresにデータを置くので、すべてを消毒すべきかどうかはわかりませんが、問題はpg_prepareの使用によって最も簡単に解決されました。

+1

SQLインジェクションやXSS攻撃を避けるためにサニタイズする? –

答えて

74

はどのようにPHPで$ _GET - 変数内のデータをサニタイズしますか?

$ _GETのデータをサニタイズしません。これはPHPスクリプトの一般的なアプローチですが、完全に間違っています*。

すべての変数は、別のタイプの文字列に埋め込むまで、プレーンテキストの形式にとどまります。値を埋め込んでいる可能性のある文字列をすべてカバーするエスケープまたは「サニタイズ」の形式はありません。

あなたはSQLクエリに文字列を埋め込むしているのであれば、あなたは途中うちにそれをエスケープする必要があります:

$sql= "SELECT * FROM accounts WHERE username='".pg_escape_string($_GET['username'])."'"; 

そして、あなたが出てHTMLに文字列を吐きている場合は、エスケープする必要がありますそれ:

Cannot log in as <?php echo(htmlspecialchars($_GET['username'], ENT_QUOTES)) ?>. 

、彼らがやっているのかわからない人々によって推奨されているようにあなたは、開始時の$ _GET配列のこれらの脱出手順の両方を行った場合:

$_GET['username']= htmlspecialchars(pg_escape_string($_GET['username'])); 
を10

あなたのユーザー名に「&」と入力した場合、データベース内で「& amp;」になり、ユーザー名にアポストロフィがあると、ページ上で2つのアポストロフィに変わります。そして、これらの文字を含むフォームがあると、編集時にダブルエスケープすることになります。そのため、多くのPHP CMSが「O \\\\からの新しい書籍」 \\\\\\\\\\\\ 'ライリー」。

当然ながら、変数を送信するたびにpg_escape_stringやmysql_real_escape_string、htmlspecialcharsを覚えておくのはちょっと面倒です。なぜなら、誰もがスクリプトの最初の場所で(間違って)それをやりたいからです。 HTML出力では、エコーを行う短い名前の関数(htmlspecialchars(...))を定義することで、少なくとも入力の手間を省くことができます。

SQLの場合、パラメータ化されたクエリを使用する方がよいでしょう。 Postgresにはpg_query_paramsがあります。または実際には、あなたが言及したように準備された声明(私は個人的に彼らが管理しにくいと思うが)。いずれにしても、SQLの「サニタイズ」やエスケープを忘れることはできますが、HTMLを含む他のタイプの文字列に埋め込んでもエスケープする必要があります。

strip_tags()は、HTML表示の入力を処理する良い方法ではありません。過去にはセキュリティ上の問題を抱えていました。ブラウザパーザーは実際にはタグがあなたの考えるよりもはるかに複雑であるためです。ほとんどの場合、htmlspecialchars()は代わりに使用するのが適切です。そうすれば、誰かが小文字の記号を入力した場合、実際には小文字の記号が表示され、テキストの半分は不思議に消えません。

(*:注射の問題を解決するための一般的なアプローチとして、とにかく特定のフィールドで実行する価値のあるドメイン固有のチェックがあります。また、送信された値からすべての制御文字を削除するなどの便利なクリーンアップタスクがありますしかし、これはほとんどのPHPコーダーがサニタイズの意味ではありません。)

+0

あなたがHTML *を含む他のタイプの文字列に埋め込んでいる場合**あなたがプリペイドステートメントを使用するときに私がdbに置いたユーザ名と電子メールをエスケープする必要はないのですか?** - 私はそのユーザのユーザ名のみを表示します –

+5

いいえ:SQL文字列に出力するには、SQLエスケープを使用します(または、パラメータ化/プリペアドステートメントで自動的に行いますが、両方ではありません)。 )HTMLに出力するには、HTMLエスケープ(htmlspecialcharsを使用)を使用します.HTMLエスケープ・テキストをSQL文字列に入れたり、SQLエスケープ・テキストをHTMLページに入れたりしないでください。 – bobince

5

出力を消毒することについて話している場合は、データをエコーアウトしているときに、完全なエスケープされていない形式でデータベースにコンテンツを格納してからエスケープすることをおすすめします(詳細はhtmlspecialcharsなど)出力のオプション。データベースコンテンツのサニタイズ/エスケープについては、thisの質問を参照してください。

ポストグルでの格納に関しては、クエリの各変数にpg_escape_stringを使用して引用符をエスケープし、一般にSQLインジェクションから保護します。その後、データベース内のデータを格納するための

私の通常の手順、およびそれを取り出し、以下のとおりです:

編集

  1. は脱出するために、(などpg_escape_string、mysql_escape_string、)関数をエスケープデータベースのデータを呼び出しあなたのクエリで使用される各入力$ _GET変数。 addslashesの代わりにこれらの関数を使用すると、データベースに格納されたときにテキストに余分なスラッシュが付きません。

  2. データをデータベースから取り除くと、出力されたデータにhtmlspecialcharsを使用するだけで、スラッシュを追加しないで、stripslashesを使用する必要はありません。

+0

ユーザーにエスケープされたデータを渡すと、スラッシュが表示されます。 **ユーザーのためにデータを再び読みやすくするために使用する関数はどれですか?** –

+0

文字列からスラッシュを削除するには、stripslashes(http://uk2.php.net/stripslashes)を使用できます。 – Kazar

+0

** 'htmlspecialvars'と' stripslashes'文をすべてのステートメントに置く必要なしに、 '$ _GET'と' $ _POST'変数でデータをサニタイズするシステム全体のオプションはありますか?** –

3

POSTはGETだけでなく、すべての要求をサニタイズする必要があります。

あなたはキャストによって正規表現、またはフィルタと機能htmlentities()、関数にpreg_replace()を使用することができます。

<? 
$id = (int)$_GET['id']; 
?> 

[]さん

+0

私は、すべてのリクエストがエスケープされなければならないことに同意します。 しかし 'pg_prepare'を使うと' pg_prepare'はデータを消毒するので、私の意見では 'htmlentitiies'という関数は必要ありません。 –

+0

正規表現を使用して出力をサニタイズしないでください - あなたは何かを見逃してしまい、誤ってXSSの脆弱性を露呈してしまいます。カスタム出力サニタイズを行うための良いライブラリがあります(http://htmlpurifier.org/) – Kazar

+2

Masi:それは間違っています。危険な。 pg_prepareはSQLエスケープを扱います。 HTMLエスケープとは何も関係がありませんし、迷子の<やキャラクターによるXSS攻撃からあなたを守ることはできません。 – bobince

2

は、それが起こっている場所に応じて、あなたの入力をサニタイズ。

  • あなたは(ページ上または入力フィールドの値として)それを表示した場合、htmlspecialcharsおよび/またはstr_replaceを使用しています。
  • 別のタイプとして使用する場合は、キャストしてください。
  • SQLクエリに含める場合は、適切な関数を使用してエスケープします(エスケープされていないものを完全に削除したい場合はhtmlタグを削除してください)。

DB内のデータは通常エスケープされないため、POSTやDBのデータと同じです。あなたがチェックする必要があり

2つのこと:あなたの入力対の

  1. エンコーディングPHPスクリプト/出力/ DBテーブル
  2. [magic_quotes_gpc][1]を有効にしている場合は、できるだけ無効にするか、またはstripslashes() GET、POST、COOKIEの値を無効にする必要があります。 magic_quotes_gpcは推奨されていません。のデータを使用してを使用して、操作するデータを消毒する必要があります。
関連する問題