サーチ…
前書き
SQLインジェクションは、フォームフィールドにSQLを挿入してWebサイトのデータベーステーブルにアクセスしようとする試みです。 WebサーバーがSQLインジェクション攻撃から保護しない場合、ハッカーはデータベースを騙して追加のSQLコードを実行することができます。ハッカーは、独自のSQLコードを実行することで、アカウントへのアクセスをアップグレードしたり、他のユーザーの個人情報を表示したり、データベースを変更したりすることができます。
SQLインジェクションサンプル
Webアプリケーションのログインハンドラへの呼び出しが次のようになっていると仮定します。
https://somepage.com/ajax/login.ashx?username=admin&password=123
login.ashxでは、次の値を読んでいます。
strUserName = getHttpsRequestParameterString("username");
strPassword = getHttpsRequestParameterString("password");
データベースに照会して、そのパスワードを持つユーザーが存在するかどうかを判断します。
したがって、SQLクエリ文字列を作成します。
txtSQL = "SELECT * FROM Users WHERE username = '" + strUserName + "' AND password = '"+ strPassword +"'";
これは、ユーザー名とパスワードに引用符が含まれていない場合に有効です。
ただし、パラメータの1つに引用符が含まれている場合、データベースに送信されるSQLは次のようになります。
-- strUserName = "d'Alambert";
txtSQL = "SELECT * FROM Users WHERE username = 'd'Alambert' AND password = '123'";
これにより、 d
d'Alambert
後の引用符がSQL文字列を終了するため、構文エラーが発生します。
あなたはユーザー名とパスワードの引用符をエスケープすることでこれを訂正することができます。
strUserName = strUserName.Replace("'", "''");
strPassword = strPassword.Replace("'", "''");
ただし、パラメータを使用する方が適切です。
cmd.CommandText = "SELECT * FROM Users WHERE username = @username AND password = @password";
cmd.Parameters.Add("@username", strUserName);
cmd.Parameters.Add("@password", strPassword);
パラメータを使用せず、いずれかの値でも引用符を置き換えるのを忘れた場合、悪意のあるユーザー(ハッカーとも呼ばれます)がこれを使用してデータベース上でSQLコマンドを実行できます。
たとえば、攻撃者が悪い場合は、パスワードを次のように設定します。
lol'; DROP DATABASE master; --
SQLは次のようになります。
"SELECT * FROM Users WHERE username = 'somebody' AND password = 'lol'; DROP DATABASE master; --'";
残念ながら、これは有効なSQLであり、DBはこれを実行します!
このタイプの悪用は、SQLインジェクションと呼ばれます。
すべてのユーザーの電子メールアドレスを盗み、誰のパスワードも盗んだり、クレジットカード番号を盗んだり、データベースのデータを盗んだりするなど、悪意のあるユーザーが行うことができる他にもたくさんのことがあります。
これは、常にあなたの弦をエスケープする必要がある理由です。
そして、遅かれ早かれそうすることをいつも忘れてしまうという事実は、まさにあなたがパラメータを使うべき理由です。パラメータを使用すると、プログラミング言語フレームワークが必要なエスケープ処理を行うためです。
簡単な注入サンプル
SQL文が次のように構築されているとします。
SQL = "SELECT * FROM Users WHERE username = '" + user + "' AND password ='" + pw + "'";
db.execute(SQL);
次に、ハッカーはpw' or '1'='1
ようなパスワードを与えてデータを取得することができます。結果のSQL文は次のようになります。
SELECT * FROM Users WHERE username = 'somebody' AND password ='pw' or '1'='1'
これは、 '1'='1'
が常に真であるため、 Users
テーブルのすべての行のパスワードチェックをパスします。
これを防ぐには、SQLパラメータを使用します。
SQL = "SELECT * FROM Users WHERE username = ? AND password = ?";
db.execute(SQL, [user, pw]);