こんにちは。帳簿を見返していたら、意外とマスク代は馬鹿にできないなーと感じているひろです。
皆さんは、データベースを扱ったり、PHPでのウェブ開発をしている際に、SQLでの攻撃というものを耳にしたことはありますか?
ウェブ開発において、絶対に欠かしてはいけないのが情報漏えい等の攻撃対策。ですが、実際どのような攻撃が行われているのかわからないと、対策のしようがありませんよね。
今回は、データベースを扱うサイトに置いて絶対に対策しなければならない
について解説していきます。ぜひこの記事を参考に、ウェブ開発を進めていってくださいね。
目次
入力フォームに不正な値を入れて攻撃する「SQLインジェクション」
簡単に言うと、SQLインジェクションというのは「入力フォームに不正な値を入れ、攻撃を行う」というものです。
例えば、以下のコードを見てみてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?PHP if(!empty($_POST['email'])){ $pdo = new PDO('mySQL:dbname=test;host=localhost;charset=utf8', 'root', '', [ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]); $SQL = 'SELECT user_name FROM users WHERE email = ' . $_POST['email']; $result = $pdo->query($SQL); } ?> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <h1>入力したemailアドレスの持ち主の名前:<?PHP echo (empty$result) ? '存在しません。' : $result; ?></h1> <form action="" method="post"> <input type="text" name="email"> <input type="submit" value="表示"> </form> </body> </html> |
このコードは、testというデータベースから、入力された情報とusersテーブルにあるemailカラムが同じデータのuser_nameを取得し、画面に表示する、というコードになります。もしも取得ができなかった場合は、「存在しません。」と表示されます。
試しにデータベースを構築してデータをいくつか作成し、動かしてみてください。
そして、次に入力フォームに以下の文字列を入力してみてください。
1 |
a OR a = a |
そうすると、全てのデータが取得できてしまいました。
なぜか?というと、入力された文字列をもとにSQLを作成すると、以下のコードになります。
1 |
$SQL = 'SELECT user_name FROM users WHERE email = a OR a = a'; |
日本語に直すと、「usersテーブルから、user_nameを取得してください。条件は、emailがa、もしくはaがaのものです」となります。
emailがaというのは引っかからないかと思いますが、後半のaがaというものは、一瞬意味が分かりづらいですが、「a」が「a」であるか?というとたしかにそうだと言えます。aはaです。
なので、この条件に引っかかるもの、つまり全てのデータが取得できてしまう、というものになります。これが、簡単なSQLインジェクションの仕組みです。
SQLインジェクションの種類
エラーベースSQLインジェクション
データベースに対して故意にエラーメッセージを吐かせることで、対象のデータベースサーバーの脆弱性やセキュリティを知ることができるというSQLインジェクション攻撃です。
本格的な攻撃の前に、相手がどのようなデータベースかを知ることができるため、次の攻撃準備のためのSQLインジェクション攻撃となります。
ブラインドSQLインジェクション
不正なSQLを用いて、サーバーからの応答や動作をもとに、データベースの構造を知るというSQLインジェクション攻撃です。何回も繰り返し行い、集めたデータからどのようなデータベースになっているかを把握する攻撃になります。
こちらもエラーベースSQLインジェクションと同じく、次の攻撃準備のためのSQLインジェクション攻撃です。
マルチプルステートメントを使用した攻撃
セミコロンでSQL文を区切り、複数のSQL文を連結させる「マルチプルステートメント」という機能を攻撃に使用したSQLインジェクション攻撃があります。
構文をセミコロンで区切ることで、攻撃側に都合の良い構文をand条件として設定し、データの書き換えや入手を行うことができてしまいます。
UNION機能を使用した攻撃
UNION句というものを使用したSQLインジェクション攻撃もあります。
UNION句というのは、マルチプルステートメントのように、複数のSQL文を連結させることができるSQL文の機能になりますが、これを使用すると、全く新しいSQL文を作成して攻撃することができるため、いろいろな攻撃ができてしまう手法です。
SQLインジェクションの被害は非常に大きいものもある
SQLインジェクションはデータベースへの攻撃ですので、機密情報を知られてしまったり、データを書き換えられてしまうことによるウイルスサイトへの誘導など比較的大きな被害になることが多いです。
サウンドハウスの個人情報流出
2008年に起きた個人情報流出事件で、9万件を超える個人情報が流出し、情報の中にはクレジットカードの情報も2万件ほど含まれていたため、大規模な情報漏えい事件として話題になりました。
SQLインジェクションにより、データベースサーバーへバックドア(正規の手順を踏まずに侵入可能な出入り口)が作られ、不正ファイルを埋め込まれていたのです。結果、不正プログラムにより顧客のデータが定期的に抜き取られてしまう事態となってしまいました。
米国のプレイステーションのサイトに不正コード挿入
アメリカのプレイステーションの公式サイトの中にある、ソフト紹介ページの一部に、不正なスクリプトが埋め込まれてしまい、偽のアンチウイルスソフトの購入を進められる、という攻撃が行われました。
SQLインジェクションの対策はサニタイジングを使う
サニタイジングというのは、英語で「消毒」という意味です。プログラミングにおいては、攻撃に使われる文字や句を無効化し、安全化を図る、という意味で使われます。
入力画面でのバリデーションチェックを行う
バリデーションチェックというのは「入力チェック」や「書式チェック」と言われるものです。例えば、eメールアドレスの入力欄にはeメールアドレスの形式であるかをチェックし、eメールアドレスに使われない記号や文字列が使われていないかというチェックを行う、といったものです。
データベースに接続する前に、入力すべきでない文字が含まれているかチェックすることにより、攻撃を防ぐ事ができます。
サニタイジングの代表例が「エスケープ処理」
エスケープ処理というのは、「<」や「>」など、プログラミングにおいて特別な意味を持つ文字を別の文字に置き換える処理のことです。今回の例においては、「<」は「<」、「>」は「>」に置き換えます。htmlでこの文字列を記述すると、実際に表示されるときにはきちんと記号になっています。
SQLでのサニタイジングは「プリペアドステートメント」を使用する
プリペアドステートメントというのは、SQL文を最初に用意しておき、クエリ内のパラメータの値だけを変更してクエリを実行できる機能のことです。高速化にも使われる機能ですが、エスケープ処理を自動で行うため、安全であり、かつ効率の良い方法です。
まとめ
いかがでしたか?今回は、
について解説しました。データベースを使用する場合は必須の知識となりますので、是非参考にしてくださいね。