私はソフトウェア開発者であり、アプリケーションのセキュリティの研究を始めており、SQLインジェクションに関連する以下の疑問があります。
私はビデオコースをフォローしていますが、次の2つの例があります。
次のような安全でないSQLクエリがあります。
txtSql = "SELECT * FROM Users WHERE UserId = " + txtUserId
渡されたtxtUserId
の値が99 OR 1 = 1
のようなものである場合、次のようなクエリを取得します
SELECT * FROM Users WHERE UserId = 99 OR 1 = 1
1 = 1
は常にtrueであり、Users
連結はtrueを返すため、次のクエリのようになるため、OR
テーブルに含まれるレコードのリスト全体が返されます。
SELECT * FROM Users WHERE TRUE
レコードのリスト全体を返します。この推論は正しいですか?
次に、この2つ目のより洗練された例を示します。
ユーザーログインフォーム(ユーザー名とパスワード)があります。このフォームの背後には、安全でないクエリ実装があります。
sql = 'SELECT * FROM USERS WHERE Name = "' + uName + '" AND Pass = "' + uPass + '"'
ユーザーがログインフォームに次のデータを挿入した場合:
uName = " OR ""="
uPass = " OR ""="
結果のクエリは次のようになります。
SELECT * FROM Users WHERE Name = "" OR ""="" AND Pass = "" OR ""=""
だからそれはレコードを選択しています
Name
フィールドは空( "")または"="
に等しい(そして、空のユーザー名や "="のようなユーザー名を持つのはかなり奇妙なので、この条件は常にfalseでなければなりません)。
Pass
フィールドは空( "")または"="
に等しい(そして、空のパスワードや "="のようなパスワードを持つのはかなり奇妙なので、この条件は常にfalseでなければなりません)。
したがって、次のような条件があります。
WHERE FALSE AND FALSE
そして、ここで私の疑問:FALSE AND FALSE = FALSE
このクエリがユーザーテーブルのレコードのリスト全体を返すと言うのはなぜですか?
ロジックを正しく理解していれば、2番目のクエリは次のように変換されます。
SELECT * FROM Users WHERE FALSE AND FALSE
私の推論の何が問題になっていますか?何が欠けていますか?
あなたは注射、特にこの部分を誤って読みました:
""=""
これは、Name
が等号かどうかをチェックするのではなく、空の文字列が空の文字列と等しいかどうかをチェックします。これは1=1
と実質的に同じものであり(ここでは1=1
も使用できた可能性があります)、したがってTRUE
と同等です。したがって、この句:
Name = "" OR ""=""
Name="" OR 1=1
およびName="" OR TRUE
と同じ
そのようなことを誤解するのは簡単です。それ以外の場合はこれらの概念を明確に理解しているため、これで十分です。ただ、ペダントになるために、クエリは基本的に次のように要約されます。
WHERE Name="" OR TRUE AND Pass="" OR TRUE
次に何が起こるかは、優先順位によって異なりますが、おそらく問題ありません。あなたが使うことができるもう一つのトリックは、バックスラッシュでユーザー名を終わらせることですPass
を一緒にクエリから削除してください(これはSQLのすべての種類で機能しないかもしれません)。 User=\
とPass= OR 1=1 --
(コメントで終わる)を挿入するとします。あなたはこのクエリで終わるでしょう:
SELECT * FROM USERS WHERE Name="\" AND Pass = " OR 1=1 --"
バックスラッシュのため、Name
of " AND Pass =
(何にも一致しない)が検索されますが、OR 1=1
はすべてに一致します。最後のコメントは、構文エラーの原因となる最後の二重引用符を取り除きます。このフォームを使用すると、Pass
列の検索を効果的に無効にして、すべてのAND
/OR
句を破棄することで、クエリをより詳細に制御できます。たとえば、Pass
条件をOR ID=10
に変更することにより、実際のIDを検索できます(ID
列があると想定)。