データベースの不正操作対策(1)

サイバーセキュリティ演習
― Webセキュリティ基礎&実践―
6. データベースの不正操作対策
講義内容
1. 2*. Webサイトの仕組みとWebプログラミング基礎
3.4.5*. 不正スクリプトの実行対策
6.7*.
データベースの不正操作対策
8 *.
システムの不正操作対策とHTTPレスポンスの改竄対策
9 *.
偽リクエストによるサービスの不正利用対策
10*.
セッションIDの
不正取得対策
11.
総合演習(1)
12*.
公開ディレクトリの不正横断対策と認証認可制御の欠落
による不正アクセス対策とエラーメッセージからの情報
漏えい対策
13.
総合演習(2)
14.
総合演習(3)
15.
学期末試験
※*はレポートがある回になります。
本日の内容
 SQLインジェクションの脆弱性攻撃体験と
脆弱性の修正
 不正なログイン(文字列リテラル)
 情報漏えい(数値リテラル)
SQLとは
 SQLは、リレーショナルデータベース管理システム
(RDBMS) において、データの操作や定義を行うた
めのデータベース言語(問い合わせ言語)である。
 RDBMSは、リレーショナルデータベースを管理す
るためのソフトウェア。
 Oracle、Access、
 MySQL、PostgreSQL、
 SQLite
(Wikipediaより)
等
リレーショナルデータベース管
理システム(RDBMS)
 データを表に似た構造で管理するデータベース。複
数のデータ群が関係と呼ばれる構造で相互連結可能
userテーブル
ログインID
ユーザ名
パスワード
(id:文字列) (name:文字列) (password:文字列)
yamada
Yamada Taro
P@ssword
suzuki
Suzuki Jiro
3f858c
accountテーブル
関係を持っ
た複数の
テーブルに
分けて管理
ログインID
口座番号
残高
(id:文字列) (account_id:数値) (balance:数値)
yamada
1000001
100,000
yamada
1000002
200,000
suzuki
1000003
300,000
RDBMSのイメージとデータ
ベースの用語
RDBMS
検索機能
追加削除機能
抽出機能
データベース
テーブル2
accountテーブル
テーブル1
userテーブル
レコード
(行)
カラム(列)
SQLの種類
 データ定義言語
 カラムやレコードなどリレーショナルデータ
ベースの構造を定義する言語
 データ操作言語
 データの検索やデータの挿入などリレーショナ
ルデータベースに対する操作を定義する言語
 データ制御言語
 データの操作に対する権限の付与やはく奪など
アクセス制御を行うために定義する言語
データ定義言語
 CREATE
 データベース、テーブルやカラム、レコードな
どを作成する
 DROP
 データベース、テーブルやカラム、レコードな
どを削除する
 ALTER
 既に存在するデータベース、テーブルやカラム、
レコードなどを変更する
 TRUNCATE
 テーブルからレコードを削除する
データ操作言語
 SELECT
 テーブルからデータを検索する
 INSERT
 レコードを追加する
 UPDATE
 レコードを更新する
 DELETE
 レコードを削除する
データ制御言語
 GRANT
 利用者に特定の作業の権限を与える
 REVOKE
 利用者に与えた特定の作業の権限をはく奪する
SQLの基礎1
 データを検索する場合、
SELECT カラム1、カラム2 FROM テーブル名
[WHERE <条件>];
 SELECT * FROM user WHERE id=‘yamada’;
 SELECT *:すべてのカラムを検索する
 FROM user:userテーブルから
 WHERE id=‘yamada’:id=yamadaに一致する
