セキュリティ

SQLインジェクションとは | 具体的な攻撃例と対策方法

2019年11月4日

SQLインジェクションって言葉をよく聞きますが、どういうモノなんですか?
Webサイトの脆弱性を狙ったサイバー攻撃の一種だよ。
データベースに命令するSQL文を不正操作して、データベースに保存されている個人情報などを盗み取る攻撃ですよね。
そうだね。本記事ではSQLインジェクションの具体的な攻撃例や被害例、対策などを分かりやすく説明していきます。

スポンサーリンク

SQLインジェクションとは

SQLインジェクションとは、入力フォームなどから入力した「SQL文を含む文字列」で、アプリケーションが想定していないSQL文を実行させ、データベースの情報を不正操作するサイバー攻撃の一種です。

次の図は、SQLインジェクションのイメージ例です。

SQLインジェクションとは
  • SQLインジェクション対策していないWebサイトに対し、悪意のある攻撃者が「SQL文を含む文字列」を入力して検索や登録を行う。
  • 悪意のある攻撃者が入力した「SQL文を含む文字列」が実行される。
  • データベースの情報が不正操作される。
「SQL文を含む文字列」って具体的にどういうモノなんですか?
攻撃方法は様々なんだ。それでは具体的な攻撃例の一部を紹介するよ。

SQLインジェクションの攻撃例

[攻撃例1] コメントアウトでSQL文を不正操作

SQLインジェクションの攻撃例不正ログイン

よくあるログイン画面です。「ID」と「パスワード」が一致しなければログインできません。

しかし、「SQLインジェクション対策」をしていないと、「ID」と「パスワード」を知らなくてもログインできてしまう可能性があります。

その攻撃方法とは、「ID」に以下の文字列を入力してログインするだけです。※パスワードは未入力で問題ありません。

1' or '1' = '1';--
これだけでログインできるの?

前提として以下のSQL文が利用されているとします。このSQL文で画面から入力された「ID」と「パスワード」がデータベースのユーザー情報に存在するか確認し、存在すればログイン成功、存在しなければログイン失敗と判断します。

SELECT id,pass FROM login_user WHERE id='入力されたID' AND pass='入力されたパスワード';

注意

今回は例なので、パスワードをSQLの条件に追加していますが、このようなSQL文を作成してはいけません。

パスワードは「ソルト」と「ストレッチング」を実施したハッシュ値(パスワードハッシュアルゴリズム)で保管し、ハッシュ値で比較しましょう。

詳しくはこちら → パスワード管理の仕組みを図解で分かりやすく説明

このSQL文に先ほどの「ID」と「パスワード」を当てはめると、次のSQL文が作られます。

SELECT id,pass FROM login_user WHERE id='1' or '1' = '1'-- AND pass='';

まず「id」の条件が"1" または"1 = 1"という条件になっているので、結果は必ずtrueです。

そしてSQL文で「-- 」はコメントアウトを表します。そのためパスワードが一致するかを確認するための条件文「-- AND pass='';」はコメントとして扱われ無視されます。

スポンサーリンク

[攻撃例2] サブクエリでSQL文を不正操作

SQLインジェクションの攻撃例情報漏洩

会員登録画面などの入力フォームです。今回は「名前」と「メールアドレス」を登録する画面があるとします。

まず各項目に、以下を入力し登録します。

名前:山田太郎', (select user_password from user_password where id='1' limit 0,1)) -- おわり
住所:aaa@co.jp

前提として以下のINSERT文が利用されているとします。

INSERT INTO users (name,mail_address) VALUES ('入力された名前','入力されたメールアドレス')

このSQL文を使い、画面で入力した「名前」と「メールアドレス」が「users」テーブルに登録します。

また、他人のパスワードを管理している「user_password」テーブルを用意します。このデータを「SQLインジェクション」の攻撃で盗み取ることを目的とします。

※通常パスワードはソルトストレッチングを実施した「ハッシュ値(パスワードハッシュアルゴリズム)」で、データベース内に格納するのが一般的ですが、ここではあえて平文で登録しています。

iduser_iduser_password
11password

INSERT文に画面から入力された「名前」と「メールアドレス」を当てはめると、以下のようなSQL文が作られます。

INSERT INTO users (name,mail_address) VALUES ('山田太郎', (select user_password from user_password where id='1' limit 0,1)) -- おわり','aaa@co.jp')
  1. カラム:name → 画面から入力された「山田太郎」が登録されます。
  2. カラム:mail_address→ 「select user_password from user_password where id='1' limit 0,1」という文字列が入っています。この文字列は、ユーザーパスワードTBL(user_password)から「id = 1」の条件と一致する「user_password」を取得するサブクエリです。
  3. その結果、カラム:mail_address→ 「password」が登録されます
  4. そして、INSERT文の最後にある「-- おわり','aaa@co.jp')」という文字列。これは「-- 」から後ろはコメントアウトという意味です。

