偽リクエストによるサービスの不正利用対策

サイバーセキュリティ演習
― Webセキュリティ基礎&実践―
9.偽リクエストによるサービスの不正利用対策
講義内容
1. 2*. Webサイトの仕組みとWebプログラミング基礎
3.4.5*. 不正スクリプトの実行対策
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
6
Cookie
 クライアントの端末にログインID、パスワード、認証状
態やアクセス履歴などセッション情報を一時的に保存す
る仕組み
オンラインショップにアクセス
ID yamada
PW ********
ログインページを送付
IDとパスワード入力
ユーザ専用ページを送付
セッション情報を通知
クライアント
購入ページにアクセス
次回から、ブラウ
ザはCookieに保
存したセッション
情報を送信
購入ページを送信
ログアウト
ログアウト後のページを送付
DBで管理する
ID、パスワード
を参照し認証
DB
Webサーバ
セッション情報をも
とに個人を特定
セッション情報は一
定期間保持
HTTPレスポンスの例
 HTTP/1.1 200 OK
レスポンスメッセージ
 Date: Thu, 24 Sep 2015 01: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: http://survey.html
 Set-Cookie: ssid=123456789;path=/var/www/html/
 <html>(省略)</html>
レスポンスボディ
CSRFの攻撃方法の一例
(ログインしていない場合)
8
ID yamada
PW ********
脆弱性があるオンライン
ショップWebサイト
④認証要求
DB
クライアント
②第三者のWebサーバにア
クセスした時に、罠のURLを
クリックしてしまう
Webサーバ
③クリックにより
意図しないリクエ
ストが送信される
第三者の
Webサーバ
攻撃者
①事前に、罠の
URLを張り付ける
意図しないリクエス
トが実行されない
CSRFの攻撃方法の一例
(ログイン中の場合)
9
脆弱性があるオンライン
ショップWebサイト
ログイン中
DB
クライアント
②第三者のWebサーバに
アクセスした時に、罠の
URLをクリックしてしまう
Webサーバ
③クリックにより
意図しないリクエ
ストが送信される
第三者の
Webサーバ
攻撃者
①事前に、罠の
URLを張り付ける
④意図しないリクエ
ストが実行される
パスワードの変更
公開設定の変更 など
ログインしたユーザのみが変更可能な設定を不正に操作されてしまう。
CSRFとXSSの違い
10
XSSの場合、
④レスポンスの意図しないスクリプトが実行される
不正スクリ
プト実行
(XSS)
不正操作
(CSRF)
ログイン中
クライアント
②第三者のWebサーバに
アクセスした時に、罠の
URLをクリックしてしまう
DB
Webサーバ
③クリックにより
意図しないリクエ
ストが送信される
第三者の
Webサーバ
攻撃者
①事前に、罠の
URLを張り付ける
CSRFの場合、
④意図しないリクエ
ストが実行される
演習内容(疑似的な攻撃)
 掲示板に罠のリンクを張り付け、クリックによってSNS
サイトの個人情報公開設定を変更する
 第三者のウェブサイト
 掲示板
 脆弱性がある
ウェブサイト
 SNSサイト
演習の進め方
1. Webサイトの挙動を把握する
2. 脆弱性となる箇所を特定する
3. 罠のリンクを考える
4. 罠のリンクを掲示板に投稿する
5. 第三者の個人情報設定が変更されることを確認す
る。
1.Webサイトの挙動を把握
する
 SNSにログイン後、設定変
更ページに移動し、個人情
報公開設定が「非公開」に
なっていることを確認する。
 IDは「yamada」、パ
スーワードは
「P@ssword」
 攻撃者として、利用できる
ことを考える。
 設定変更ページのソースを
確認しましょう。
 公開/非公開設定した後の
URLも確認しましょう。
2.脆弱性となる箇所を特定す
る
 公開と非公開が指定されたパラメータを確認できま
したか?
 http://localhost/Web/Scenario113/VulSoft/sns.php
?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文が作成され
ます。
 http://localhost/Web/Scenario113/VulSoft/sns.php?pag
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
 http://localhost/Web/Scenario113/VulSoft/sns.php?pag
e=4&public=1
4.罠のリンクを掲示板に投稿
する
 罠のリンクをURL欄に入
力し投稿しましょう。
http://localhost/We
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サイトの設定変更ページのソースコードを確
認してみましょう。
 <input type="hidden" name="secret_token"
value="ihv95674r654qgc926qfo9njk0"/>
トークン処理の流れ
GET送信とPOST送信
 GET送信
 URLに入力値を含めてデータを送信する
 送信できるデータはテキストのみ
 宣言しない場合はGETで送信される(デフォルト)
 GET送信でトークンを送付すると、外部サーバのア
