セッションIDの不正取得対策

サイバーセキュリティ演習
― Webセキュリティ基礎&実践―
10.セッションIDの不正取得対策
講義内容
1. 2*. Webサイトの仕組みとWebプログラミング基礎
3.4.5*. 不正スクリプトの実行対策
6.7*.
データベースの不正操作対策
8 *.
システムの不正操作対策とHTTPレスポンスの改竄対策
9 *.
偽リクエストによるサービスの不正利用対策
10*.
セッションIDの不正取得対策
11.
総合演習(1)
12*.
公開ディレクトリの不正横断対策と認証認可制御の欠落
による不正アクセス対策とエラーメッセージからの情報
漏えい対策
13.
総合演習(2)
14.
総合演習(3)
15.
学期末試験
※*はレポートがある回になります。
本日の内容
 セッション管理の不備の脆弱性攻撃体験と
脆弱性の修正
 セッションIDの固定化
 セッションIDの推測
セッションとは
 セッションは一連のインタラクティブな操作のこと。
 典型的には、ログインしてからログアウトするまでが
一つのセッション。
5
セッションIDとCookie
 セッションIDは、ログインID、パスワード、認証状態やアクセ
ス履歴といったセッション情報の識別子
 Cookieは、ブラウザにセッションIDを一時的に保存する仕組み
オンラインショップにアクセス
ID yamada
PW ********
ログインページを送付
IDとパスワード入力
ユーザ専用ページを送付
セッションIDを通知
クライアント
購入ページにアクセス
次回から、ブラウ
ザはCookieに保
存したセッション
IDを送信
購入ページを送信
ログアウト
ログアウト後のページを送付
DBで管理する
ID、パスワード
を参照し認証
DB
Webサーバ
セッションIDをもと
に個人を特定
セッション情報は一
定期間保持
セッションIDを運ぶ手段
URL
HTTPヘッダ
HTTPボディ
セッションハイジャック
 ログイン中の利用者のセッションIDを不正に取得する攻
撃方法
 セッションIDの漏えい
ネットワークの盗聴やXSSなどの脆弱性攻撃により、セッ
ションIDを盗み出す
 セッションIDの固定化
セッションIDを盗み出す代わりに、セッションIDを利用者の
ブラウザに設定する。攻撃者は利用者のセッションIDを
「知っている」状態となる。
 セッションIDの推測
連番や日時・ユーザIDなどをもとにしたセッションIDの利用
により、第三者がセッションIDを容易に推測する。
セッションIDの漏えいの事例1
 セッションIDのURL埋め込みによる漏えい
なぜ、セッションIDがURLに埋
め込まれる?
 PHPの設定ファイル(php.ini) で設定されているため。
 session.use_cookies
セッションIDの保存にCookieを使う(デフォルトはON)
 session.use_cookies
セッションIDをCookieのみに保存する(デフォルトはON)
 session.use_trans_sid
URLにセッションIDを自動埋め込みする(デフォルトはOFF)
 セッションIDがURLに埋め込みになる条件
 session.use_trans_sidがONの場合
 session.use_trans_sidがOFFでも、
session.use_cookiesがON、session.use_cookiesがOFFで
Cookieが使えない場合
(携帯電話向けWebアプリケーションなど)
セッションIDの漏えいの事例2
 Cookieのセキュア属性不備による漏えい
脆弱性があるオンライン
ショップWebサイト
ログイン中
SSL(通信暗号化)
https://xxx.co.jp/443
クライアント
②第三者のWebサーバに
アクセスして、罠のURL
をクリック
Webサーバ
③クリックによりhttpに変更
したリクエストが送信される
http://xxx.co.jp/443
第三者の
Webサーバ
攻撃者
①事前に、罠の
URLを張り付ける
DB
④HTTPリクエストの
Cookieを盗聴
Cookieのセキュア属性
 HTTPS通信のみCookieを利用する場合に指定するオプ
ション
 Cookieにsecure属性を設定していない場合は、HTTP通
信でもCookieにセッションIDが保持されるため、
HTTPS通信で発行したCookieでもHTTP通信の盗聴によ
りCookie情報を不正に取得されてしまう可能性がある。
オンラインショッピングなどHTTP(商品カテゴリページ)と
HTTPS(購入ページ)が混在する場合はオプションの指定が
難しい
 Set-Cookieヘッダの文法
 Set-Cookie: [Cookie名=値]; [expires=期限];