レコードの
例えば、以下のテーブルがあっ
た場合の検索結果は?
SELECT * FROM user WHERE id=‘yamada’;
userテーブル
ログインID
(id:文字列)
ユーザ名
(name:文字列)
パスワード
(password:文字列)
yamada
Yamada Taro
P@ssword
suzuki
Suzuki Jiro
3f858c
accountテーブル
ログインID
口座番号
残高
(id:文字列) (account_id:数値) (balance:数値)
yamada
1000001
100,000
yamada
1000002
200,000
suzuki
1000003
300,000
SQLの基礎2
 リテラル(直定数)
 プログラミングなどで、データ型に直接定めた値のこと。
 文字列リテラルは、データ型に直接定めた文字列のこと
以下の例では、yamadaが文字列リテラルとなる
SELECT * FROM user WHERE id = 'yamada';
 数値リテラルは、データ型に直接定めた数値のこと
以下の例では、200000が数値リテラルとなる
SELECT * FROM account WHERE balance >= 200000;
SQLの基礎3
 シングルクォート(’)
 SQLでは、データの区切り文字として使う。
シングルクォートで囲むことで文字列リテラルを定義
する
数値リテラルの定義の場合は不要
 コメント(--)
 SQLでは、2連続のハイフン(--)以降は、コメン
トとして扱う
SQLインジェクションとは
 悪意のあるSQLを注入(インジェクショ
ン)し、Webアプリケーションが意図しな
いSQL文を実行してしまうことで、データ
ベースを不正に操作されてしまう脆弱性
SQLインジェクションの種類
 文字列リテラルに対するSQLインジェクション
 SQL文の文字列要素に、SQL文の一部やSQLコメント
を入力することで、データベースへ不正な操作が行わ
れる。
 数値リテラルに対するSQLインジェクション
 SQL文の数値要素に、SQL文の一部や悪意のあるSQL
文を入力することで、データベースへ不正な操作が行
われる。
演習テーマ
SQLインジェクション
 「不正なログイン(文字列リテラル)」のリンクをク
リックしましょう。
文字列リテラルに対するSQLイ
ンジェクションの原理
 ユーザからの入力値をそのまま文字列リテラルに連結して
SQL文を組み立てることにより、意図しないSQL文を実行さ
れ、データベースを不正に操作されてしまう
一般的なSQL文の組み立て処理
のやり方
 指定したidの個人情報をuserテーブルから取得するSQL文を
ユーザからの入力値(yamada)を利用して文字列連結によ
り組み立てる
入力値に「' OR 'A'='A' --」と
いう文字列を与えると
 Where句の条件がTRUE(真)となります。
 その結果、userテーブルの全てのレコードが取得されます。
SQLを使った認証判定
 ログインページの認証判定でSQLはよく使われる。
 WHERE句の条件にあてはまるならば認証OK
 WHERE句の条件にあてはまらないならば認証NG
○:SELECT * FROM user WHERE id=‘yamada’ AND
password=‘P@ssword’
×:SELECT * FROM user WHERE id=‘suzuki’ AND
password=‘12345678’
userテーブル
ログインID
(id:文字列)
ユーザ名
(name:文字列)
パスワード
(password:文字列)
yamada
Yamada Taro
P@ssword
suzuki
Suzuki Jiro
3f858c
文字列リテラルを用いたSQLイ
ンジェクションの攻撃手口
 WHERE句の条件が必ずTRUE(真)になるように内容
を変更する
 シングルクォート(’)とコメント(- -)が使われること
が多い
 SELECT * FROM user WHERE id = ‘yamada’ AND
password = ‘ ‘ OR ‘A’=’A’ -- ';
最初のシングルクォート(‘)でpasswordの入力を終端する
OR演算子を使って別の条件を提示する
‘A’=’A’によって条件を必ずTRUE(真)とする
コメント (--)で最後のシングルクォートを無効にする
ID入力部分のSQLインジェク
ションの攻撃手口
 IDの入力部分にSQLインジェクションの脆弱性があった
場合、攻撃者はパスワードを知らなくてもログインが可
能になることがあります。
 SELECT * FROM user WHERE id = ‘ yamada ‘ - AND password = ‘P@ssword';
