Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


Presentation on theme: "サイバーセキュリティ演習 ― Webセキュリティ基礎&実践―"— Presentation transcript:

1 サイバーセキュリティ演習 ― Webセキュリティ基礎&実践―
6. データベースの不正操作対策

2 講義内容 1. 2*. Webサイトの仕組みとWebプログラミング基礎 3.4.5*. 不正スクリプトの実行対策 6.7*. データベースの不正操作対策 8*. システムの不正操作対策とHTTPレスポンスの改竄対策 9*. 偽リクエストによるサービスの不正利用対策 10*. セッションIDの 不正取得対策 11. 総合演習(1) 12*. 公開ディレクトリの不正横断対策と認証認可制御の欠落 による不正アクセス対策とエラーメッセージからの情報 漏えい対策 13. 総合演習(2) 14. 総合演習(3) 15. 学期末試験 ※*はレポートがある回になります。

3 本日の内容 SQLインジェクションの脆弱性攻撃体験と 脆弱性の修正 不正なログイン(文字列リテラル) 情報漏えい(数値リテラル)

4 SQLとは SQLは、リレーショナルデータベース管理システム (RDBMS) において、データの操作や定義を行うた めのデータベース言語(問い合わせ言語)である。 RDBMSは、リレーショナルデータベースを管理す るためのソフトウェア。 Oracle、Access、 MySQL、PostgreSQL、 SQLite 等 (Wikipediaより)

5 リレーショナルデータベース管理システム(RDBMS)
データを表に似た構造で管理するデータベース。複 数のデータ群が関係と呼ばれる構造で相互連結可能 userテーブル ログインID (id:文字列) ユーザ名 (name:文字列) パスワード (password:文字列) yamada Yamada Taro suzuki Suzuki Jiro 3f858c accountテーブル ログインID (id:文字列) 口座番号 (account_id:数値) 残高 (balance:数値) yamada 100,000 200,000 suzuki 300,000 関係を持った複数のテーブルに分けて管理

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

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

8 データ定義言語 CREATE DROP ALTER TRUNCATE データベース、テーブルやカラム、レコードな どを作成する
データベース、テーブルやカラム、レコードな どを削除する ALTER 既に存在するデータベース、テーブルやカラム、 レコードなどを変更する TRUNCATE テーブルからレコードを削除する

9 データ操作言語 SELECT INSERT UPDATE DELETE テーブルからデータを検索する レコードを追加する レコードを更新する
レコードを削除する

10 データ制御言語 GRANT 利用者に特定の作業の権限を与える REVOKE 利用者に与えた特定の作業の権限をはく奪する

11 SQLの基礎1 データを検索する場合、 SELECT カラム1、カラム2 FROM テーブル名 [WHERE <条件>];
SELECT * FROM user WHERE id=‘yamada’; SELECT *:すべてのカラムを検索する FROM user:userテーブルから WHERE id=‘yamada’:id=yamadaに一致する レコードの

12 例えば、以下のテーブルがあった場合の検索結果は?
SELECT * FROM user WHERE id=‘yamada’; userテーブル ログインID (id:文字列) ユーザ名 (name:文字列) パスワード (password:文字列) yamada Yamada Taro suzuki Suzuki Jiro 3f858c accountテーブル ログインID (id:文字列) 口座番号 (account_id:数値) 残高 (balance:数値) yamada 100,000 200,000 suzuki 300,000

13 SQLの基礎2 リテラル(直定数) SELECT * FROM user WHERE id = 'yamada';
プログラミングなどで、データ型に直接定めた値のこと。 文字列リテラルは、データ型に直接定めた文字列のこと 以下の例では、yamadaが文字列リテラルとなる SELECT * FROM user WHERE id = 'yamada'; 数値リテラルは、データ型に直接定めた数値のこと 以下の例では、200000が数値リテラルとなる SELECT * FROM account WHERE balance >= ;

14 SQLの基礎3 シングルクォート(’) コメント(--) SQLでは、データの区切り文字として使う。
シングルクォートで囲むことで文字列リテラルを定義 する 数値リテラルの定義の場合は不要 コメント(--) SQLでは、2連続のハイフン(--)以降は、コメン トとして扱う

15 SQLインジェクションとは 悪意のあるSQLを注入(インジェクショ ン)し、Webアプリケーションが意図しな いSQL文を実行してしまうことで、データ ベースを不正に操作されてしまう脆弱性

