他の回答はすでにあなたが知る必要があることをカバーしています。しかし、それはもう少し明確にするのに役立ちます:
あなたがする必要がある2つの事があります:
1.フォームデータを検証します。
以下のようジョナサン・ホッブズ回答ショーは非常に明確に、フォーム入力のためのhtml要素の選択は、あなたのための任意の信頼性の高いフィルタリングを行いません。
検証は通常、データを変更しない方法で行われますが、フィールドには「これを修正してください」とマークされたフォームが再度表示されます。
ほとんどのフレームワークとCMSには、このタスクに役立つフォームビルダーがあります。それだけでなく、攻撃のもう1つの形式であるCSRF(または「XSRF」)に対しても役立ちます。
2. SQLステートメントの変数をサニタイズ/エスケープします。
..または、準備されたステートメントに任せてください。
(My)SQLステートメントを、ユーザー指定の変数かどうかに関係なく変数で作成する場合は、これらの変数をエスケープして引用符で囲む必要があります。
一般に、MySQLステートメントに挿入するそのような変数は、文字列か、PHPがMySQLで消化できる文字列に確実に変換できるものでなければなりません。数など。
文字列の場合、文字列をエスケープするためにいくつかの方法の1つを選択する必要があります。つまり、MySQLで副作用のある文字を置き換えます。
- 昔ながらのMySQL + PHPでは、mysql_real_escape_string()がその役割を果たします。問題は、簡単に忘れることができるため、準備されたステートメントまたはクエリビルダーを絶対に使用する必要があることです。
- MySQLiでは、準備済みステートメントを使用できます。
- ほとんどのフレームワークとCMSには、このタスクに役立つクエリビルダーが用意されています。
数値を扱う場合は、エスケープと引用符を省略できます(これが、準備されたステートメントで型を指定できる理由です)。
SQLステートメントの変数はエスケープし、データベース自体はエスケープしないことを指摘することが重要です。データベースは元の文字列を格納しますが、ステートメントにはエスケープバージョンが必要です。
これらの1つを省略するとどうなりますか?
フォーム検証を使用せずに SQL入力をサニタイズすると、あらゆる種類の問題が発生する可能性がありますが、SQLインジェクションは表示されません。(*)
まず、アプリケーションを予定外の状態にすることができます。たとえば、すべてのユーザーの平均年齢を計算したいが、1人のユーザーが年齢に「aljkdfaqer」を与えた場合、計算は失敗します。
第二に、考慮する必要のある他のあらゆる種類のインジェクション攻撃がある可能性があります。たとえば、ユーザー入力にJavaScriptまたはその他のものが含まれている可能性があります。
それでもデータベースに問題がある可能性があります。たとえば、フィールド(データベーステーブルの列)が255文字に制限されていて、文字列がそれより長い場合などです。または、フィールドが数字しか受け入れず、代わりに非数値文字列を保存しようとした場合。しかし、これは「注入」ではなく、単に「アプリケーションをクラッシュさせる」だけです。
ただし、検証なしで入力を許可するフリーテキストフィールドがある場合でも、データベースステートメントに移動するときに適切にエスケープすれば、これをそのままデータベースに保存できます。この文字列をどこかで使用したいときに問題が発生します。
(*)またはこれは本当にエキゾチックなものになります。
SQLステートメントの変数をエスケープしなくても、フォーム入力を検証した場合でも、問題が発生していることがわかります。
まず、データベースにデータを保存して再度ロードすると、同じデータでなくなり、「翻訳が失われる」というリスクがあります。
次に、SQLステートメントが無効になり、アプリケーションがクラッシュする可能性があります。たとえば、変数に引用符または二重引用符が含まれている場合、使用する引用符のタイプに応じて、無効なMySQLステートメントが取得されます。
第三に、SQLインジェクションを引き起こす可能性があります。
フォームからのユーザー入力が既にフィルター/検証されている場合、入力がハードコードされたオプションのリストに減らされるか、数値に制限されていると、意図的な SQlインジェクションの可能性が低くなる可能性があります。ただし、SQLステートメントの変数を適切にエスケープしないと、任意のフリーテキスト入力をSQLインジェクションに使用できます。
そして、フォーム入力がまったくない場合でも、あらゆる種類のソースからの文字列を保持できます。ファイルシステムからの読み取り、インターネットからのスクレイピングなど。これらの文字列が安全であることを誰も保証できません。
<select>
入力に必要な値を送信することを妨げるものはありません。実際、少し技術的なユーザーでも、ブラウザコンソールを使用してオプションを追加できます。利用可能な値の配列ホワイトリストを保持し、それと入力を比較する場合、それを軽減できます(不要な値を防ぐためです)