クセスログにトークンを含むURLが記録されてしま
い、トークンが漏れる可能性があるので注意
 POST送信
 URLに入力値を含めずデータを送信する
 送信できるデータはテキストとバイナリが可能
 トークンを含むリクエストはPOST送信で実施すべき
演習内容(脆弱性の修正)
 SNSサイトのCSRFの脆弱性となるコードを特定し、
トークンをチェックし一致しない場合はログイン画面へ
遷移する実装を行う
修正プログラム
 SNSサイト
 sns.php
 sns113.class.php
sns113.class.ph
pの処理内容を
ゲット
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();
「ページ番号が同じ」かつ「変数が
セットされNULLではない」かつ
「トークンが異なる」場合
$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 {
ログイン処理結果を失敗に、
出力ページをログインペー
ジに、出力メッセージを警
告メッセージに設定し、
falseを返す
parent::validate_is_logined();
}
}
そうでない場合、ログイン処理を実行
動作確認
 佐藤さんのアカウントでSNSにログインしましょう。
 ログインIDは「sato」、パスワードは「sato310 」
 掲示板のURL欄に次のURLを投稿しましょう
http://localhost/Web/Scenario113/EditSoft/sns.p
hp?page=4&public=1
 「不正なリクエストです。」と出力され、佐藤さんの個
人情報公開設定が「非公開」から「公開」にならなけれ
ばOKです。
本日の内容
 クロスサイト・リクエスト・フォージェリ
(CSRF)の脆弱性攻撃体験と脆弱性の修正
 意図しない命令の実行
 不完全な対策
演習テーマ
CSRF
 「不完全な対策」のリンクをクリックしましょう。
CSRFの不完全な対策
 CSRFの対策として、リクエストにトークンを含ませる方
法は有効だが、トークンに規則性がある場合、悪意のある
人に推測され、対策を回避されてしまう可能性がある
演習内容(疑似的な攻撃)
 SNSサイトで利用されるトークンの規則性を発見する
 脆弱性があるウェブサイト
 SNSサイト
演習の進め方
1. Webサイトの挙動を把握する
2. 脆弱性となる箇所を特定する
1.Webサイトの挙動を把握
する
 SNSにログイン後、設定変
更ページに移動し、設定変
更をしましょう。
 IDは「yamada」、パ
スーワードは
「P@ssword」
 攻撃者として、利用できる
ことを考える。
 設定変更ページのソースを
確認しましょう。
2.脆弱性となる箇所を特定す
る
 トークンの規則性を確認できましたか?
 <input type="hidden" name="secret" value="1000"
/>
 トークンは連番で割り当てられます。
 ログインし直すと、secretパラメータの値がインクリ
メントされることが確認できます。
対処方法
 原因
 ログインしたユーザからのリクエストに対して発行す
るトークンが規則性を有するため、トークンを推測さ
れてしまい、不正な操作が実行されてしまう
 対処方法
 CSRFの対策として秘密情報を使用する場合は、安全な
疑似乱数を用いて、第三者に予測困難なトークンを利
用する
演習内容(脆弱性の修正)
 SNSサイトのCSRFの脆弱性となるコードを特定し、安
全な擬似乱数により生成したトークンを使用する実装を
行う
修正プログラム
 SNSサイト
 sns.php
 sns114.class.php
sns114.class.ph
pの処理内容を
ゲット
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) {
トークン検索のSQL
を準備し、実行
throw new Exception((__LINE__ . json_encode($this->_db->errorInfo())),
LogUtil::ERROR_DB_EXECUTE);
}
(次ページに続く)
1.処理内容の確認
(つづき)
トークン更新のSQL
文を準備し実行
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;
セット
}
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()]);
今回はセッションIDで使われている
return $this;
疑似乱数をそのまま利用している。
}
(本来はNG)
動作確認
 SNSにログインし、設定変更ページに移動しましょう。
 ログインIDは「yamada」、パスワードは
「P@ssword 」
 ソースコードを表示し、トークンが疑似乱数に変わって
いればOKです。
CSRFの要点
 CSRFの脆弱性の原因は、ユーザが意図したリクエ
ストであるかどうかを識別する仕組みを持たない
ことです。
 Webページを出力する際には、第三者に予測困難
なトークンをhiddenパラメータに挿入するように
しましょう。そして、ユーザからのリクエストを
受けた際には、hiddenパラメータの値と元のトー
クンを比較し、一致しない場合は処理を行わない
ようにしましょう。
課題
 実際に、CSRFの脆弱性を突かれて被害を受
けた事件を調査し、1)被害の内容と時期、
2)攻撃方法とその攻撃で可能だったこと、
3)脆弱性が生まれた原因、4)実施され
た対策について、参考にした情報源などを
引用しつつ簡潔にまとめてください。
 本講義の感想、要望、質問などあれば、書
いてください。
https://moodle.artsci.kyushu-u.ac.jp/course/view.php?id=2661