'
攻撃者が入力した文字列リテラル:yamada ‘ - コメントになる部分: ’ AND password = ‘P@ssword';
 適当なパスワードでyamadaのページにログインできる
演習内容(疑似的な攻撃)
 オンラインバンキングの文字列リテラルに不正な文字列
を入力し、不正にログインする
 脆弱性があるウェブサイト
 オンラインバンキング
演習の進め方
1. Webサイトの挙動を把握する
2. 脆弱性となる箇所を特定する
3. 不正ログイン用の文字列リテラルを考える
4. 不正にログインする
1.Webサイトの挙動を把握
する
 オンラインバンクの入力
フィールドに様々な値を
入力して動作を確認する。
 攻撃者として、利用でき
ることを考える。
 SQL文のエラーを起こす
値を入力して、脆弱な個
所を発見しましょう。
2.脆弱性となる箇所を特定す
る
 文字列リテラルを終端を狙い、Webサイトの入力項目
にシングルクォート(’)を入力してみる
 正常(ログインエラー)
 脆弱性あり(データベースエ
ラー)
構文エラーが出た
ということは、入
力値を含んだSQL
文が作成され、
データベースに問
い合わせされたと
推測できる
なぜデータベースエラーが起き
るのか
 正常なSQL文
 SELECT * FROM user WHERE id = ‘yamada ’ AND
password = ‘P@ssword’;
 エラーとなるSQL文
 SELECT * FROM user WHERE id = ‘’ ‘ AND password =
‘P@ssword’;
 SELECT * FROM user WHERE id = ‘yamada ’ AND
password = ‘’ ’;
 シングルクォートの余りがあるため構文エラーとなる。
3.不正ログイン用の文字列リ
テラルを考える
 ユーザ認証処理では、次のSQL文が使用されていま
す。
 SELECT * FROM user WHERE id = ‘yamada' AND
password = 'パスワード';
 論理演算子 OR を使用してWHERE句が常に正しく
なる条件にしましょう
 パスワードの条件が常に「真」となる文字リテラル
を考えましょう。
SELECT * FROM user WHERE id = ‘yamada'
AND password = ‘OR ‘A’=’A’ --';
4.不正にログインする
 考えたパスワードを使ってログインができるか確認
しましょう。
 ログインIDは「yamada」を使いましょう
 パスワードは「' OR 'A'='A' --」
 以下のログインIDを使った場合でもログインができ
るか確認しましょう。
 ログインIDは「yamada ‘ --」
 パスワードは、適当。
4.不正にログインする
 「Congratulations!!演習の目標を達成しまし
た。」と表示されたら、OKです。
SQLインジェクションの一般的
な影響
 データベースに蓄積された非公開情報を閲覧される
 個人情報や機密情報などが漏えいする可能性がある
 データベースに蓄積された情報を改ざん、消去される
 ウェブページが改ざんされたり、パスワードが変更されてし
まったり、システムが停止するといった被害が発生する可能性
がある。
 認証回避により不正にログインされる
 ログインしたユーザに許可されている全ての操作が可能となり、
不正な行為が行われる可能性がある。
 ストアドプロシージャなどを利用してOS コマンドを実行さ
れる
 システムの乗っ取りや、他への攻撃の踏み台として悪用される
可能性がある。
対処方法
 原因
 外部から入力できるパラメータをそのまま文字列連結
してSQL文を組み立てるため、WHERE句の条件が常に
真となるリテラルの注入によりSQL文が変更されてし
まい、そのままSQLの処理が実行される
 対処方法
 文字列リテラルの入力値を文字そのものとして解釈さ
せるために、SQL文の組み立ては全てプレースホルダ
を使いプリペアステートメントで実装する。
プレースホルダ
 SQL文のリテラル部分に後から正式な値を挿入するために一
時的に場所として確保しておく値
 SQL文の事前に確定させておく方法をプリペアドステートメン
