AppGoatを利用した集合教育補助資料-SQLインジェクション編-

独立行政法人情報処理推進機構 (IPA)
セキュリティセンター

Copyright © 2019 独立行政法人情報処理推進機構

内容(演習１)⚫脆弱性の原理解説・基礎知識⚫脆弱性の発見方法⚫演習１：不正なログイン（文字列リテラル）⚫演習解説

Copyright © 2019 独立行政法人情報処理推進機構

2

SQLインジェクションとは？
⚫ SQLとは、データベースを操作する為の問合せ言語⚫ SQL Injection = SQLの注入⚫ すなわち、SQLインジェクションとは、外部から意図しないSQLを注入し、不正にデータベースを操作する攻撃⚫ ウェブアプリケーションで、最も狙われ易い脆弱性の一つ

Copyright © 2019 独立行政法人情報処理推進機構

3

SQLの基礎知識１-1⚫ SQLの基本形
特定のテーブルから情報を取り出す場合

SELECT [A] FROM [B] WHERE [C][B] (テーブル)から [C] の条件で [A] (列の値)を取り出す
例

SELECT id FROM employee WHERE employee_name = ‘john’employee テーブルからemployee_name = ‘john’ となる条件でid 列の値を取り出す
employee テーブル

idemployee_name100

hanako101

johnCopyright © 2019 独立行政法人情報処理推進機構

101
4

SQLの基礎知識１-2⚫ リテラル(定数)SQL文中で使用される定数をリテラルと呼び、文字列型、数値型、日付型などがある
文字列型

SELECT id FROM employee WHERE employee_name = ‘john’
数値型

日付型

SELECT name FROM employee WHERE age >= 25

hire_date >= ‘2014/12/01’⚫ クォート(‘)
SQLにおいて、データの区切り文字として使われる特殊な意味を持つ記号。
シングルクォートを使い、文字列リテラルの範囲を示す。２つ（始まり・終わり）で一組。
文字列リテラルの始まり

終わり

SELECT id FROM employee WHERE employee_name = ‘john’

スペース‘john Smith’⚫ コメント(--)
SQLにおいて、-- 以降は、命令文ではなくコメントとして扱う。 SQL文として無効となる
SELECT id FROM employee -- WHERE employee_name = ‘ john’
Copyright © 2019 独立行政法人情報処理推進機構

5

SQLを使った認証判定の例（通常時）⚫ ログインページでの認証判定では、SQLが使われることが多い。
認証判定SQL：SELECT * FROM user WHERE id= ‘user テーブルで id がID

ID

で pass が’ AND pass=‘PASS

PASS'

な行が1つ以上あれば認証可、0なら認証不可例）
id=hanako
pass=test
id=hanako

iduser テーブル
passhanakotest

yamadaP@ssword

sato

sato

pass=123
Copyright © 2019 独立行政法人情報処理推進機構

6

SQLを使った認証判定の例（攻撃時）⚫ 攻撃者は‘(シングルクォート)と--(コメント)を使って攻撃認証判定SQL：SELECT * FROM user WHERE id= ‘

ID’ AND pass=‘PASS'

id=hanako’-コメント

pass=123
SELECT * FROM user WHERE id= ‘ hanako’'‘'--

user テーブルで id が hanako で pass が’ AND pass=‘ 123’
123

な行が1つ以上あれば認証可、0なら認証不可
iduser テーブル
passhanako

test

yamadaP@sswordsato
sato
パスワードを知らなくてもログインされてしまう
Copyright © 2019 独立行政法人情報処理推進機構

7

SQLインジェクションを発見するために⚫STEP1：脆弱性が存在する箇所を発見するURLパラメータ

Input フィールド「‘」 (シングルクォート1つ)○○ウェブサイト‘Copyright © 2019 独立行政法人情報処理推進機構

検索

ウェブサイト内の入力項目に、検出パターンを入力して送信する。
（この例の場合、検索フォームに「'」と入力して検索ボタンを押す）
8

SQLインジェクションを発見するために【正常】○○ウェブサイト【脆弱性あり】
データベースエラーが発生しました！

■ 「‘」の検索結果は 3 件です・xxxxxxxx
・xxxxxxxx xx xxxxxx
・xxxxxxxxxx xx xxxx xx

機能が正常に稼働して データベース関連のエラいれば、正常と判定。 ーが発生していれば、脆弱性ありと判定。
Copyright © 2019 独立行政法人情報処理推進機構

9

SQLインジェクションを発見するためになぜデータベースエラーが起きるのかデータベースエラーが発生しました！
SELECT * FROM kensaku WHERE input = ‘ keyword ’ ;keywordに「’」を入れるとSELECT * FROM kensaku WHERE input = ‘’‘ ;‘ ’ ‘

始まりCopyright © 2019 独立行政法人情報処理推進機構

