ハッカーが文字と数字だけを使用してSQLインジェクション攻撃を実行することがまったく可能かどうか疑問に思っていました。たとえば、組み込みのPHP関数の代わりに正規表現を使用するこのPHPコードを見てみましょう。
<?php
$id = preg_replace('/[^a-zA-Z0-9]/', '', $_GET['id']);
$result = $mysqli->query("SELECT * users WHERE id = '".$id."'");
コードが何をするのか疑問に思われる場合は、文字や数字以外のすべての文字を削除し、MySQLでそのクエリを実行します。ハッカーがそのコードを何らかの方法で悪用できるかどうか疑問に思っていましたが、そうでない場合、それとmysqli::prepare
またはmysqli::escape_string
の違いは何でしょうか?
MySQL文字列リテラル コンテキストに$id
値が挿入され、任意のSQLフラグメントを提供することが可能である場合にのみ、セキュリティ上の欠陥があります。そして、これは、$id
に、MySQL文字列リテラルの終了区切り文字を示すプレーンな'
が含まれている場合にのみ可能です。
// resulting SQL statement with $id = "' OR '1'='1"
SELECT * users WHERE id = '' OR '1'='1'
ここで、'
から$id
文字を削除するため、文字列リテラルコンテキストを離れることはできず、したがって任意のSQLフラグメントを提供することはできません。
ただし、この結論は、値がMySQL文字列リテラルで使用される場合にのみ適用されます。別のクエリの値に対して同じ入力フィルタリングを使用している場合でも、SQLインジェクションに対して脆弱である可能性があります。
つまり、mysqli::prepare
やmysqli::escape_string
などのメソッドは適切な緩和手法です。 mysqli::prepare
は、いわゆるパラメーター化されたステートメント/クエリを実装します 準備されたステートメント ここで、コマンド(SQLステートメント)とユーザー提供のデータは互いに分離されているため、ユーザーは提供されたデータを誤ってコマンドとして解釈することはできません。 mysqli::escape_string
は、データの特定の文字をエスケープするだけで、文字列リテラルの終了区切り文字のような制御文字と混同されないため、現在の手法に似ています。
(私はこれをコメントとして投稿しますが、コメントはリンクをきちんと行いません)。
これはスタックオーバーフローでは similar から manyquestions へとかなり変わります。
Open Web Application Security Project(OWASP) 注意事項 その 特殊文字のエスケープ は、SQLインジェクションに対する防御策です。
- 準備済みステートメント(パラメーター化されたクエリ)とストアドプロシージャを使用する
- Ifパラメータ化されたAPIが利用できない...特殊文字をエスケープする
- ホワイトリスト入力検証を実行する
特殊文字なしでSQLiを実現する概念実証コードに関する限り、私は何も見ていませんが、証拠がないことは、存在しないという証拠ではありません。パラメーター化されたクエリを実装できる場合は、実装しないでください。
一般的な経験則:車輪を再発明しないでください!
あなたが提供したコードはおそらく悪用可能ではありませんが、可能な限り、準備されたステートメントを使用するいくつかの正当な理由があります(優れた 永続フレームワーク はさらに優れています)。
SQLインジェクションはMySQLの16進リテラルのサポートであり、投票テーブルのid列が文字列型であるという事実は次のようになります。
文字列コンテキストでは、これらはバイナリ文字列のように機能し、16進数の各ペアが文字に変換されます。
mysql> SELECT 0x0f+0;
-> 15
PHP 0x…は数値(is_numeric)であり、MySQLの場合0x…は文字列として解釈および保存され、後で上記のSELECTステートメントに挿入されます。
これは、次の場合には不可能です。
idは数値データ型、またはSELECTは準備済みステートメントでした。
したがって、0x [0-9a-f] .....で始まる16進エンコードされたペイロードを挿入するために使用できる0-9およびa-zを許可しているため、16進エンコードされたペイロードが通過する可能性があります。