More Related Content
Similar to 徳丸本に載っていないWebアプリケーションセキュリティ (20)
More from Hiroshi Tokumaru (20)
徳丸本に載っていないWebアプリケーションセキュリティ
- 3. 徳丸浩の自己紹介
• 経歴
– 1985年 京セラ株式会社入社
– 1995年 京セラコミュニケーションシステム株式会社(KCCS)に出向・転籍
– 2008年 KCCS退職、HASHコンサルティング株式会社設立
• 経験したこと
– 京セラ入社当時はCAD、計算幾何学、数値シミュレーションなどを担当
– その後、企業向けパッケージソフトの企画・開発・事業化を担当
– 1999年から、携帯電話向けインフラ、プラットフォームの企画・開発を担当
Webアプリケーションのセキュリティ問題に直面、研究、社内展開、寄稿など
を開始
– 2004年にKCCS社内ベンチャーとしてWebアプリケーションセキュリティ事業を立
ち上げ
• その他
– 1990年にPascalコンパイラをCabezonを開発、オープンソースで公開
「大学時代のPascal演習がCabezonでした」という方にお目にかかることも
• 現在
– HASHコンサルティング株式会社 代表 http://www.hash-c.co.jp/
– 京セラコミュニケーションシステム株式会社 技術顧問
http://www.kccs.co.jp/security/
– 独立行政法人情報処理推進機構2012 HASH Consulting Corp. http://www.ipa.go.jp/security/
Copyright © 非常勤研究員 3
- 4. 本を書きました
2011年3月5日初版第1刷
2011年12月13日 初版第5刷
Copyright © 2012 HASH Consulting Corp. 4
- 8. Demoの構成
ブラウザ OpenPNE 3.4.12.1
PROXY
squid PHP/MySQL
Ubuntu 10.04LTS
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|?) 0 0% 0
refresh_pattern (Release|Package(.gz)*)$ 0 20% 2880
refresh_pattern . 1440 20% 4320 override-lastmod
※デモ環境では、WebサーバーとProxyサーバーは同一VM上で稼
働 Copyright © 2012 HASH Consulting Corp. 8
- 9. サトーさん タナカさん
Demo
Copyright © 2012 HASH Consulting Corp. 9
- 10. ブラウザキャッシュのデモ
デフォルト
Copyright © 2012 HASH Consulting Corp. 10
- 11. そもそもこれは脆弱性なのか?
• PROXY設定の問題ではないのか?
– PROXY設定の問題とは言い切れない
– squidの標準的な機能の範囲である
– PROXY設定の基準が明確にあるわけではない
• RFC2616 13.4 Response Cacheability
– (原文)A response received with a status code of 200, 203, 206,
300, 301 or 410 MAY be stored by a cache and used in reply to
a subsequent request, subject to the expiration mechanism,
unless a cache-control directive prohibits caching.
– (日本語訳)200, 203, 206, 300, 301, 410 のステータスコードと
共に受信されたレスポンスは、cache-control 指示子がキャッ
シングを禁止していなければ、キャッシュによって保存され、
以降のリクエストへの応答に使用され、期限メカニズムに従う
事ができる。
http://tools.ietf.org/html/rfc2616#section-13.4
http://www.studyinghttp.net/cgi-bin/rfc.cgi?2616#Sec13.1.3 より引用
Copyright © 2012 HASH Consulting Corp. 11
- 13. 対策
• HTTPレスポンスヘッダで「キャッシュを禁止するヘッダ」を応
答することが根本対策
• セキュアプログラミング講座には…
1. Cache-Control: private
Webサーバから返されるコンテンツがただ一人のユーザのためのものであること
を示す。このコンテンツは、複数のユーザが共有されるキャッシュに記録されるべ
きではないことを表している。ただし、これは、一人のユーザのみが利用するキャ
ッシュ(ブラウザのキャッシュ等)への記録を禁じるものではない。Cache-
Control: private のみが指定されている場合、何らかのキャッシュへの記録が行わ
れるおそれがある。
2. Cache-Control: no-store
このヘッダは、Webサーバから返されてくるコンテンツをキャッシュに記録する
な、という指示である。
3. Cache-Control: no-cache
一見「キャッシュを使うな」のように見えるこのヘッダが実際に意味するところ
は少々ニュアンスが異なる。このヘッダの意味は、いちどキャッシュに記録された
コンテンツは、現在でも有効か否かを本来のWebサーバに問い合わせて確認がと
れない限り再利用してはならない、という意味である。
4. Cache-Control: must-revalidate
このヘッダは、キャッシュに記録されているコンテンツが現在も有効であるか否
かをWebサーバに必ず問い合わせよ、という指示である。
http://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/405.html より引用 13
- 14. 対策(続き)
• HTTP/1.0対策として
– Pragma: no-cache
– 非標準の方法であり、確実なものではない
• その他の手法
– 「現場の知恵」としてURL(クエリ文字列)にランダムな数字
を付加することが行われる
• 例: http://example.jp/private.php?rand=8314329428479210
– HTTPSにする
• 通常のPROXYはHTTPSのメッセージをキャッシュしない(できない)
• リバースPROXY、ブラウザはキャッシュする可能性があるので過信し
ないこと
– テストする
• 別ユーザ or 非ログイン状態で、同じURLをアクセスする
Copyright © 2012 HASH Consulting Corp. 14
- 18. クリックジャッキングの対策
• クリックジャッキングの影響はクロスサイト・リクエス
トフォージェリ(CSRF)と同等
– ユーザの意識とは無関係に、ユーザの権限で操作が行われる
• クリックジャッキングされると困るページには、X-
FRAME-OPTIONSヘッダを指定する(徳丸本P63)
– frame/iframeを禁止して良い場合
header('X-FRAME-OPTIONS', 'DENY');
– frame/iframeを禁止できないが単一ホストの場合
header('X-FRAME-OPTIONS', 'SAMEORIGIN');
• CSRF対策のトークン発行しているページが対象となる
• メタ要素によるX-FRAME-OPTIONS指定は無効です。
徳丸本第3刷までの記述は間違いです(_ _)
Copyright © 2012 HASH Consulting Corp. 18
- 19. CSRF対策との関係
入力/確認画面 更新・実行画面
更新してよろしいですか?
更新しました
実行 トップへ
•トークン埋め込み •トークン確認
•X-FRAME-OPTIONS
ヘッダ出力
トークン埋め込みしている画面に、X-FRAME-
OPTIONS
ヘッダを出力する(全ての画面で出力しても良い)
Copyright © 2012 HASH Consulting Corp. 19
- 23. とある入門書のサンプル
Copyright © 2012 HASH Consulting Corp. 23
よくわかるJavaScriptの教科書、たにぐちまこと著、2012 P228より引用
- 31. 脆弱性の原因と対策
• htmlメソッドによりHTMLテキストを設定しているにも
関わらず、データをHTMLエスケープしていない
• ただし、元文献は固定テキストなので、必ずしも脆弱性
とは言えない
• HTMLエスケープするタイミングは、以下の候補がある
– ブラウザでレンダリングする箇所
– JSONを組み立てる段階で、あらかじめHTMLエスケープして
おく
Copyright © 2012 HASH Consulting Corp. 31
- 34. JSON作成も自前で
<?php
$image = 'img/1.jpg';
$image_big = 'img/1_big.jpg';
$caption = 'キャプション2';
$a = '[{"image":"' . $image . '","image_big":"' .
$image_big . '","caption":"' . $caption . '"}]';
echo $a;
生成されるJSON
[{"image":"img/1.jpg","image_big":"img/1_b
ig.jpg","caption":"キャプション2 "}]
Copyright © 2012 HASH Consulting Corp. 34
- 36. データにJavaScriptを入れてみる
<?php
$image = 'img/1.jpg';
$image_big = 'img/1_big.jpg';
$caption = 'キャプション2x"+alert("1")+"';
$a = '[{"image":"' . $image . '","image_big":"' .
$image_big . '","caption":"' . $caption . '"}]';
echo $a;
生成されるJSON
[{"image":"img/1.jpg","image_big":
"img/1_big.jpg","caption":
"キャプション2x"+alert("1")+""}]
Copyright © 2012 HASH Consulting Corp. 36
- 45. Copyright © 2012 HASH Consulting Corp. 45
http://d.hatena.ne.jp/hasegawayosuke/20110106/p1 より引用
- 46. Copyright © 2012 HASH Consulting Corp. 46
http://d.hatena.ne.jp/hasegawayosuke/20110106/p1 より引用
- 47. X-Content-Type-Options: nosniff を入れてみる
生成される
JSON
X-Content-Type-Options: nosniff
Content-Length: 125
Content-Type: application/json; charset=utf8
[{"image":"img/1.jpg","image_big":"img/1_b
ig.jpg","caption":"u30adu30e3u30d7u30b7
u30e7u30f31<body onload=alert(1)>"}]
Copyright © 2012 HASH Consulting Corp. 47
- 51. 対策
• 必須対策(全ブラウザ共通)
– レスポンスがブラウザによりtext/htmlと解釈されないようにす
る
X-Content-Type-Options: nosniff
Content-Type: application/json; charset=utf8
• IE6,7対策
– IE7以前をサポートしない
– ブラウザからの直接リクエストを受け付けない
– 「<」、「>」などもエスケープする
Copyright © 2012 HASH Consulting Corp. 51
- 60. Androidの標準ブラウザでハイジャック成功
Xperia ARC(SO-01C)
Android 2.3.4 でキャプチャ
Galaxy Nexus
Android 4.0.3では取得できず
Copyright © 2012 HASH Consulting Corp. 60
- 61. 対策
• script要素からのリクエストにはレスポンスを返さない
ようにする
– XMLHttpRequestからのリクエストに特別なヘッダを入れてお
き、JSON提供側でチェックするなど
Jqueryの以下のヘッダを使っても良いかも
X-Requested-With: XMLHttpRequest
– POSTにのみ応答(個人的には好みません)
• JSONデータを、JavaScriptとして実行できない形にする
– 1行目に for(;;) ; を置く(個人的には好みません)
– JSONデータをJavaScriptとして実行できない形にする(同
上)
• JSONハイジャック可能なブラウザを使わない(利用者
側でとれる対策)
Copyright © 2012 HASH Consulting Corp. 61
- 67. 作ってみた
// トレードするカードのidと新オーナーのidがパラメータ
$item_id = (int)$_GET['item_id'];
$newowner = (int)$_GET['newowner'];
// カード情報を取得
$stmt = $pdo->query(
"SELECT * FROM cards WHERE item_id=$item_id");
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$kind = $row['kind'];
$owner_id = $row['owner_id'];
// トレード後のカードを作成
$stmt = $pdo->exec("INSERT INTO cards VALUES (NULL, $kind,".
"$newowner, $item_id, $owner_id, NOW())");
// 元のカードを削除
$stmt = $pdo->exec(
"DELETE FROM cards WHERE item_id= $item_id ");
※デモスクリプトはプレースホルダをちゃんと使っています!
Copyright © 2012 HASH Consulting Corp. 67
- 70. 対策
• トランザクションを使う
– PDOの場合は、begeinTransaction ~ commit / rollbackの間
• ロック(排他制御)
– SELECT … FOR UPDATE など
• 上記の両方が必須
– トランザクションを使うだけでは排他制御にならない場合が多
い
厳密にはDB依存 および モードに依存
• 「クリティカルセクション」に注意
– このスクリプトの場合は、SELECT ~ DELETE FROMまでは
クリティカルセクションであり、同一カードIDについては並行
動作してはいけない
• ちゃんとRDBを基礎から勉強しよう
Copyright © 2012 HASH Consulting Corp. 70
- 71. トランザクションと行ロックで対策
try {
$pdo->beginTransaction();
$item_id = (int)$_GET['item_id'];
$stmt = $pdo->query(
"SELECT * FROM cards WHERE item_id=$item_id FOR UPDATE");
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (! $row) throw new DataNotFoundException();
$kind = $row['kind'];
$owner_id = $row['owner_id'];
$stmt = $pdo->exec("INSERT INTO cards VALUES (NULL, $kind,".
"$newowner, $item_id, $owner_id, NOW())");
$stmt = $pdo->exec(
"DELETE FROM cards WHERE item_id=$item_id");
$pdo->commit();
} catch (DataNotFoundException $e) {
$pdo->rollback();
} catch (Exception $e) {
// ……
※上記は概要でありデモスクリプトはプレースホルダをちゃんと使っています!
Copyright © 2012 HASH Consulting Corp. 71
- 73. トランザクションを難しくする要因
• NoSQL
• Memcached
• データベースのパーティショニング、シャーディング
• データベースのレプリケーション
• LDAP、ファイル等トランザクション非対応のストレー
ジ
• …
• 完全なロールバックが難しい場合でも、排他制御だけな
ら比較的容易に実装できる場合がある
Copyright © 2012 HASH Consulting Corp. 73
- 75. Thank you!
Copyright © 2012 HASH Consulting Corp. 75