終わり

余り
10

[演習]AppGoatの準備①AppGoatを起動します②以下の遷移で演習画面に移動します１.「実習環境へ」クリック

３.「不正なログイン（文字列リテラル）」クリック

４.「演習(発見)」クリック

2.「はい」クリック
Copyright © 2019 独立行政法人情報処理推進機構

11

[演習]AppGoatを用いた疑似攻撃体験⚫演習テーマ：「不正なログイン（文字列リテラル）」⚫ミッション：
パスワード認証回避に挑戦!

Copyright © 2019 独立行政法人情報処理推進機構

12

[演習]演習の進め方
Step1：脆弱となる箇所を特定する
・ログイン画面の入力フィールドに様々な値を入力して、動作を確認する。

検査文字列の入力

Step2：脆弱性を突く攻撃を考える
・ 「前提条件」を参考に、認証を回避するようなSQL文を考える。

Step3:認証を回避してログインしてみる。
ログインID「yamada」でログインしてみましょう
Copyright © 2019 独立行政法人情報処理推進機構

13

演習

演習はじめてください。
※演習が終わったら次のページで解説を行います。

Copyright © 2019 独立行政法人情報処理推進機構

14

[Step1]
ログイン画面の入力フィールドに様々な値を入力する
演習の手順

SQL文のエラーを起こす値を入力して、脆弱な箇所を発見してみましょう⚫ 入力フィールドにシングルクォート「‘」を入力し、ログインしてみましょう。
⚫ その結果、下記のようなSQL文が作成され、構文エラーが起きたことが推測できます。

‘ ’ ‘

始まり

終わり

余り

SELECT * FROM user WHERE id = ‘’‘ AND password = ‘test’;Copyright © 2019 独立行政法人情報処理推進機構

15

[演習]演習の進め方
Step1：脆弱となる箇所を特定する
・ログイン画面の入力フィールドに様々な値を入力して、動作を確認する。

検査文字列の入力

Step2：脆弱性を突く攻撃を考える
・ 「前提条件」を参考に、認証を回避するようなSQL文を考える。

Step3:認証を回避してログインしてみる。
・Step2で考えたSQL文が成立する様に入力フィールドに値を入力する。
ログインID「yamada」でログインしてみましょう
Copyright © 2019 独立行政法人情報処理推進機構

16

[Step2]
認証を回避するようなSQL文を考える
演習の手順

SQL文のパスワード認証部分の条件式を書き換えましょう⚫ 論理演算子（OR）と（'）を使って条件式を書き換える
SELECT * FROM user WHERE id = ‘yamada’ AND password = ‘A’ OR ‘A’=‘A’--;
常に正しい条件⚫ [参考] (‘)と コメント（--）を使って条件式を書き換える
id= yamada‘ -pass=a
SELECT * FROM user WHERE id = ‘yamada' -- ' AND password = 'a';
SQL文として無効となる
Copyright © 2019 独立行政法人情報処理推進機構

17

[Step3]
攻撃により、手順2のSQL文を発行させる
演習の手順

ログインID「yamada」で認証を回避してログインしてみましょう

1. 攻撃者がオンラインバンキングのログインフォームのID欄に「yamada」を入力、パスワード欄に「' OR 'A'='A' --」を入力しログインを試みます。
' OR 'A'='A' --2. その結果、攻撃者が山田さんとしてログインできてしまいます。

Copyright © 2019 独立行政法人情報処理推進機構

18

内容(演習2)⚫脆弱性の原理解説・基礎知識⚫演習2：情報漏えい（数値リテラル）⚫演習解説

Copyright © 2019 独立行政法人情報処理推進機構

19

SQLの基礎知識２⚫ 論理演算子(AND、OR)
SQL文中のWHERE句で複数の条件を指定する演算子

年齢が25歳以上”かつ”所属が総務SELECT id FROM employee WHERE age >= 25 AND unit = ‘soumu’
SELECT id FROM employee WHERE age >= 25 AND unit = ‘soumu’ OR unit=‘keiri’
年齢が25歳以上 ”かつ” 所属が総務 ”または” 所属が経理先にANDを判定し、ORが次になる⚫ Where 句の特殊な使われ方
常に正になる条件式：条件式が同じリテラル値同士で成立している条件式
SELECT id FROM employee WHERE ‘john’ = ‘john’
常に正になるため、条件式の意味がない
SELECT id FROM employeeCopyright © 2019 独立行政法人情報処理推進機構

20

SQLを使ったデータ抽出（通常時）⚫ 特定ユーザの情報を取り出すページではSQLが使われることが多い。（例：成績確認、残高照会 等）
認証判定SQL：SELECT * FROM seiseki WHERE sid= ‘ ID

seiseki テーブルで sid がIDな行を出力例）
seiseki テーブルsidkamoku tokuten