[path=Cookieが使用されるURLのパス名];
[domain=Webサーバ名]; secure
参考:通信データキャプチャソフト
 Fiddler
 オープンソースのWebデバッグツール
 HTTP,HTTPSの通信データの閲覧、書き換えが可能
 Windows OSに対応
 Wireshark
 オープンソースの通信データ解析ツール
 HTTP, HTTPSだけでなくTCP, UDPなど800以上の通信
データの閲覧が可能
 Windows, Mac, LinuxなどのOSに対応
セッション管理不備の一般的な
影響
 ログインユーザのみが利用可能なサービスを悪用される
 不正送金、商品購入、退会処理など。
 ログインユーザのみが編集可能な情報を改ざん、新規登
録がされる
 各種設定の変更(管理者画面、パスワードなど)、掲示板への
不適切な書き込みなど。
 ログインユーザのみが閲覧可能な情報を閲覧される
 非公開の個人情報を不正閲覧、ウェブメールを不正閲覧、コ
ミュニティ会員専用の掲示板を不正閲覧など。
セッションIDの漏えい対策
 セッションIDの漏えいの原因は、セッションIDがURLに
格納されていることです。 またCookieのセキュア属
性が無効になっていることです。
 セッションIDは、URLパラメータに埋め込むのではなく、
Cookieに格納するか、POSTメソッドのhiddenパラ
メータに格納する方法で受け渡しするようにしましょ
う。また、特別な理由が無い限り、php.iniでセッショ
ンIDをURLパラメータに格納する組み合わせの設定には
しないようにしましょう。
 HTTPS通信で利用するCookieは必ずsecure属性を設定
するようにしましょう。 secure属性が設定できない場
合はトークンを用いるようにしましょう。また、HTTP
通信でCookieを利用する場合は、HTTPS通信で発行す
るCookieとは別のものを発行するようにしましょう。
本日の内容
 セッション管理の不備の脆弱性攻撃体験と
脆弱性の修正
 セッションIDの固定化
 セッションIDの推測
演習テーマ
セッション管理の不備
 「セッションIDの固定化」のリンクをクリックしま
しょう。
セッションIDの固定化の攻撃例1
 セッションIDを使い続けている場合の攻撃事例
ID yamada
PW ********
③罠のURL
をクリック
クライアント
⑥再ログイン
ログイン中
SSL(通信暗号化)
⑤認証再要求
HTTPヘッ
ダインジェ
クション
DB
Webサーバ
④無意識に攻撃者のセッションID
によるリクエストが送信される
①ログインしてセッションIDを取得
攻撃者
②フィッシング
メールを送付
⑦利用者になりすまして不正操作
セッションIDの固定化の攻撃例2
ID18 yamada
PW ********
⑥再ログイン
⑤再認証が求められ、レスポンスに含
まれる不正スクリプトが実行される
不正スクリ
プト実行
(XSS)
クライアント
③第三者のWebサーバに
アクセスした時に、罠の
URLをクリックしてしまう
ログイン中
SSL(通信暗号化)
DB
Webサーバ
④クリックにより
意図しないリクエ
ストが送信される
第三者の
①ログインして
②事前に、罠の Webサーバ セッションIDを
取得
URLを張り付ける
攻撃者
⑦利用者になりすまして不正操作
演習内容(疑似的な攻撃)
 掲示板に罠のリンクを張り付け、XSSによってセッショ
ンIDを固定化する
 第三者のウェブサイト
 掲示板
 脆弱性がある
ウェブサイト
 ネット証券
演習の進め方
1. 2種類のブラウザを用意する
2. Webサイトの挙動を把握する
3. 脆弱性となる箇所を特定する
4. セッションIDを固定化するスクリプトを考える
5. 罠のリンクを考える
6. 罠のリンクを掲示板に投稿する
7. 標的の利用者になりすましが可能なことを確認す
る。
1.2種類のブラウザを用意す
る
 正規のユーザ用と攻撃者用の2種類のブラウザが必要になり
ますので用意しましょう。
資料上は正規のユー
ザ用のブラウザをIE
とします。
資料上は攻撃者のブ
ラウザをChromeと
します。
2.Webサイトの挙動を把握
する
 ネット証券に攻撃者のアカウ