16 SQLインジェクションの種類 文字列リテラルに対するSQLインジェクション 数値リテラルに対するSQLインジェクション

17 演習テーマ SQLインジェクション 「不正なログイン(文字列リテラル)」のリンクをク リックしましょう。

18 文字列リテラルに対するSQLインジェクションの原理
ユーザからの入力値をそのまま文字列リテラルに連結して SQL文を組み立てることにより、意図しないSQL文を実行さ れ、データベースを不正に操作されてしまう

19 一般的なSQL文の組み立て処理のやり方 指定したidの個人情報をuserテーブルから取得するSQL文を ユーザからの入力値(yamada)を利用して文字列連結によ り組み立てる

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

21 SQLを使った認証判定 ログインページの認証判定でSQLはよく使われる。 WHERE句の条件にあてはまるならば認証OK
WHERE句の条件にあてはまらないならば認証NG ○:SELECT * FROM user WHERE id=‘yamada’ AND ×:SELECT * FROM user WHERE id=‘suzuki’ AND password=‘ ’ userテーブル ログインID (id:文字列) ユーザ名 (name:文字列) パスワード (password:文字列) yamada Yamada Taro suzuki Suzuki Jiro 3f858c

22 文字列リテラルを用いたSQLインジェクションの攻撃手口
WHERE句の条件が必ずTRUE(真)になるように内容 を変更する シングルクォート(’)とコメント(- -)が使われること が多い SELECT * FROM user WHERE id = ‘yamada’ AND password = ‘   '; 最初のシングルクォート(‘)でpasswordの入力を終端する OR演算子を使って別の条件を提示する ‘A’=’A’によって条件を必ずTRUE(真)とする コメント (--)で最後のシングルクォートを無効にする ‘ OR ‘A’=’A’ --

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

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

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

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

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

28 なぜデータベースエラーが起きるのか 正常なSQL文 エラーとなるSQL文
SELECT * FROM user WHERE id = ‘yamada ’ AND password = エラーとなるSQL文 SELECT * FROM user WHERE id = ‘’ ‘ AND password = SELECT * FROM user WHERE id = ‘yamada ’ AND password = ‘’ ’; シングルクォートの余りがあるため構文エラーとなる。

29 3.不正ログイン用の文字列リテラルを考える
ユーザ認証処理では、次のSQL文が使用されていま す。 SELECT * FROM user WHERE id = ‘yamada' AND password = 'パスワード'; 論理演算子 OR を使用してWHERE句が常に正しく なる条件にしましょう パスワードの条件が常に「真」となる文字リテラル を考えましょう。 SELECT * FROM user WHERE id = ‘yamada' AND password = ‘OR ‘A’=’A’ --';

30 4.不正にログインする 考えたパスワードを使ってログインができるか確認 しましょう。
ログインIDは「yamada」を使いましょう パスワードは「' OR 'A'='A' --」 以下のログインIDを使った場合でもログインができ るか確認しましょう。 ログインIDは「yamada ‘ --」 パスワードは、適当。

31 4.不正にログインする 「Congratulations!!演習の目標を達成しまし た。」と表示されたら、OKです。

32 SQLインジェクションの一般的な影響 データベースに蓄積された非公開情報を閲覧される データベースに蓄積された情報を改ざん、消去される
個人情報や機密情報などが漏えいする可能性がある データベースに蓄積された情報を改ざん、消去される ウェブページが改ざんされたり、パスワードが変更されてし まったり、システムが停止するといった被害が発生する可能性 がある。 認証回避により不正にログインされる ログインしたユーザに許可されている全ての操作が可能となり、 不正な行為が行われる可能性がある。 ストアドプロシージャなどを利用してOS コマンドを実行さ れる システムの乗っ取りや、他への攻撃の踏み台として悪用される 可能性がある。 ストアドプロシージャとは、データベースに対する一連の処理をプログラムにまとめて、リレーショナルデータベース管理システムに保存(永続化)したもの

33 対処方法 原因 外部から入力できるパラメータをそのまま文字列連結 してSQL文を組み立てるため、WHERE句の条件が常に 真となるリテラルの注入によりSQL文が変更されてし まい、そのままSQLの処理が実行される 対処方法 文字列リテラルの入力値を文字そのものとして解釈さ せるために、SQL文の組み立ては全てプレースホルダ を使いプリペアステートメントで実装する。