100

English60

100

Math80200

Math40300

Math100

Copyright © 2019 独立行政法人情報処理推進機構

sid=100sid

kamoku tokuten

100

English60

100

Math80sid=400

出力なし(0件)
21

SQLを使ったデータ抽出（攻撃時）⚫ 攻撃者は OR 演算子を使って攻撃をしてくる
認証判定SQL：SELECT * FROM seiseki WHERE sid= ‘ ID

sid=400 OR 1=1
SELECT * FROM seiseki WHERE sid= ‘400 OR 1=1

seiseki テーブルで sid が400

またはヒット 0件

1=1な行を出力

sid

kamoku tokutensid

常に正しい（ヒット 全件）
SELECT * FROM seiseki
kamoku tokuten

100

English60

100

English60

100

Math80100

Math80200

Math40200Math

40300

Math

100300

Math100

seiseki テーブルsid の値に関わらず、すべての情報が出力される
Copyright © 2019 独立行政法人情報処理推進機構

22

[演習]AppGoatの準備①以下の遷移で演習画面に移動します

3.IDに「sato」、パスワードに「sato123」と入力しログイン

１.「情報漏えい（数値リテラル）」クリック

Copyright © 2019 独立行政法人情報処理推進機構

２.「演習」クリック

23

[演習]AppGoatを用いた疑似攻撃体験⚫演習テーマ：「情報漏えい（数値リテラル）」⚫ミッション：
全ユーザの口座残高を閲覧

Copyright © 2019 独立行政法人情報処理推進機構

24

[演習]演習の進め方
Step1：脆弱となる箇所を特定する・SQL文のエラーを起こす値を入力して、脆弱な箇所を発見してみましょう--

Step2：前提条件を参考に脆弱性を突く攻撃を考える
・論理演算子 OR を使用してWHERE句を常に正しくなる条件にしましょう

Step3:SQL文を発行し、他人の口座残高情報を取得する・ログインユーザ以外の口座残高情報が取得できるか確認しましょう。
Copyright © 2019 独立行政法人情報処理推進機構

25

演習

演習はじめてください。
※演習が終わったら次のページで解説を行います。

Copyright © 2019 独立行政法人情報処理推進機構

26

[Step1]
URLパラメータに様々な値を入力して、動作を確認する
演習の手順

SQL文のエラーを起こす値を入力して、脆弱な箇所を発見してみましょう⚫ URLパラメータ（ account_id ）に ‘ や test という文字列を入力し、アクセスしてみましょう。
① account_id ：‘② account_id ：test→ エラーが発生→ エラーが発生

account_id にSQLインジェクションの脆弱性が存在する可能性⚫ その結果、下記のようなSQL文が作成され、構文エラーが発生することが推測できます。

SELECT * FROM account WHERE id = ‘sato’ AND account_id = ‘;
SELECT * FROM account WHERE id = ‘sato’ AND account_id = test ;Copyright © 2019 独立行政法人情報処理推進機構

27

[演習]演習の進め方
Step1：脆弱となる箇所を特定する・SQL文のエラーを起こす値を入力して、脆弱な箇所を発見してみましょう

Step2：前提条件を参考に脆弱性を突く攻撃を考える
・論理演算子 OR を使用してWHERE句を常に正しくなる条件にしましょう

Step3:SQL文を発行し、他人の口座残高情報を取得する
・すべてのログインユーザの口座残高情報が取得できるか確認しましょう。
Copyright © 2019 独立行政法人情報処理推進機構

28

[Step2]
他人の口座残高情報を参照するSQL文を考える
演習の手順

論理演算子 OR を使用してWHERE句が常に正しくなる条件にしましょう⚫ 論理演算子（OR）を使って条件式を書き換える
99 OR 1=1
SELECT * FROM account WHERE id = ‘sato’ AND account_id = 99 OR 1=1;

SELECT * FROM account ;Copyright © 2019 独立行政法人情報処理推進機構

29

[手順3]
脆弱性を突いてみる
演習の手順

ログインユーザ以外の口座残高情報が取得できるか確認しましょう

1. 攻撃者がオンラインバンキングの口座照会ページのURLのaccount_idパラメータに「99 OR 1=1」の文字列を入力し、アクセスを試みます。

2. その結果、攻撃者が全ユーザの口座情報を盗み見ることができることを確認します。

Copyright © 2019 独立行政法人情報処理推進機構

30

内容(演習3)⚫演習3：演習3(グループウェア)
⚫演習解説
⚫対策方法

Copyright © 2019 独立行政法人情報処理推進機構

31

[演習]AppGoatの準備①以下の遷移で演習画面に移動します

１.「演習3(グループウェア)」をクリック

2.IDに「yamada」、パスワードに「yamada123」と入力しログイン

