ウェブ・セキュリティ基礎試験(徳丸基礎試験)②
徳丸基礎試験勉強まとめ②
「体系的に学ぶ 安全なWebアプリケーションの作り方 第2版」の3章を自分なりにまとめる
アドバイスや間違い指摘など歓迎です
3章「Webセキュリティの基礎 ~ HTTP、セッション管理、同一オリジンポリシー」
3.1 HTTPとセッション管理
HTTPをなぜ学ぶ?
WebアプリケーションはHTTPでデータのやり取りをする
HTTPの仕組みを理解することが脆弱性の理解につながる
HTTPのデータの中身は?
-
用語「HTTPメッセージ」
HTTPリクエスト(リクエストメッセージ) + HTTPレスポンス(レスポンスメッセージ) -
用語「リクエストライン」
リクエストメッセージの1行目のこと- メソッド: GETの部分。POSTやHEADなどがある
- URL(URI): /blog/index.phpの部分
- プロトコルバージョン: HTTP/1.1の部分
GET /blog/index.php HTTP/1.1
-
用語「リクエストヘッダ」
リクエストメッセージの2行目以降~空白行までのこと
必須のヘッダはHost(送信先ホスト名 + ポート番号)だけ
代表的なものは以下- Referer: リンク元のURL(セキュリティの役に立つことも。ただしOWASP ZAPなどで改ざん可能)
- Content-Length: ボディのバイト数
- Content-Type: MIMEタイプ(text/html, application/jsonなど)
-
用語「リクエストメッセージボディ」
リクエストヘッダの空白行以降のこと
POSTメソッドのデータなどが入る
Content-Type未指定だとapplication/x-www-form-urlencodedになる
パーセントエンコーディングされる -
用語「パーセントエンコーディング」
URLで特別な意味を持つ文字の変換
UTF-8では
あ → %E3%81%82 -
用語「ステータスライン」
レスポンスメッセージの1行目のこと
処理結果のステータスを表示する- プロトコルバージョン: HTTP/1.1の部分
- ステータスコード: 200の部分
- テキストフレーズ: OKの部分
HTTP/1.1 200 OK
-
用語「レスポンスヘッダ」
レスポンスメッセージの2行目以降~空白行までのこと
代表的なものは以下- Content-Length: ボディのバイト数
- Content-Type: MIMEタイプ(text/html, application/jsonなど)
-
用語「レスポンスメッセージボディ」
レスポンスヘッダの空白行以降のこと -
用語「Basic認証」
demo: http://ait-sample.list.jp/rtcp/p05-auth/index.html
HTTP認証の1つでIDとパスワードによる認証(AuthorizationヘッダにIDとパスワード記載)
認証が必要なページは下記のようなステータスライン&ヘッダになる
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Hoge Hoge"
-
用語「ステートレス」
HTTPはクライアントの現在の状態を覚えない設計になっていること
FTPなどはステートフル
このため、Basic認証では毎回IDとパスワードが要求される
2回目以降はブラウザが自動的にAuthorizationヘッダ付与してくれているため、見かけ上ステートフルに見える -
用語「hiddenパラメータ」
- デメリット: 利用者自身から書き換え可能 => 利用者から書き換えられたくない場合はセッション変数を使用すること!!
- メリット: 情報漏洩や第三者からの書き換えに対しては堅牢
クッキーやセッション変数はなぜいるの?
HTTP認証を使う場合はブラウザがIDとパスワードを覚えてくれる
でも、下記みたいな認証画面は嫌だな、、、自分でログイン画面使いたい!
って場合はクッキーやセッション変数を使用して認証状態を覚えておく必要がある
クッキーはどんな仕組み?
- レスポンスヘッダーにSet-Cookieが入っているレスポンス取得
サーバー君「ブラウザさん、このクッキー覚えてね、あなたの整理番号です」
Set-Cookie: PHPSESSID=XXX; path=/
- その後ブラウザからのリクエストは、リクエストヘッダーにCookieがセットされて送信される
ブラウザさん「サーバー君、覚えたクッキー(整理番号)を毎回送るね」
Cookie: PHPSESSID=XXX
-
用語「クッキー属性」
上記の「path=/」もクッキー属性のひとつ
その他Domain, Expires, Secure. HttpOnlyがある- Domain: 原則使用しないこと!複数のサーバーにクッキーを送信したい場合使う(サブドメインのみ。別ドメインは指定できるがブラウザ側で無視するようになっている)
- Path: ブラウザがクッキーを送信するURLのディレクトリ
- Expires: クッキーの有効期限。設定しない場合はブラウザ終了まで
- Secure: HTTPS通信のサーバーにのみクッキーを送信する
- HttpOnly: Javascriptからクッキーにアクセスできないようにする
-
用語「クッキーモンスターバグ」
古いブラウザでは、クッキー属性 Domain = co.jp などのクッキーが作れるというバグ。
これができると、amazon.co.jpやyahoo.co.jpにも自由にクッキーが送れてしまう
現在も地域型JPドメイン(xx.kanagawa.jpなど)では古いWindowsブラウザではこの問題が残ってしまっている
※注意点
クッキーそのものには値(パスワードやメールアドレスなど)は入れないように!!
- クッキーが保持できる値の個数や長さには制限がある
- クッキーの値は利用者本人に参照&変更できるので秘密情報保持に向かない
値を入れないなら、クッキーはどうやって使うべき?
整理番号を入れる
※注意点
- セッションIDが推測されやすいものを使わないこと!
001, 002などを使ってしまうと他のユーザーになりすましできる(クッキーの値は利用者本人に参照&変更できる) - 強制されないこと!
1ユーザーに1固定セッションIDにしない。(漏洩した時になりすましされる)
対応として、認証されるごとにセッションIDを変更する - 漏洩しないこと!
3.2 受動的攻撃と同一オリジンポリシー
受動的攻撃って?
- 能動的攻撃
悪者から直接Webサーバーへ攻撃 - 受動的攻撃
- 単純な受動的攻撃
- 利用者が罠サイトにアクセスしマルウェア感染
- 正規サイトを悪用する受動的攻撃
- 正規サイトに悪者が罠を仕込む
- 利用者が正規サイトにアクセスしマルウェア感染
- サイトをまたがった受動的攻撃
- 利用者が罠サイトにアクセスし、仕掛けのあるHTML取得
- そのHTMLから正規サイトにリクエスト送信
- 仕掛けを含むレスポンスを取得(罠サイトを見てるのに正規サイトの情報が取得されてしまう)
- 単純な受動的攻撃
受動的攻撃を防ぐには?
-
同一オリジンポリシー
JSは下記の条件のソースにしかアクセスできない
URLホストが一致、スキーム(httpなどプロトコルが一致)、ポートが一致
(クッキーはドメインだけだったのでJSの方が厳しい条件) -
クロスドメインアクセス
- iframe: src要素にクロスドメインの指定可能だが、クロスドメインを指定した場合は、Javascriptでiframe内の要素にアクセスできない(同一ドメインならアクセスできる)
- img: src要素にクロスドメインの指定可能だが、あまり問題ない
- script: JSONP
- css: CSSXSS攻撃。最新ブラウザを使用することで対応
- formのaction属性: CSRF攻撃
3.3 CORS(Cross-Origin Resource Sharing)
公開APIなど、XMLHttpRequestなどでは別オリジンのサイト間でデータをやり取りしたい!
CORSは別オリジンとのデータ交換をやり取りするための規格
CORSをしない場合どうなるの?
別オリジンのAPIへリクエストすると、「クロスオリジン要求をブロックしました」エラー
CORSはどうやるの?
- Access-Contral-Allow-Originをレスポンスヘッダにつける
別オリジンのAPIへリクエスト(GETメソッドなど)すると、Access-Contral-Allow-Originで指定されたドメインからのリクエストの場合のみ、Access-Contral-Allow-Originヘッダ付きのレスポンスが返ってくる
(クライアント側は特になにもしなくてOK)
Access-Contral-Allow-Origin: https://example.jp
- プリフライトリクエストを行う
クライアント側から別オリジンのAPIへ、事前にプリフライトリクエスト(OPTIONSメソッド)を行い、200レスポンスが返ってきたら、別オリジンのAPIへリクエスト(GETメソッドなど)する
いつプリフライトリクエストが必要なの?
「シンプルなリクエスト」の条件(下記)が満たないリクエストの場合必要
- メソッド: GET, HEAD, POST
- リクエストヘッダ: Accept, Accept-Language, Content-Language, Content-Type
- Content-Typeヘッダ: application/x-www-form-urlencoded, multipart/form-data, text/plain
つまり、下記などの場合はプリフライトリクエストが必要
- メソッド: PATCHを使いたい場合など
- リクエストヘッダ: x-requested-with(XMLHttpRequest使用時によく使うヘッダ)を使いたい場合など
- Content-Typeヘッダ: application/jsonを使いたい場合など
プリフライトリクエストは具体的にどんなもの?
- メソッドに対する許可: PATCHを使いたい場合などの例
リクエスト | レスポンス |
---|---|
Access-Control-Request-Method: PATCH | Access-Control-Allow-Methods: POST, GET, OPTIONS, PATCH |
- ヘッダに対する許可: Content-Typeヘッダにapplication/jsonを使いたい場合など
リクエスト | レスポンス |
---|---|
Access-Control-Request-Headers: Content-Type | Access-Control-Allow-Headers: Content-Type, x-requested-with |
- オリジンに対する許可: 別オリジンAPIにリクエストを送りたいとき
リクエスト | レスポンス |
---|---|
Origin: https://example.jp | Access-Control-Allow-Origin: https://example.jp |
毎回リクエストのたびにプリフライトリクエストするの?
しない。Access-Control-Max-Ageに指定されている有効期限が切れるまではプリフライトリクエストは必要ない
リクエスト | レスポンス |
---|---|
-- | Access-Control-Max-Age: 1728000 |
ヘッダにCookieを使いたい場合どうするの?
リクエスト | レスポンス |
---|---|
XMLHttpRequestのwithCredentioalsプロパティをTrue | Access-Control-Allow-Credentials: true |