34 プレースホルダ SQL文のリテラル部分に後から正式な値を挿入するために一 時的に場所として確保しておく値 プレースホルダなし
実際の値を挿入することをバインド処理という 静的プレースホルダと動的プレースホルダがある プレースホルダなし SELECT * FROM user WHERE id = ‘yamada' AND password = プレースホルダあり SELECT * FROM user WHERE id = ? AND password = ?; バインド処理後は普通の文字列として扱われる yamada

35 静的&動的プレースホルダ 静的プレースホルダ 動的プレースホルダ
バインド処理をデータベース側で実行する方式 PHPからプレースホルダのついたSQL文をデータベース側 にあらかじめ送信してSQL文を確定させておく SQL実行段階で、PHPから実際の値をデータベースに送り、 データベースがバインド処理をしてからSQL文を実行する 動的プレースホルダ バインド処理をWebアプリケーション側で実行する方式 PHPがバインド処理したSQL文をデータベースに送り、 データベースがそのSQL文を実行する 動的プレースホルダの不適切な実装は脆弱性となるため、 可能な限り静的プレースホルダを利用しましょう

36 プリペアドステートメントの実装 PDO(PHP Data Object) プリペアドステートメントの実装手順
1つの関数で複数のデータベースアクセスを可能にす る抽象化クラス 2005年11月にリリースされたPHP5.1.0から実装された PDOが実装されるまでは、データベースの種類ごとに 関数を分けていた プリペアドステートメントの実装手順 PDOの利用を宣言:PDO() 例外処理を施す: try{}catch{} SQL文を準備する:prepare() SQLを実行する:execute()

37 プレースホルダを使わないプリペアドステートメントの例
<?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’; 例外発生時の エラー表示

38 プレースホルダを使ったプリペアドステートメントの例
<?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関数に配列で渡す

39 演習内容(脆弱性の修正) オンラインバンキングの文字列リテラルを用いたSQLイ ンジェクションの脆弱性となるコードを特定し、プレー スホルダの実装を行う 演習では、脆弱性のあるWebアプリケーションとデータ ベースサーバが同一ホスト上にあるため、結果として動 的プレースホルダの実装で演習を進めることになります。

40 修正プログラム オンラインバンキング bank.php bank108.class.php
メッセージ割り当て テンプレート表示 bank108.class.php データベースのデータの初期設定 テーブルからの情報取得の成功判定 ログイン処理

41 脆弱性の修正の手順 bank108.class.php ログイン処理の内容の確認。 プレースホルダを使用する箇所の特定。
プレースホルダを使ったプリペアドステートメントの 実装。

42 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); } (次ページに続く) データベースのアクセス情報を取得 リテラル(入力値)の情報を取得 プリペアドステートメントを実行 (データベース検索の実行)

43 データベース検索結果からユーザ情報を取得
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; } 検索結果が返ってきたら 攻撃成功判定 クライアントとのセッションを確立 利用者のページを設定 認証成功を返す ログアウト処理を実行 警告メッセージを設定 認証失敗を返す

44 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); }

45 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); }

46 動作確認 ログインIDに「yamada」、パスワードに「' OR 'A'='A' --」を入力してログインしてみましょう。
ログインができなければOKです。

47 文字列リテラルに対するSQLインジェクションの要点
文字列リテラルに対するSQLインジェクションの脆弱性 の原因は、ユーザから受け取った入力値をそのまま文字 連結してSQL文を組み立てていることです。 意図しないSQL文の実行を防ぐために、プレースホルダ を用いたプリペアドステートメントによるSQL文の組み 立てを行い、ユーザからの入力値をエスケープ処理する ようにしましょう。

48 本日の内容 SQLインジェクションの脆弱性攻撃体験と 脆弱性の修正 不正なログイン(文字列リテラル) 情報漏えい(数値リテラル)

49 SQLインジェクションの種類 文字列リテラルに対するSQLインジェクション 数値リテラルに対するSQLインジェクション

50 演習テーマ SQLインジェクション 「情報漏えい(数値リテラル)」のリンクをクリック しましょう。

51 数値リテラルに対するSQLインジェクションの原理
ユーザからの入力値をそのまま数値リテラルに連結してSQL 文を組み立てることにより、意図しないSQL文を実行され、 データベースを不正に操作されてしまう