結果、実際に実行されたINSERT文(コメントアウト部分を除く)は、以下と同じです。

INSERT INTO users (name,mail_address) VALUES ('山田太郎', (select user_password from user_password where id='1' limit 0,1))

そして、登録内容を閲覧する画面で登録データを見ると、メールアドレスの所に「password」が表示され、他人の個人情報を奪い取る事に成功しています。

サブクエリを使えば、簡単に他のテーブルからデータを取得することが出来るんですね・・・。
SQLインジェクション
【SQLインジェクション】INSERT文への攻撃例

続きを見る

[攻撃例3] セミコロンでSQL文を不正操作

SQLインジェクションの攻撃例改ざん

商品の検索画面などの入力フォームです。今回は「商品名」で検索する画面があるとします。

そして「商品名」を完全一致で検索するSQL文を使用します。

SELECT * FROM item_info WHERE item_name = '入力された商品名';

ここで商品名に以下を入力して検索します。

'; DELETE FROM item_info WHERE 'A' = 'A

SELECT文に画面から入力された「商品名」を当てはめると、以下のようなSQL文が作られます。

SELECT * FROM item_info WHERE item_id = ''; DELETE FROM item_info WHERE 'A' = 'A'

これで「SELECT * FROM item_info WHERE item_id = ''」と「DELETE FROM item_info WHERE 'A' = 'A'」の2つのSQL文が作られました。

なぜなら、セミコロン「;」を使うことで、SQLを複数のSQL文を連結できるからです。

結果、「item_info」テーブルの全データが削除されてしまいました

このようにセミコロン「;」を使うことで、データベースのデータを「改ざん」することが出来ます。

スポンサーリンク

SQLインジェクションの被害事例

発生年内容
2011年ソニーグループに対する「SQLインジェクション」による攻撃が発覚し、個人情報が流出した可能性があることを発表。流出した個人情報は氏名、住所、Eメールアドレス、生年月日、PlayStation®Network/Qriocity™パスワード、PlayStation®NetworkオンラインID。
2016年日販アイ・ピー・エスのウェブサーバが「SQLインジェクション」による攻撃を受け、同社が運営する「CLUB JAPAN」「MagDeli」で最大13万1936件分の顧客情報が流出。流出情報の大半は会員のメールアドレスやIDだが、約30件のクレジットカード情報も同時に流出した可能性があることを発表。
2019年株式会社釣りビジョンがSQLインジェクション」による攻撃を受け個人情報が流出した疑いがあることを発表。流出した情報は「メールアドレス:5万1,345人」「メールアドレス、氏名:7,629人」「メールアドレス、氏名、住所:4,682人」
個人情報を狙った攻撃が多いですね。
そうだね。個人情報の流出を防ぐためにも「SQLインジェクション対策」は非常に重要なんだ。

SQLインジェクションの対策方法

スポンサーリンク

[対策1] SQL文の組み立ては「プレースホルダ」で実装する

SQLインジェクションの一般的な対策方法は、「プレースホルダ」を使いSQL文を組み立てることです。

プレースホルダによる組み立てとは、パラメータ部分を「?」などの記号で示しておき、後から実際の値を機械的な処理で割り当てる方法です。

以下は、Java における「プレースホルダ」の例です。

ps = conn.prepareStatement("INSERT INTO users (name,address) VALUES (?,?)");
ps.setString(1, name);
ps.setString(2, address);

パラメータを「プレースホルダ」で指定することで、入力された文字列は「ただの文字列」と判断され、SQLインジェクションによる攻撃を防げます。

[対策2] エスケープ処理を行う

SQL 文を構成する要素には、キーワード、演算子、識別子、リテラルなどがあります。

要素
キーワード(予約語)SELECT FROM WHERE AND
演算子など= >= ,
識別子a b c atable name age
リテラル'入力値' 10

SQL 文の組み立てを文字列連結により行う場合は、リテラル内で特別な意味を持つ記号文字をエスケープ処理します。(たとえば、「'」→「''」、「\」→「\\」等)

特殊な意味を持つ記号文字をエスケープすることで、SQLインジェクションによる攻撃を防げます。

[対策3] WAF(Web Application Firewall)の導入

WAF(Web Application Firewall)とは、Webアプリケーションの脆弱性を突いた攻撃からWebアプリケーションを保護するセキュリティ対策の一つです。

このWAFを利用するのも、有効なSQLインジェクション対策です。

helpful