サイバーセキュリティ演習 ― Web セキュリティ基礎 & 実践 ― 9. 偽リクエストによるサービスの不正利用対策
講義内容 1. 2 *.Webサイトの仕組みとWebプログラミング基礎 *.不正スクリプトの実行対策 6.7 *.データベースの不正操作対策 8 *.システムの不正操作対策とHTTPレスポンスの改竄対策 9 *.偽リクエストによるサービスの不正利用対策 10 *.セッションIDの不正取得対策 11.総合演習(1) 12 *. 公開ディレクトリの不正横断対策と認証認可制御の欠落 による不正アクセス対策とエラーメッセージからの情報 漏えい対策 13.総合演習(2) 14.総合演習(3) 15.学期末試験 ※* はレポートがある回になります 。
本日の内容 クロスサイト・リクエスト・フォージェリ (CSRF)の脆弱性攻撃体験と脆弱性の修正 意図しない命令の実行 不完全な対策
演習テーマ CSRF 「 意図しない命令の実行 」 のリンクをクリックしま しょう 。
クロスサイトリクエストフォー ジェリ (CSRF) とは 、 Cross-Site Request Forgery サイト横断型リクエスト偽造 攻撃者が他人の Web サイトに罠のリンクを埋め込み 、 偽造のリクエストを送信することで 、 認証済みの ページ上でしか行えない処理を不正に実行する脆弱 性 Web の認証状態の管理方法 Cookie
Cookie クライアントの端末にログイン ID 、 パスワード 、 認証状 態やアクセス履歴などセッション情報を一時的に保存す る仕組み 6 Web サーバ ID とパスワード入力 ユーザ専用ページを送付 セッション情報を通知 ログアウト ログアウト後のページを送付 クライアント DB 次回から、ブラウ ザは Cookie に保 存したセッション 情報を送信 セッション情報をも とに個人を特定 セッション情報は一 定期間保持 DB で管理する ID 、パスワード を参照し認証 ID PW yamada ******** 購入ページにアクセス 購入ページを送信 オンラインショップにアクセス ログインページを送付
HTTP レスポンスの例 HTTP/ OK Date: Thu, 24 Sep :05:20 GMT Server: Apache/2 Cache-Control: no-cache Expires: 0 Connection: close Transfer-Encoding: chunked Content-Type: text/html; charset=shift_jis Location: Set-Cookie: ssid= ;path=/var/www/html/ ( 省略 ) レスポンスヘッダ レスポンスボディ レスポンスメッセージ
CSRF の攻撃方法の一例 ( ログインしていない場合 ) 8 Web サーバ クライアント DB ④ 認証要求 攻撃者 ① 事前に 、 罠の URL を張り付ける ③ クリックにより 意図しないリクエ ストが送信される ②第三者の Web サーバにア クセスした時に、罠の URL を クリックしてしまう 第三者の Web サーバ 脆弱性があるオンライン ショップ Web サイト ID PW yamada ******** 意図しないリクエス トが実行されない
CSRF の攻撃方法の一例 ( ログイン中の場合 ) ログインしたユーザのみが変更可能な設定を不正に操作されてしまう 。 9 Web サーバ クライアント DB ログイン中 攻撃者 ① 事前に 、 罠の URL を張り付ける ③ クリックにより 意図しないリクエ ストが送信される ④ 意図しないリクエ ストが実行される ②第三者の Web サーバに アクセスした時に、罠の URL をクリックしてしまう パスワードの変更 公開設定の変更 など 第三者の Web サーバ 脆弱性があるオンライン ショップ Web サイト
CSRF と XSS の違い 10 Web サーバ クライアント DB ログイン中 攻撃者 ① 事前に 、 罠の URL を張り付ける ③ クリックにより 意図しないリクエ ストが送信される CSRF の場合 、 ④ 意図しないリクエ ストが実行される ②第三者の Web サーバに アクセスした時に、罠の URL をクリックしてしまう 第三者の Web サーバ XSS の場合 、 ④ レスポンスの意図しないスクリプトが実行される 不正操作 (CSRF) 不正スクリ プト実行 (XSS)
演習内容 ( 疑似的な攻撃 ) 掲示板に罠のリンクを張り付け 、 クリックによって SNS サイトの個人情報公開設定を変更する 第三者のウェブサイト 掲示板 脆弱性がある ウェブサイト SNS サイト
演習の進め方 1.Web サイトの挙動を把握する 2. 脆弱性となる箇所を特定する 3. 罠のリンクを考える 4. 罠のリンクを掲示板に投稿する 5. 第三者の個人情報設定が変更されることを確認す る 。
1. Web サイトの挙動を把握 する SNS にログイン後 、 設定変 更ページに移動し 、 個人情 報公開設定が 「 非公開 」 に なっていることを確認する 。 ID は 「 yamada 」、 パ スーワードは 「 」 攻撃者として 、 利用できる ことを考える 。 設定変更ページのソースを 確認しましょう 。 公開 / 非公開設定した後の URL も確認しましょう 。
2. 脆弱性となる箇所を特定す る 公開と非公開が指定されたパラメータを確認できま したか ? ?page=4&secret_token=ialeltofu7c6v63hbtuol4nid 4&name=yamada&year=1990&month=1&day=1& mail=yamada%40example.com&public=1 public=1 は公開 public=0 は非公開
3. 罠のリンクを考える SNS サイトの公開設定変更時には 、 次の URL 文が作成され ます 。 e=4&secret_token=ialeltofu7c6v63hbtuol4nid4&name=y amada&year=1990&month=1&day=1&mail=yamada%4 0example.com&public=1 「 非公開 」 から 「 公開 」 に変更する URL を考えましょう 。 不要なパラメータは削ってください 。 secret_token, name, year, month, day, mail e=4&public=1
4. 罠のリンクを掲示板に投稿 する 罠のリンクを URL 欄に入 力し投稿しましょう 。 b/Scenario113/VulS oft/sns.php?page= 4&public=1
5. 第三者の個人情報設定が変 更されることを確認する 。 第三者のアカウントでログインをしましょう 。 ログイン ID は 「 sato 」 パスワードは 「 sato310 」 罠の URL をクリックすることによって 、 佐藤さんの 個人情報公開設定が 「 非公開 」 から 「 公開 」 になっ てしまうことを確認しましょう 。
5. 第三者の個人情報設定が変 更されることを確認する 。 「 Congratulations!! 演習の目標を達成しまし た 。」 と表示されたら 、 OK です 。
CSRF の一般的な影響 ログインユーザのみが利用可能なサービスを悪用される ショッピングサイトなどのウェブアプリケーションへユーザが 意図しないリクエストを送信させられることで 、 不正送金 、 商 品購入 、 退会処理など 、 ユーザに不利益となる被害や 、 不快と 思われる行為が 、 ユーザの気がつかないうちに実行されてしま う 。 ログインユーザのみが編集可能な情報を改ざんされる SNS などのウェブアプリケーションにユーザの意図しないリク エストを送信させられることで 、 各種設定の変更 ( 管理者画面 、 パスワードなど )、 掲示板への不適切な書き込みなどが 、 ユー ザの気がつかないうちに実行されてしまう 。
対処方法 原因 ログインしたユーザからのリクエストに対して 、 その ユーザが意図したリクエストであるかどうかを識別す る仕組みを持たないために 、 認証状態を悪用され 、 不 正な操作が実行されてしまう 対処方法 罠の URL を経由したリクエストと正規のリクエストを識 別できるよう 、 リクエストにトークン ( 秘密情報 ) を 付加し 、 検証する機能を実装する 。
トークンとは 第三者が知りえない秘密情報として用いる暗号 理論的に安全な疑似乱数 ユーザからリクエストを受けた際に 、 ログイン時 のトークンとの比較により検証する HTML の input タグに hidden パラメータとともに指 定され 、 ブラウザ上には表示されない SNS サイトの設定変更ページのソースコードを確 認してみましょう 。
トークン処理の流れ
GET 送信と POST 送信 GET 送信 URL に入力値を含めてデータを送信する 送信できるデータはテキストのみ 宣言しない場合は GET で送信される ( デフォルト ) GET 送信でトークンを送付すると 、 外部サーバのア クセスログにトークンを含む URL が記録されてしま い 、 トークンが漏れる可能性があるので注意 POST 送信 URL に入力値を含めずデータを送信する 送信できるデータはテキストとバイナリが可能 トークンを含むリクエストは POST 送信で実施すべき
演習内容 ( 脆弱性の修正 ) SNS サイトの CSRF の脆弱性となるコードを特定し 、 トークンをチェックし一致しない場合はログイン画面へ 遷移する実装を行う
修正プログラム SNS サイト sns.php sns113.class.ph p の処理内容を ゲット メッセージ割り 当て テンプレート表 示 sns113.class.php SNS の内容 ( データベースの データ ) の初期設定 攻撃成功判定 設定完了画面の処理 個人情報設定変更時の検証処理 日付チェック SQL 文の処置 生年月日 、 ユーザ ID の取得 リファラ ( 参照元 ) チェック ログイン状態の検証
脆弱性の修正の手順 sns113.class.php public function validate_is_logined() 1. 処理内容の確認 。 2. トークンチェック機能を追加する箇所の特定 。 3. トークンチェック機能の実装 。
1. 処理内容の確認 public function validate_is_logined() { $session = $this->get_session(); $param = $this->get_param(); parent::validate_is_logined(); return $this; } ログイン処理を実行 セッション情報とパ ラメータ情報を取得
2. トークンチェック機能を追 加する箇所の特定 public function validate_is_logined() { $session = $this->get_session(); $param = $this->get_param(); parent::validate_is_logined(); return $this; }
3. トークンチェック機能の実 装 public function validate_is_logined() { $session = $this->get_session(); $param = $this->get_param(); if (($this->get_page() == parent::PAGE_SETTING) && isset($session[$this- >get_login()]["secret"]) && ($session[$this->get_login()]["secret"] !== $param["secret_token"])) { $this->set_session($this->get_login(), false); $this->set_page(parent::PAGE_LOGIN); $this->set_content(self::WARNING9, true); return false; } else { parent::validate_is_logined(); } 「ページ番号が同じ」かつ「変数が セットされ NULL ではない」かつ 「トークンが異なる」場合 そうでない場合、ログイン処理を実行 ログイン処理結果を失敗に、 出力ページをログインペー ジに、出力メッセージを警 告メッセージに設定し、 false を返す
動作確認 佐藤さんのアカウントで SNS にログインしましょう 。 ログイン ID は 「 sato 」、 パスワードは 「 sato310 」 掲示板の URL 欄に次の URL を投稿しましょう hp?page=4&public=1 「 不正なリクエストです 。」 と出力され 、 佐藤さんの個 人情報公開設定が 「 非公開 」 から 「 公開 」 にならなけれ ば OK です 。
本日の内容 クロスサイト・リクエスト・フォージェリ (CSRF)の脆弱性攻撃体験と脆弱性の修正 意図しない命令の実行 不完全な対策
演習テーマ CSRF 「 不完全な対策 」 のリンクをクリックしましょう 。
CSRF の不完全な対策 CSRF の対策として 、 リクエストにトークンを含ませる方 法は有効だが 、 トークンに規則性がある場合 、 悪意のある 人に推測され 、 対策を回避されてしまう可能性がある
演習内容 ( 疑似的な攻撃 ) SNS サイトで利用されるトークンの規則性を発見する 脆弱性があるウェブサイト SNS サイト
演習の進め方 1.Web サイトの挙動を把握する 2. 脆弱性となる箇所を特定する
1. Web サイトの挙動を把握 する SNS にログイン後 、 設定変 更ページに移動し 、 設定変 更をしましょう 。 ID は 「 yamada 」、 パ スーワードは 「 」 攻撃者として 、 利用できる ことを考える 。 設定変更ページのソースを 確認しましょう 。
2. 脆弱性となる箇所を特定す る トークンの規則性を確認できましたか ? トークンは連番で割り当てられます 。 ログインし直すと 、 secret パラメータの値がインクリ メントされることが確認できます 。
対処方法 原因 ログインしたユーザからのリクエストに対して発行す るトークンが規則性を有するため 、 トークンを推測さ れてしまい 、 不正な操作が実行されてしまう 対処方法 CSRF の対策として秘密情報を使用する場合は 、 安全な 疑似乱数を用いて 、 第三者に予測困難なトークンを利 用する
演習内容 ( 脆弱性の修正 ) SNS サイトの CSRF の脆弱性となるコードを特定し 、 安 全な擬似乱数により生成したトークンを使用する実装を 行う
修正プログラム SNS サイト sns.php sns114.class.ph p の処理内容を ゲット メッセージ割り 当て テンプレート表 示 sns114.class.php SNS の内容 ( データベースの データ ) の初期設定 ログイン処理 設定入力画面の処理 トークン割り当ての処理 個人情報設定変更時の検証処理
脆弱性の修正の手順 sns114.class.php public function prepare_set_token() 1. 処理内容の確認 。 2. トークンを割り当る箇所の特定 。 3. 予測困難なトークン割り当ての実装 。
1. 処理内容の確認 public function prepare_set_token() { $db = $this->get_db(); $param = $this->get_param(); $session = $this->get_session(); $token = null; try { $get_stmt = $db->prepare(self::GET_TOKEN_SQL); $get_stmt->execute(); $token = $get_stmt->fetch(); } catch(Exception $e) { throw new Exception((__LINE__. json_encode($this->_db->errorInfo())), LogUtil::ERROR_DB_EXECUTE); } ( 次ページに続く ) トークン検索の SQL を準備し、実行 データベース情報、 パラメータ、セッ ション情報を取得
1. 処理内容の確認 ( つづき ) try { $update_stmt = $db->prepare(self::UPDATE_TOKEN_SQL); $update_stmt->execute(); } catch(Exception $e) { throw new Exception((__LINE__. json_encode($this->_db- >errorInfo())), LogUtil::ERROR_DB_EXECUTE); } $session[$this->get_login()][self::TOKEN] = $token["value"]; $this->set_session($this->get_login(), $session[$this- >get_login()]); return $this; } トークン割り当て トークン更新の SQL 文を準備し実行 セッション情報として セット
2. トークンを割り当る箇所の 特定 ( つづき ) try { $update_stmt = $db->prepare(self::UPDATE_TOKEN_SQL); $update_stmt->execute(); } catch(Exception $e) { throw new Exception((__LINE__. json_encode($this->_db- >errorInfo())), LogUtil::ERROR_DB_EXECUTE); } $session[$this->get_login()][self::TOKEN] = $token["value"]; $this->set_session($this->get_login(), $session[$this- >get_login()]); return $this; }
3. 予測困難なトークン割り当 ての実装 ( つづき ) try { $update_stmt = $db->prepare(self::UPDATE_TOKEN_SQL); $update_stmt->execute(); } catch(Exception $e) { throw new Exception((__LINE__. json_encode($this->_db- >errorInfo())), LogUtil::ERROR_DB_EXECUTE); } $session[$this->get_login()][self::TOKEN] = session_id(); $this->set_session($this->get_login(), $session[$this- >get_login()]); return $this; } 今回はセッション ID で使われている 疑似乱数をそのまま利用している。 (本来は NG )
動作確認 SNS にログインし 、 設定変更ページに移動しましょう 。 ログイン ID は 「 yamada 」、 パスワードは 「 」 ソースコードを表示し 、 トークンが疑似乱数に変わって いれば OK です 。
CSRF の要点 CSRF の脆弱性の原因は 、 ユーザが意図したリクエ ストであるかどうかを識別する仕組みを持たない ことです 。 Web ページを出力する際には 、 第三者に予測困難 なトークンを hidden パラメータに挿入するように しましょう 。 そして 、 ユーザからのリクエストを 受けた際には 、 hidden パラメータの値と元のトー クンを比較し 、 一致しない場合は処理を行わない ようにしましょう 。
課題 実際に 、 CSRF の脆弱性を突かれて被害を受 けた事件を調査し 、1) 被害の内容と時期 、 2) 攻撃方法とその攻撃で可能だったこと 、 3) 脆弱性が生まれた原因 、4) 実施され た対策について 、 参考にした情報源などを 引用しつつ簡潔にまとめてください 。 本講義の感想 、 要望 、 質問などあれば 、 書 いてください 。