52 一般的なSQL文の組み立て処理のやり方 指定したaccount_idの口座情報をaccountテーブルから取 得するSQL文をユーザからの入力値(10)を利用して文字列 連結により組み立てる

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

54 SQLを使った情報取得 ユーザの情報取得にSQLはよく使われる。 WHERE句の条件にあてはまるならば結果を出力
○:SELECT * FROM user WHERE id=‘yamada’ AND account_id= ×:SELECT * FROM user WHERE id=‘suzuki’ AND account_id= accountテーブル ログインID (id:文字列) 口座番号 (account_id:数値) 残高 (balance:数値) yamada 100,000 200,000 suzuki 300,000

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

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

57 演習の進め方 Webサイトの挙動を把握する 脆弱性となる箇所を特定する 全てのユーザの口座残高を表示させる数値リテラ ルを考える
不正アクセスのURLを作成し実行する

58 1.Webサイトの挙動を把握する オンラインバンクの口座 残高照会ページの動作を 確認する。 攻撃者として、利用でき ることを考える。
SQL文のエラーを起こす 値を入力して、脆弱な個 所を発見しましょう。 URLも確認しましょう。

59 2.脆弱性となる箇所を特定する 数値リテラルの終端を狙い、account_idにシングルクォー ト(’)を入力してみる
ge=3&account_id=‘; 構文エラーが出たということは、入力値を含んだSQL文が作成され、データベースに問い合わせされたと推測できる 正常(番号が無ければ表示されない) 脆弱性あり(データベースエラー)

60 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;

61 4.不正アクセスのURLを作成し実行する 口座残高照会のURLは以下の通りです。 考えた数値リテラルを追記したURLを作成しましょ う。
php?page=3&account_id= 考えた数値リテラルを追記したURLを作成しましょ う。 php?page=3&account_id=1 OR 1=1;

62 4.不正アクセスのURLを作成し実行する ログインユーザ以外の口座残高情報が取得できるか 確認しましょう
まずは、yamadaのIDでログインしましょう。 ログインIDは「yamada」 ログイン後、作成したURLをURL欄に入力しましょう。

63 4.不正アクセスのURLを作成し実行する 「Congratulations!!演習の目標を達成しまし た。」と表示されたら、OKです。

64 対処方法 原因 外部から入力できるパラメータをそのまま文字列連結 してSQL文を組み立てるため、WHERE句の条件が常に 真となるリテラルの注入によりSQL文が変更されてし まい、そのままSQLの処理が実行される 対処方法 数値リテラルの入力値を値そのものとして解釈させる ために、SQL文の組み立ては全てプレースホルダを使 いプリペアステートメントで実装する。

65 演習内容(脆弱性の修正) オンラインバンキングの数値リテラルを用いたSQLイン ジェクションの脆弱性となるコードを特定し、動的プ レースホルダの実装を行う 演習では、脆弱性のあるWebアプリケーションとデータ ベースサーバが同一ホスト上にあるため、結果として動 的プレースホルダの実装で演習を進めることになります。

66 修正プログラム オンラインバンキング bank.php bank109.class.php
メッセージ割り当て テンプレート表示 bank109.class.php データベースのデータの初期設定 テーブルからの情報取得の成功判定 口座番号の有効性の検証 口座データの取得処理

67 脆弱性の修正の手順 bank109.class.php 口座データの取得の内容の確認。 プレースホルダを使用する箇所の特定。
プレースホルダを使ったプリペアドステートメントの 実装。

68 データベース、セッション、アカウント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の情報を取得

69 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); (次ページに続く)

70 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(); 残高を金額形式(カンマ区切り)に変換 金額形式の残高をセットし、攻撃成功判定

71 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);

72 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);

73 動作確認 ログインIDに「yamada」、パスワードに 「 P@ssword 」を入力してログインしてみましょう。
URL欄に次のURLを入力してみましょう ?page=3&account_id=99 OR 1=1 口座残高照会ページに全てのユーザの口座残高が表示さ れなければOKです。

74 数値リテラルに対するSQLインジェクションの要点
数値リテラルに対するSQLインジェクションの脆弱性の 原因も、ユーザから受け取った入力値をそのまま文字連 結してSQL文を組み立てていることです。 文字列リテラルに対するSQLインジェクションと同様に、 プレースホルダを用いたプリペアドステートメントによ るSQL文の組み立てを行い、ユーザからの入力値をエス ケープ処理するようにしましょう。


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

Similar presentations


Ads by Google