3.「スケジュール管理」をクリック

Copyright © 2019 独立行政法人情報処理推進機構

32

[演習]AppGoatを用いた疑似攻撃体験⚫演習テーマ：「演習3(グループウェア)」⚫ミッション：
全ユーザのスケジュールを閲覧

Copyright © 2019 独立行政法人情報処理推進機構

33

[演習]演習の進め方
Step1：脆弱となる箇所を特定する・SQL文のエラーを起こす値を入力して、脆弱な箇所を発見してみましょう-Step2：前提条件を参考に脆弱性を突く攻撃を考える
SELECT * FROM schedule WHERE id = ‘ログインID’ AND date = ’日付’

Step3:SQL文を発行し、他人のスケジュールを取得する・ログインユーザ以外のスケジュールが取得できるか確認しましょう。
Copyright © 2019 独立行政法人情報処理推進機構

34

演習

演習はじめてください。
※演習が終わったら次のページで解説を行います。

Copyright © 2019 独立行政法人情報処理推進機構

35

[Step1]
URLパラメータに様々な値を入力して、動作を確認する
演習の手順

SQL文のエラーを起こす値を入力して、脆弱な箇所を発見してみましょう⚫ URLパラメータ（ date ）に ‘ という文字列を入力し、アクセスしてみましょう。
date =‘→ エラーが発生

date にSQLインジェクションの脆弱性が存在する可能性⚫ その結果、下記のようなSQL文が作成され、構文エラーが発生することが推測できます。

SELECT * FROM schedule WHERE id = ‘yamada’ AND date = ‘’‘ ;Copyright © 2019 独立行政法人情報処理推進機構

36

[Step2]
他人のスケジュールを参照するSQL文を考える演習の手順

論理演算子 OR を使用してWHERE句が常に正しくなる条件にしましょう
SELECT * FROM schedule WHERE id = ‘ログインID’ AND date = ‘日付’

⚫ 論理演算子（OR）を使って条件式を書き換える
SELECT * FROM schedule WHERE id = ‘ログインID’ AND date = ‘日付
2017/09/03’
OR ‘a’=‘a’

SELECT * FROM schedule WHERE id = ‘yamada’ AND date = ‘2017/09/03’ OR ‘a’=‘a’;

SELECT * FROM schedule ;Copyright © 2019 独立行政法人情報処理推進機構

37

[手順3]
脆弱性を突いてみる
演習の手順

ログインユーザ以外のスケジュールが取得できるか確認しましょう

1. 攻撃者がグループウェアのスケジュールページのURLのdateパラ
メータに「2017/09/03’ OR ‘a’=‘a」の文字列を入力し、アクセスを試みます。
2017/09/03

2. その結果、攻撃者が全ユーザのスケジュールを盗み見ることができることを確認します。

Copyright © 2019 独立行政法人情報処理推進機構

38

対策方法

対策方法

Copyright © 2019 独立行政法人情報処理推進機構

39

SQLインジェクションを引起す実装⚫ SQL文の組立てに問題がある実装

SELECT
SELECT* *FROMFROMuser
userWHERE
WHERE
id=' AND
pass=‘ 123’
id=‘ ‘hanako’ -' ANDpass=''id=hanako‘ -pass=123
悪意がある人user
ウェブサーバ＋

データベース

ウェブアプリ

不正なリクエストによって、発行するSQL文の構文を書き換えられないように処理する
Copyright © 2019 独立行政法人情報処理推進機構

40

SQLインジェクション脆弱性の対策⚫根本的解決 「意図しないSQL文の発行を防止する実装」
SQL文の組立ては全てプレースホルダで実装する
エスケープ処理を利用する(対策の抜け漏れを起こしやすいので注意)⚫保険的対策「攻撃を抑制、または被害を軽減する対策」
詳細なエラーメッセージの抑止
データベースアカウントの権限見直し

テーブル
Copyright © 2019 独立行政法人情報処理推進機構

テーブル

41

根本的解決～プレースホルダを利用した対策例～⚫ SQL文の組立てはプレースホルダで実装する
プレースホルダは、先にSQL文の構文を確定させ、後からパラメータの値を機械的な処理で割り当てる方式
プレースホルダ

準備されたSQL文SELECT ＊ FROM employee WHERE id= ‘?’ AND password= ‘?’;構文確定後に値を割当てる

パラメータ

パラメータabc

yamada‘ --実行されるSQL文SELECT ＊ FROM employee WHERE id=‘yamada‘ --’ AND password=‘ abc ’;
文字列としか取扱われない細工されたパラメータ値による、構文の書き換えを防止
Copyright © 2019 独立行政法人情報処理推進機構

42以上で、SQLインジェクションの解説は終了です。

Copyright © 2019 独立行政法人情報処理推進機構

43