ントでログインして、いろい
ろ操作をしてみましょう。
 IDは「sato」、パスーワード
は「sato310」
 ログインボタンを押すと擬似
ウェブデバッガが動作し、リ
クエストのデータを確認でき
ます。
 佐藤さんであることを確認し
ましょう。
 Cookieの値を確認しましょう。
 Submitボタンを押すとログイ
ンできます。
3.脆弱性となる箇所を特定す
る
 <script>のタグをそれぞれの入力フォームに入力して
投稿してみましょう。
 エスケープ処理がされておらず、ソースコードに
<script>タグが追記される箇所はどこでしょうか?
4.セッションIDを固定化するスク
リプトを考える
 セッションIDを固定化するスクリプトを考えましょう。
 DOMベースのCookieの設定方法は以下の通りです。
<script>document.cookie=“ ”</script>
 Set-Cookieヘッダの文法は以下の通りです。
Set-Cookie: [Cookie名=値]; [expires=期限];
[path=Cookieが使用されるURLのパス名];
[domain=Webサーバ名]; secure
Cookie名は「PHPSESSID」としましょう。
Cookieが使用されるURLのパスは「/」としましょう。
 セッションIDを固定化するスクリプトは以下になります。
 <script>document.cookie=“PHPSESSID=gll3n7kettiscjlj
bju47o0b23;path=/"</script>
5.罠のリンクを考える
 ネット証券のお問い合わせには、次のURL文が作成されます。
http://localhost/Web/Scenario127/VulSoft/bon
d.php?page=9&from_name=a&mail=b%40xxx.
co.jp&comment=ccc
%40はURL上では@を意味する
 セッションIDを固定化するスクリプトを含むURLを考えま
しょう。
 スクリプトを含めるURL上のパラメータは「mail」です。
 http://localhost/Web/Scenario127/VulSoft/bond.php?pa
ge=9&mail=<script>document.cookie="PHPSESSID=gll3n7
kettiscjljbju47o0b23;path=/"</script>
6.罠のリンクを掲示板に投稿
する
 罠のリンクをURL欄に入
力し投稿しましょう。
http://localhost/We
b/Scenario127/VulS
oft/bond.php?pag
e=9&mail=<script>d
ocument.cookie="P
HPSESSID=gll3n7ketti
scjljbju47o0b23;pat
h=/"</script>
7.標的の利用者になりすまし
が可能なことを確認する
 一旦、ネット証券の攻撃者のアカウントはログアウ
トしておきましょう。
7.標的の利用者になりすまし
が可能なことを確認する
 ネット証券に正規ユーザのアカ
ウントでログインしましょう。
 IDは「yamada」、パスー
ワードは「P@ssword」
 山田さんであることを確認しま
しょう。
 攻撃者のCookieの値と異なる
ことを確認しましょう。
7.標的の利用者になりすまし
が可能なことを確認する
 罠のリンクをクリックしましょう。
7.標的の利用者になりすまし
が可能なことを確認する
 ネット証券のお問い合わせのエラーページに飛ばさ
れます。株の購入タグをクリックしましょう。
7.標的の利用者になりすまし
が可能なことを確認する
 再度ログインが求められますので、正規ユーザのID
とパスワードでログインし、Cookieの値が攻撃者
のセッションIDになっていることを確認しましょう。
7.標的の利用者になりすまし
が可能なことを確認する
 最後に、攻撃者のIDとパスワードで再度ログイン
して、「Congratulations!!演習の目標を達成しま
した。」と表示され、正規ユーザのアカウントに
なっていたら、OKです。
対処方法
 原因
 ログイン前後で同じセッションIDを使いまわしている
ために、セッションIDが固定化され、なりすましによ
る不正な操作が実行されてしまう
 対処方法
 攻撃者が用意したセッションIDによる不正アクセスを
防ぐために、ログイン認証後にセッションIDの変更を
行う。
 セッションIDの変更ができない場合は、トークンを用い
て正規のリクエストを識別する
演習内容(脆弱性の修正)
 ネット証券サイトのセッションID固定化の脆弱性となる
コードを特定し、ログイン後にセッションIDを再発行
(リフレッシュ)する実装を行う
セッションIDリフレッシュPHP
関数
 session_regenerate_id()
 現在のセッションIDを新しく生成したものと置き換える。
 認証状態などのセッション情報は維持される。
