サイバーセキュリティ演習 ― Webセキュリティ基礎&実践―

Slides:



Advertisements
Similar presentations
1 安全性の高いセッション管理方 式 の Servlet への導入 東京工業大学 理学部 千葉研究室所属 99-2270-6 松沼 正浩.
Advertisements

サイバーセキュリティ演習 ― Web セキュリティ基礎 & 実践 ― 9. 偽リクエストによるサービスの不正利用対策.
OWL-Sを用いたWebアプリケーションの検査と生成
サイバーセキュリティ演習 ― Webセキュリティ基礎&実践―
DB(データベース)のおはなし 作成者:小野正広 DBと言っても、  ドラゴンボール ではないですぞ! 3/1/2017.
情報理工学部 情報システム工学科 ラシキアゼミ 3年 H 井奈波 和也
サイバーセキュリティ演習 ― Webセキュリティ基礎&実践―
情報理工学部 情報システム工学科 3年 H 井奈波 和也
SQLの条件節が動的に構成されることを考慮した データベース接続APIの設計
サイバーセキュリティ演習 ― Webセキュリティ基礎&実践―
JPAを利用した RESTful Webサービスの開発
WEBから確認できる 駐車場管理システムについて
3-1 MySQLについて 発表者:藤村元彦 自然言語処理研究室.
Excel による データベース入門 Ver /9.
6-2 データベース 1.SQLite SQLを単純化した SQLite を使ってデータベースを操作 表「fruit」
Accessによる SQLの操作 ~実際にテーブルを操作してみよう!~.
SQL J2EE I 第3回 /
サイバーセキュリティ演習 ― Webセキュリティ基礎&実践―
第2回:Javaの変数と型の宣言 プログラミングII 2007年10月2日.
キャンパスクラウドによる 実験環境の構築 情報ネットワーク特論 講義資料.
Vulnerability of Cross-Site Scripting
3-2.データを取り出す 2004年 5月20日(木) 01T6074X 茂木啓悟.
HTTPプロトコルとJSP (1) データベース論 第3回.
サイバーセキュリティ演習 ― Webセキュリティ基礎&実践―
JQueryでAjax 藤田@ジャストプレイヤー ※参考しまくり文献 jQuery日本語リファレンス.
HTTPプロトコル J2EE I 第7回 /
Day3 Day4 Day3 Day4.
 データベースによる並列処理 情報論理工学研究室  三宅健太.
(B2) 親: minami, kazuki 多様な認証機器に対応する 認証システム (B2) 親: minami, kazuki.
岡村耕二 サイバーセキュリティ Web セキュリティ 岡村耕二 情報ネットワーク.
データベース設計 第9回 Webインタフェースの作成(1)
マイクロソフト Access での SQL 演習 第1回 SQL問い合わせ(クエリ)
第8章 Web技術とセキュリティ   岡本 好未.
プログラム実行履歴を用いたトランザクションファンクション抽出手法
第2回 SQL インジェクション その攻撃と対処 NECラーニング 山崎 明子.
2004/05/13 3-4 データ型(カラムタイプ) について 発表者:藤村元彦 自然言語処理研究室.
九州大学キャンパスクラウド 利用法 情報ネットワーク特論 講義資料.
JDBC J2EE I 第4回 /
第2回.リレーショナルデータベース入門 SQL を用いたテーブルへの行の挿入 SQL 問い合わせの発行と評価結果の確認.
3-10. MySQLシステムの管理  2004年6月10日  大北高広                01T6010F.
第1回.リレーショナルデータベースを使ってみよう
第1回.リレーショナルデータベースを使ってみよう
第2回.リレーショナルデータベース入門 SQL を用いたテーブルへの行の挿入 SQL 問い合わせの発行と評価結果の確認.
第9章 例外処理,パッケージ 9.1 例外処理 9.2 ガーベッジコレクション.
SQL パフォーマンス チューニング ~ プランガイドの利用~
マイクロソフト Access での SQL 演習 第5回 副問い合わせ
第3回.テーブルの結合 結合条件 SQL を用いた結合問い合わせ.
第3回.テーブルの結合 結合条件 SQL を用いた結合問い合わせ.
JDBC データベース論 第12回.
Javaによる Webアプリケーション入門 第7回
キャンパスクラウドによる 実験環境の構築 情報ネットワーク特論 講義資料.
Webセキュリティ 情報工学専攻 1年 赤木里騎 P226~241.
3-6.インデックスについて 3-7.関数と併用されることの 多いMySQLコマンド
3-3.テーブルを更新する 2004年 4月22日(木) 01T6074X 茂木啓悟.
オープンソース開発支援のための リビジョン情報と電子メールの検索システム
ネットワークプログラミング (3回目) 05A1302 円田 優輝.
UNIX演習 情報ネットワーク特論.
JDBC J2EE I (データベース論) 第5回 /
サイバーセキュリティ演習 ― Webセキュリティ基礎&実践―
3.リレーショナルデータベース,主キー, SQL
基礎プログラミング演習 第12回.
JDBC ソフトウェア特論 第3回.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
情報基礎演習I(プログラミング) 第11回 7月12日 水曜5限 江草由佳
Webアプリケーションと JSPの基本 ソフトウェア特論 第4回.
CO-Client Opeartion 1.1 利用履歴データベースの設計 (スキーマ バージョン 対応)
プログラミング 4 文字列.
第2回.リレーショナルデータベース入門 SQL を用いたテーブルへの行の挿入 SQL 問い合わせの発行と評価結果の確認.
データの改竄を防ぐ仕組み 2002/9/12 牧之内研究室「インターネット実習」Webページ
Javaとは Javaとはオブジェクト指向言語でJava VM(Java仮想マシン)と呼ばれるプログラム上で動作します。
Presentation transcript:

サイバーセキュリティ演習 ― 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 1000002 200,000 suzuki 1000003 300,000 関係を持った複数のテーブルに分けて管理

RDBMSのイメージとデータベースの用語 検索機能 抽出機能 追加削除機能 データベース テーブル2 accountテーブル テーブル1 userテーブル レコード (行) カラム(列)

SQLの種類 データ定義言語 データ操作言語 データ制御言語 カラムやレコードなどリレーショナルデータ ベースの構造を定義する言語 データの検索やデータの挿入などリレーショナ ルデータベースに対する操作を定義する言語 データ制御言語 データの操作に対する権限の付与やはく奪など アクセス制御を行うために定義する言語

データ定義言語 CREATE DROP ALTER TRUNCATE データベース、テーブルやカラム、レコードな どを作成する データベース、テーブルやカラム、レコードな どを削除する 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 1000002 200,000 suzuki 1000003 300,000

SQLの基礎2 リテラル(直定数) SELECT * FROM user WHERE id = 'yamada'; プログラミングなどで、データ型に直接定めた値のこと。 文字列リテラルは、データ型に直接定めた文字列のこと 以下の例では、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文の組み立て処理のやり方 指定した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 = ‘   '; 最初のシングルクォート(‘)でpasswordの入力を終端する OR演算子を使って別の条件を提示する ‘A’=’A’によって条件を必ずTRUE(真)とする コメント (--)で最後のシングルクォートを無効にする ‘ OR ‘A’=’A’ --

ID入力部分のSQLインジェクションの攻撃手口 SELECT * FROM user WHERE id = ‘ 攻撃者が入力した文字列リテラル:yamada ‘ - - コメントになる部分: ’ AND password = ‘P@ssword'; 適当なパスワードでyamadaのページにログインできる yamada ‘ - - ' AND password = ‘P@ssword';

演習内容(疑似的な攻撃) オンラインバンキングの文字列リテラルに不正な文字列 を入力し、不正にログインする 脆弱性があるウェブサイト

演習の進め方 Webサイトの挙動を把握する 脆弱性となる箇所を特定する 不正ログイン用の文字列リテラルを考える 不正にログインする

1.Webサイトの挙動を把握する オンラインバンクの入力 フィールドに様々な値を 入力して動作を確認する。 攻撃者として、利用でき ることを考える。 SQL文のエラーを起こす 値を入力して、脆弱な個 所を発見しましょう。

2.脆弱性となる箇所を特定する 文字列リテラルを終端を狙い、Webサイトの入力項目 にシングルクォート(’)を入力してみる 正常(ログインエラー) 脆弱性あり(データベースエ ラー) 構文エラーが出たということは、入力値を含んだSQL文が作成され、データベースに問い合わせされたと推測できる

なぜデータベースエラーが起きるのか 正常な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文のリテラル部分に後から正式な値を挿入するために一 時的に場所として確保しておく値 プレースホルダなし 実際の値を挿入することをバインド処理という 静的プレースホルダと動的プレースホルダがある プレースホルダなし 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) { print(“Error:”.$e->getMessage()); } ?> データベース接続 SQLを準備 例外処理 実行 以下は既に宣言済みとする。 $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.ログイン処理の内容の確認 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文の組み立て処理のやり方 指定したaccount_idの口座情報をaccountテーブルから取 得するSQL文をユーザからの入力値(10)を利用して文字列 連結により組み立てる

入力値に「 0 OR 1 = 1 」という文字列を与えると Where句の条件がTRUE(真)となります。 その結果、accountテーブルの全てのレコードが取得されます。

SQLを使った情報取得 ユーザの情報取得にSQLはよく使われる。 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 1000002 200,000 suzuki 1000003 300,000

数値リテラルを用いたSQLインジェクションの攻撃手口 WHERE句の条件が必ずTRUE(真)になるように内容 を変更する OR演算子が使われることが多い SELECT * FROM user WHERE id = ‘yamada’ AND account_id=    ; account_idには適当な値を指定する OR演算子を使って別の条件を提示する 1=1によって条件を必ずTRUE(真)とする 0 OR 1=1

演習内容(疑似的な攻撃) オンラインバンキングの数値リテラルに不正な文字列を 入力し、口座残高照会ページで全てのユーザの口座残高 を表示させる 脆弱性があるウェブサイト オンラインバンキング

演習の進め方 Webサイトの挙動を把握する 脆弱性となる箇所を特定する 全てのユーザの口座残高を表示させる数値リテラ ルを考える 不正アクセスの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は以下の通りです。 考えた数値リテラルを追記した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 口座データの取得の内容の確認。 プレースホルダを使用する箇所の特定。 プレースホルダを使ったプリペアドステートメントの 実装。

データベース、セッション、アカウントIDの情報を取得 1.口座データの取得の内容の確認 public function proc_inquiry() { $param = $this->get_param(); if (isset($param[parent::ACCOUNT_ID])) { $stmt = null; $db = $this->get_db(); $session = $this->get_session(); $id = $session[$this->get_login()][parent::USER_ID]; $account_id = $param[parent::ACCOUNT_ID]; (次ページに続く) データベース、セッション、アカウント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文の組み立てを行い、ユーザからの入力値をエス ケープ処理するようにしましょう。