トと言う。
 実際の値を挿入することをバインド処理という
 静的プレースホルダと動的プレースホルダがある
 プレースホルダなし
 SELECT * FROM user WHERE id = ‘yamada' AND password
= ‘P@ssword';
 プレースホルダあり
 SELECT * FROM user WHERE id = ? AND password = ?;
バインド処理後は普通の
文字列として扱われる
yamada
P@ssword
静的&動的プレースホルダ
 静的プレースホルダ
 バインド処理をデータベース側で実行する方式
 PHPからプレースホルダのついたSQL文をデータベース側
にあらかじめ送信してSQL文を確定させておく
 SQL実行段階で、PHPから実際の値をデータベースに送り、
データベースがバインド処理をしてからSQL文を実行する
 動的プレースホルダ
 バインド処理をWebアプリケーション側で実行する方式
 PHPがバインド処理したSQL文をデータベースに送り、
データベースがそのSQL文を実行する
 動的プレースホルダの不適切な実装は脆弱性となるため、
可能な限り静的プレースホルダを利用しましょう
プリペアドステートメントの実装
 PDO(PHP Data Object)
 1つの関数で複数のデータベースアクセスを可能にす
る抽象化クラス
 2005年11月にリリースされたPHP5.1.0から実装された
 PDOが実装されるまでは、データベースの種類ごとに
関数を分けていた
 プリペアドステートメントの実装手順
 PDOの利用を宣言:PDO()
 例外処理を施す: try{}catch{}
 SQL文を準備する:prepare()
 SQLを実行する:execute()
プレースホルダを使わないプリ
ペアドステートメントの例
<?php
データベース接続
try {
例外処理
$db = new PDO($dbsrv, $dbusr, $dbpwd);
$stmt = $db->prepare("SELECT * FROM user WHERE id = $id
AND password = $pwd”);
$stmt->execute();
} catch (PDOException $e) {
}
?>
SQLを準備
実行
以下は既に宣言済みとする。
print(“Error:”.$e->getMessage()); $dbsrv=‘mysql:host=example.jp;
dbname=exampleDB’;
$dbusr=‘root’;
例外発生時の
$dbpwd=‘csr2015’;
エラー表示
$id=‘yamada’;
$pwd=‘P@ssword’
プレースホルダを使ったプリペ
アドステートメントの例
<?php
try {
$db = new PDO($dbsrv, $dbusr, $dbpwd);
疑問符プレースホルダ
を記述
$stmt = $db->prepare("SELECT * FROM user WHERE id = ?
AND password = ?”);
$stmt->execute(array($id,$pwd));
} catch (PDOException $e) {
print(“Error:”.$e->getMessage());
}
?>
プレースホルダに代
入する値をexecute
関数に配列で渡す
演習内容(脆弱性の修正)
 オンラインバンキングの文字列リテラルを用いたSQLイ
ンジェクションの脆弱性となるコードを特定し、プレー
スホルダの実装を行う
 演習では、脆弱性のあるWebアプリケーションとデータ
ベースサーバが同一ホスト上にあるため、結果として動
的プレースホルダの実装で演習を進めることになります。
修正プログラム
 オンラインバンキング
 bank.php
bank108.class.phpの処理内容をゲット
メッセージ割り当て
テンプレート表示
 bank108.class.php
データベースのデータの初期設定
テーブルからの情報取得の成功判定
ログイン処理
脆弱性の修正の手順
 bank108.class.php