関連付けられた古いセッションを削除する場合は引数に
trueを入れる
 <?php
session_regenerate_id();
$new_sessionid = session_id();
session_start();
?>
修正プログラム
 ネット証券サイト
 Bond.php
bond127.class.phpの処理内容をゲット
ヘッダの設定
メッセージ割り当て
テンプレート表示
 bond127.class.php
ネット証券の内容(データベースのデータ)の初期設定
ログイン処理
お問い合わせ内容送信時の検証処理
攻撃成功判定
脆弱性の修正の手順
 bond127.class.php
 public function login()
1. 処理内容の確認。
2. セッションIDのリフレッシュ機能を追加する箇所の特
定。
3. セッションIDのリフレッシュ機能の実装。
1.処理内容の確認
public function login()
{
$db = $this->get_db();
$param = $this->get_param();
データベース情報、
セッション情報、パ
ラメータ情報を取得
$session = $this->get_session();
$stmt = $db->prepare(parent::LOGIN_SQL);
$stmt->execute(array(parent::ID => $param[parent::ID],
parent::PASSWORD => $param[parent::PASSWORD]));
$user = $stmt->fetch();
(次ページに続く)
アカウント情報をデー
タベースから検索
1.処理内容の確認
(つづき)
データベースにアカウントが存
在する(認証OKの)場合、
ユーザ専用ページ
の設定
if ($user) {
$this->set_session(ScenarioEnvironment::ENV_ID_NAME,
"Web");
$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.セッションIDのリフレッ
シュ機能を追加する箇所の特定
if ($user) {
$this->set_session(ScenarioEnvironment::ENV_ID_NAME,
"Web");
$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;
}
}
3.セッションIDのリフレッ
シュ機能の実装
if ($user) {
session_regenerate_id();
$this->set_session(ScenarioEnvironment::ENV_ID_NAME,
"Web");
$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;
}
}
動作確認
 攻撃者のセッションIDを確認しましょう。
 ログインIDは「sato」、パスワードは「sato310 」
 掲示板のURL欄に次のURLを投稿しましょう
http://localhost/Web/Scenario127/VulSoft/bon
d.php?page=9&mail=<script>document.cooki
e="PHPSESSID=gll3n7kettiscjljbju47o0b23;path=/
"</script>
動作確認
 正規ユーザのブラウザ上で罠のリンクをクリックし
ましょう。
 正規ユーザのIDとパスワードでログインしましょう。
 Cookieの値が攻撃者のセッションIDにならなければ
OKです。
セッションID固定化の要点
 セッションID固定化の脆弱性の原因は、ログイン前後で
同じセッションIDを使いまわしていることです。
 セッションハイジャックを防ぐために、ログイン認証後
にセッションIDをリフレッシュするようにしましょう。
なお、セッションIDの変更ができない場合は、第三者に
予測困難なトークンを用いるようにして正規のリクエス
トを識別できるようにしましょう。
本日の内容
 セッション管理の不備の脆弱性攻撃体験と
脆弱性の修正
 セッションIDの固定化
 セッションIDの推測
演習テーマ
セッション管理の不備
 「セッションIDの推測」のリンクをクリックしましょ
う。
セッションIDの推測の事例
 セッションIDが連番で生成されている場合、
ありがちなセッションIDの生成
規則
演習内容(疑似的な攻撃)
 オンラインバンキングで利用されるセッションIDの規則
性を発見する
 脆弱性があるウェブサイト
 オンラインバンキング
演習の進め方
1. Webサイトの挙動を把握する
2. 脆弱性となる箇所を特定する
1.Webサイトの挙動を把握
する
 オンラインバンキングにロ
グインを繰り返し、セッ
ションIDの変化を確認しま
しょう。
 IDは「yamada」、パ
スーワードは
「P@ssword」
 攻撃者として、利用できる
ことを考える。
 擬似ウェブデバッガの
Cookie値を確認して、
セッションIDの生成規則を
見極めて推測しましょう。
2.脆弱性となる箇所を特定す
る
 セッションIDの規則性を確認できましたか?
 日時を使用して推測してみましょう。
 2015/11/30
 1回目:30121149201558、2回目:30121150201525
 2015/12/1
 1回目:1111253201513、2回目:111125520154
 日+時+月+分+年+秒
 30 12 11 49 2015 58
対処方法
 原因
 ログインしたユーザからのリクエストに対して発行す
るセッションIDが規則性を有するため、推測されてし
まい、不正な操作が実行されてしまう
 対処方法
 セッションIDの推測の対策としては、PHPのセッショ
ンID生成機能を用いて、第三者に予測困難なセッショ
ンIDを利用する
演習内容(脆弱性の修正)
 オンラインバンキングのセッションID推測の脆弱性とな
るコードを特定し、推測が困難なセッションIDを使用す
る実装を行う
セッションID生成のPHP関数
 session_id()
 自動的に疑似乱数を設定する。現在のセッション ID を
取得 または指定のセッションIDの設定も可能。
 <?php
$sessionid = session_id();
session_start();
?>
 mcrypt関数
 暗号理論的に安全な疑似乱数を生成することが可能。
セッション管理機構を自作しなければいけない場合は、
mcrypt関数を利用しましょう。
修正プログラム
 オンラインバンキング
 bank.php
bank128.class.phpの処理内容をゲット
メッセージ割り当て
ヘッダの設定
テンプレート表示
 bank128.class.php
オンラインバンキングの内容(データベースのデータ)
の初期設定
ログイン処理
ログアウト処理
脆弱性の修正の手順
 bank128.class.php
 public function login()
1. 処理内容の確認。
2. セッションIDを割り当る箇所の特定。
3. 推測困難なセッションID割り当ての実装。
1.処理内容の確認
public function login()
{
$user = parent::login();
if ($user) {
$dtoken = getdate();
データベースにアカウントが存
在する(認証OKの)場合、
日時情報を取得
$stoken =
$dtoken['mday'].$dtoken['hours'].$dtoken['mon'].$dtoken['minutes'].$dtoken['year'].$dtoken['
seconds'];
setcookie('SESSIONID', $stoken, time()+300, '/Web/Scenario128/EditSoft');
return true;
} else {
$this->proc_logout();
300秒の有効期限付きセッションID
をWebページに設定
$this->set_content(parent::WARNING3, true);
$this->set_content(parent::WARNING4, false);
return false;
}
}
2.セッションIDを割り当る箇
所の特定
public function login()
{
$user = parent::login();
if ($user) {
$dtoken = getdate();
$stoken =
$dtoken['mday'].$dtoken['hours'].$dtoken['mon'].$dtoken['minutes'].$dtoken['year'].$dtoken['
seconds'];
setcookie('SESSIONID', $stoken, time()+300, '/Web/Scenario128/EditSoft');
return true;
} else {
$this->proc_logout();
$this->set_content(parent::WARNING3, true);
$this->set_content(parent::WARNING4, false);
return false;
}
}
3.推測困難なセッションID割
り当ての実装
public function login()
{
$user = parent::login();
if ($user) {
$dtoken = getdate();
$stoken = session_id():
setcookie('SESSIONID', $stoken, time()+300, '/Web/Scenario128/EditSoft');
return true;
} else {
$this->proc_logout();
$this->set_content(parent::WARNING3, true);
$this->set_content(parent::WARNING4, false);
return false;
}
}
動作確認
 オンラインバンキングに繰り返しログインしましょう。
 ログインIDは「yamada」、パスワードは
「P@ssword 」
 セッションIDが複雑で規則性が無く推測が困難な疑似乱
数に変わっていればOKです。
セッションID推測の要点
 セッションID推測の脆弱性の原因は、規則性のあるセッ
ションIDを生成し使用していることです。
 セッションハイジャックを防ぐために、PHPのセッショ
ンID生成機能を用いて第三者に推測が困難なセッション
IDを生成しましょう。なお、どうしてもセッション管理
機構を自作しなければいけない場合は、暗号理論的に安
全な疑似乱数を生成するPHPの関数を用いて十分な桁数
のセッションIDを生成するようにしましょう。
課題
 実際に、セッションハイジャックの被害を
受けた事件を調査し、1)被害の内容と時
期、2)攻撃方法とその攻撃で可能だった
こと、3)脆弱性が生まれた原因、4)実
施された対策について、参考にした情報源
などを引用しつつ簡潔にまとめてください。
 本講義の感想、要望、質問などあれば、書
いてください。
https://moodle.artsci.kyushu-u.ac.jp/course/view.php?id=2661