1. ログイン処理の内容の確認。
2. プレースホルダを使用する箇所の特定。
3. プレースホルダを使ったプリペアドステートメントの
実装。
1.ログイン処理の内容の確認
public function login()
データベースのアクセス情報を取得
{
$db = $this->get_db();
リテラル(入力値)の情報を取得
$param = $this->get_param();
try {
$stmt = $db->prepare("SELECT * FROM user WHERE id = '" .
$param["id"] . "' AND password = '" . $param["password"] . "';");
if ($stmt == null) { throw new Exception(); }
$stmt->execute();
プリペアドステートメントを実行
(データベース検索の実行)
} catch (Exception $e) {
throw new Exception((__LINE__ . $db->errorInfo()),
LogUtil::ERROR_DB_EXECUTE);
}
(次ページに続く)
1.ログイン処理の内容の確認
データベース検索結果からユーザ情報を取得
(つづき)
$user = $stmt->fetch();
if ($user) {
検索結果が返ってきたら
攻撃成功判定
$this->is_success($user, $param["id"], $param["password"]);
$this->set_session($this->get_login(), $user);
クライアントとの
$this->set_name();
利用者のページを セッションを確立
return true;
設定
認証成功を
返す
} else {
ログアウト処理を
$this->proc_logout();
$this->set_content(parent::WARNING3, true);
$this->set_content(parent::WARNING4, false);
return false;
}
}
認証失敗を
返す
実行
警告メッセージを
設定
2.プレースホルダを使用する
箇所の特定
try {
$stmt = $db->prepare("SELECT * FROM user WHERE id =
‘" . $param["id"] . "' AND password =
‘" . $param["password"] . "';");
if ($stmt == null) { throw new Exception(); }
$stmt->execute();
} catch (Exception $e) {
throw new Exception((__LINE__ . $db->errorInfo()),
LogUtil::ERROR_DB_EXECUTE);
}
3.プレースホルダを使ったプ
リペアドステートメントの実装
try {
$stmt = $db->prepare("SELECT * FROM user WHERE id = ?
AND password = ?");
if ($stmt == null) { throw new Exception(); }
$stmt->execute(array($param["id"], $param["password"]));
} catch (Exception $e) {
throw new Exception((__LINE__ . $db->errorInfo()),
LogUtil::ERROR_DB_EXECUTE);
}
動作確認
 ログインIDに「yamada」、パスワードに「' OR
'A'='A' --」を入力してログインしてみましょう。
 ログインができなければOKです。
文字列リテラルに対するSQLイ
ンジェクションの要点
 文字列リテラルに対するSQLインジェクションの脆弱性
の原因は、ユーザから受け取った入力値をそのまま文字
連結してSQL文を組み立てていることです。
 意図しないSQL文の実行を防ぐために、プレースホルダ
を用いたプリペアドステートメントによるSQL文の組み
立てを行い、ユーザからの入力値をエスケープ処理する
ようにしましょう。
本日の内容
 SQLインジェクションの脆弱性攻撃体験と
脆弱性の修正
 不正なログイン(文字列リテラル)
 情報漏えい(数値リテラル)
SQLインジェクションの種類
 文字列リテラルに対するSQLインジェクション
 SQL文の文字列要素に、SQL文の一部やSQLコメント
を入力することで、データベースへ不正な操作が行わ
れる。
 数値リテラルに対するSQLインジェクション
 SQL文の数値要素に、SQL文の一部や悪意のあるSQL
文を入力することで、データベースへ不正な操作が行
われる。
演習テーマ
SQLインジェクション
 「情報漏えい(数値リテラル)」のリンクをクリック
しましょう。
数値リテラルに対するSQLイン
ジェクションの原理
 ユーザからの入力値をそのまま数値リテラルに連結してSQL
文を組み立てることにより、意図しないSQL文を実行され、
データベースを不正に操作されてしまう
一般的なSQL文の組み立て処理
のやり方
 指定したaccount_idの口座情報をaccountテーブルから取
得するSQL文をユーザからの入力値(10)を利用して文字列
連結により組み立てる
入力値に「 0 OR 1 = 1 」とい
う文字列を与えると
 Where句の条件がTRUE(真)となります。
 その結果、accountテーブルの全てのレコードが取得されます。
SQLを使った情報取得
 ユーザの情報取得にSQLはよく使われる。
 WHERE句の条件にあてはまるならば結果を出力
 WHERE句の条件にあてはまらないならば出力なし
○:SELECT * FROM user WHERE id=‘yamada’ AND
account_id=1000001
×:SELECT * FROM user WHERE id=‘suzuki’ AND
account_id=9999999
accountテーブル
ログインID
口座番号
残高
(id:文字列) (account_id:数値) (balance:数値)
yamada
1000001
100,000
yamada
1000002
200,000
suzuki
1000003
300,000
数値リテラルを用いたSQLイン
ジェクションの攻撃手口
 WHERE句の条件が必ずTRUE(真)になるように内容
を変更する
 OR演算子が使われることが多い
 SELECT * FROM user WHERE id = ‘yamada’ AND
account_id= 0 OR 1=1
;
account_idには適当な値を指定する
OR演算子を使って別の条件を提示する
1=1によって条件を必ずTRUE(真)とする
演習内容(疑似的な攻撃)
 オンラインバンキングの数値リテラルに不正な文字列を
入力し、口座残高照会ページで全てのユーザの口座残高
を表示させる
 脆弱性があるウェブサイト
 オンラインバンキング
演習の進め方
1. Webサイトの挙動を把握する
2. 脆弱性となる箇所を特定する
3. 全てのユーザの口座残高を表示させる数値リテラ
ルを考える
4. 不正アクセスのURLを作成し実行する
1.Webサイトの挙動を把握
する
 オンラインバンクの口座
残高照会ページの動作を
確認する。
 攻撃者として、利用でき
ることを考える。
 SQL文のエラーを起こす
値を入力して、脆弱な個
所を発見しましょう。
 URLも確認しましょう。
2.脆弱性となる箇所を特定す
る
 数値リテラルの終端を狙い、account_idにシングルクォー
ト(’)を入力してみる
 http://localhost/Web/Scenario109/VulSoft/bank.php?pa
ge=3&account_id=‘;
構文エラーが出た
ということは、入
力値を含んだSQL
文が作成され、
データベースに問
い合わせされたと
推測できる

正常(番号が無ければ表示されない)  脆弱性あり(データベースエラー)
3.全てのユーザの口座残高を表
示させる数値リテラルを考える
 口座残高照会処理では、次のSQL文が使用されてい
ます。
 SELECT * FROM account WHERE id = 'ログインID'
AND account_id = 口座番号;
 論理演算子 OR を使用してWHERE句を常に正しく
なる条件にしましょう
 account_idの条件が常に「真」となる数値リテラル
を考えましょう。
SELECT * FROM account WHERE id =
‘yamada' AND account_id = 1 OR 1=1;
4.不正アクセスのURLを作成
し実行する
 口座残高照会のURLは以下の通りです。
 http://localhost/Web/Scenario109/VulSoft/bank.
php?page=3&account_id=1000001
 考えた数値リテラルを追記したURLを作成しましょ
う。
 http://localhost/Web/Scenario109/VulSoft/bank.
php?page=3&account_id=1 OR 1=1;
4.不正アクセスのURLを作成
し実行する
 ログインユーザ以外の口座残高情報が取得できるか
確認しましょう
 まずは、yamadaのIDでログインしましょう。
ログインIDは「yamada」
パスワードは「P@ssword」
 ログイン後、作成したURLをURL欄に入力しましょう。
4.不正アクセスのURLを作成
し実行する
 「Congratulations!!演習の目標を達成しまし
た。」と表示されたら、OKです。
対処方法
 原因
 外部から入力できるパラメータをそのまま文字列連結
してSQL文を組み立てるため、WHERE句の条件が常に
真となるリテラルの注入によりSQL文が変更されてし
まい、そのままSQLの処理が実行される
 対処方法
 数値リテラルの入力値を値そのものとして解釈させる
ために、SQL文の組み立ては全てプレースホルダを使
いプリペアステートメントで実装する。
演習内容(脆弱性の修正)
 オンラインバンキングの数値リテラルを用いたSQLイン
ジェクションの脆弱性となるコードを特定し、動的プ
レースホルダの実装を行う
 演習では、脆弱性のあるWebアプリケーションとデータ
ベースサーバが同一ホスト上にあるため、結果として動
的プレースホルダの実装で演習を進めることになります。
修正プログラム
 オンラインバンキング
 bank.php
bank109.class.phpの処理内容をゲット
メッセージ割り当て
テンプレート表示
 bank109.class.php
データベースのデータの初期設定
テーブルからの情報取得の成功判定
口座番号の有効性の検証
口座データの取得処理
脆弱性の修正の手順
 bank109.class.php
1. 口座データの取得の内容の確認。
2. プレースホルダを使用する箇所の特定。
3. プレースホルダを使ったプリペアドステートメントの
実装。
1.口座データの取得の内容の
確認
public function proc_inquiry()
{
$param = $this->get_param();
if (isset($param[parent::ACCOUNT_ID])) {
$stmt = null;
$db = $this->get_db();
データベース、セッ
ション、アカウントID
の情報を取得
$session = $this->get_session();
$id = $session[$this->get_login()][parent::USER_ID];
$account_id = $param[parent::ACCOUNT_ID];
(次ページに続く)
(つづき)
1.口座データの取得の内容の
確認
プリペアドステートメ
ントを実行
try {
$stmt = $db->prepare("SELECT * FROM account WHERE id =
'" . $id . "' AND account_id = " . $account_id);
if ($stmt == null) {
throw new Exception();
}
$result1 = $stmt->execute();
} catch (Exception $e) {
throw new Exception((__LINE__ . $db->errorInfo()),
LogUtil::ERROR_DB_EXECUTE);
}
(次ページに続く)
1.口座データの取得の内容の
確認
(つづき)
$balances = array();
while ($row = $stmt->fetch()) {
残高を金額形式(カン
マ区切り)に変換
$row[parent::BALANCE] =
number_format($row[parent::BALANCE]);
$balances[] = $row;
}
金額形式の残高をセッ
トし、攻撃成功判定
$this->set_content(parent::BALANCE, $balances);
$this->is_success($balances);
}
$result2 = $this->set_accounts();
}
2.プレースホルダを使用する
箇所の特定
try {
$stmt = $db->prepare("SELECT * FROM account
WHERE id = '" . $id . "' AND account_id = " . $account_id);
if ($stmt == null) {
throw new Exception();
}
$result1 = $stmt->execute();
} catch (Exception $e) {
throw new Exception((__LINE__ . $db->errorInfo()),
LogUtil::ERROR_DB_EXECUTE);
}
3.プレースホルダを使ったプ
リペアドステートメントの実装
try {
$stmt = $db->prepare("SELECT * FROM account WHERE
id = ? AND account_id = ?”);
if ($stmt == null) {
throw new Exception();
}
$result1 = $stmt->execute(array($id, $account_id));
} catch (Exception $e) {
throw new Exception((__LINE__ . $db->errorInfo()),
LogUtil::ERROR_DB_EXECUTE);
}
動作確認
 ログインIDに「yamada」、パスワードに
「 P@ssword 」を入力してログインしてみましょう。
 URL欄に次のURLを入力してみましょう
 http://localhost/Web/Scenario109/EditSoft/bank.php
?page=3&account_id=99 OR 1=1
 口座残高照会ページに全てのユーザの口座残高が表示さ
れなければOKです。
数値リテラルに対するSQLイン
ジェクションの要点
 数値リテラルに対するSQLインジェクションの脆弱性の
原因も、ユーザから受け取った入力値をそのまま文字連
結してSQL文を組み立てていることです。
 文字列リテラルに対するSQLインジェクションと同様に、
プレースホルダを用いたプリペアドステートメントによ
るSQL文の組み立てを行い、ユーザからの入力値をエス
ケープ処理するようにしましょう。