Skip to content

Instantly share code, notes, and snippets.

@mesummery
Last active October 1, 2017 04:23
Show Gist options
  • Save mesummery/92d813b6fbb3895026e8c2df971a16ca to your computer and use it in GitHub Desktop.
Save mesummery/92d813b6fbb3895026e8c2df971a16ca to your computer and use it in GitHub Desktop.
Webアプリケーションのセキュリティ
  • Session
  • Cookie
  • JavaScript
  • HTML
  • HTTPメソッド
  • リクエストパラメタやヘッダ情報
  • バリデーションやエスケープ処理を適切に設定

はじめに

👮💭 = セキュリティ関連の項目に登場する。 こいつが現れたら気をつける。


HTTP

リクエストメッセージ

GET /hoge/fuga.php HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg
Accept-Language: ja
// ...

リクエストライン

リクエストメッセージの1行め。

GET /hoge/fuga.php HTTP/1.1
パーツ 内容
GET メソッド
/hoge/fuga.php URI
HTTP/1.1 プロトコルバージョン

レスポンスメッセージ

HTTP/1.1 200 OK
Date: Mon, 10 Jan 2011 05:34:30 GTM
Server: Apache/2.2.14(Ubuntu)
// ...

ステータスライン

HTTP/1.1 200 OK
パーツ 内容
HTTP/1.1 プロトコルバージョン
200 ステータスコード
OK テキストフレーズ

レスポンスヘッダ

レスポンスメッセージの2行め。

  • Content-Length
  • Content-Type

などがある。

メッセージボディ

POSTメソッドのリクエストメッセージで、送信される。

POST /v1/oauth2/token HTTP/1.1
Host: api.example.com
Authorization: Basic Y2xpzW5021kOmNsaWVudF9zZWNyZXQ
Content-Type: application/x-www-form-urlencoded

grant-type=password&username=mafmoff&password=abc&scope=api // リクエストボディ

👮💭 リクエストヘッダのReferer

Refererヘッダ

  • リンク元のURLを示すヘッダ
  • Refererを確認することでアプリケーションが意図した時に遷移を経ていることを確認できる

セキュリティ上の注意

  • URLが秘密情報(セッションIDなど)を含んでいる場合、Referer経由で外部に漏洩して、なりすましに悪用されうる

HTTPメソッド

Name Description
GET リソースの取得
POST リソースの新規登録
PUT 既存リソースの更新
DELETE リソースの削除
PATCH リソースの一部変更
HEAD リソースのメタ情報の取得

👮💭 GETとPOSTの使い分け

POST利用が好ましいケース

  • データ更新などの副作用が伴うリクエスト
  • 秘密情報を送信する
  • 送信するデータの総量が多い

GETだと、以下の可能性があるため。

  • URL上に指定されたパラメータがReferer経由で外部に漏洩する
  • URL上に指定されたパラメータがアクセスログに残る

認証(HTTP認証)

  • Basic認証
  • NTML認証
  • Digest認証 などがある。

Basic認証の流れ

  1. [Browser] ---> [Server]
    GET /hoge/fuga.php HTTP/1.1

  2. [Browser] <--- [Server]
    HTTP/1.1 401 Unauthorized

  3. [Browser] ---> [Server]

GET /hoge/fuga.php HTTP/1.1
Authorization: Basic HogehogeFugafuga
  1. [Browser] <--- [Server]
    HTTP/1.1 200 OK

IDとパスワードはブラウザ上で記憶される。
以降、HOSTへのリクエストには、ブラウザが自動的にAuhtorizationヘッダを付与し、リクエスト毎にIDとパスワードを送出する。

Cookie・Session

セッション管理

  • アプリケーションの状態を覚えておくこと

HTTP認証を使わない場合には、サーバー側で認証状態を保持しておく必要があるため、このセッション管理が必要。

クッキー

  • セッション管理をHTTPで実現する仕組み
  • サーバ側からブラウザに対して「名前 = 変数」の組みを覚えておくように指示するもの
  • 有効期限を設定できるが、未設定のものはブラウザが終了するまで有効
  • 保持できる値の個数や文字列長には制限がある
  • 値は利用者本人に参照・変更できるので、秘密情報の格納には不向き

**TIPS: **クッキーに設定するのは「整理番号」としてのセッションIDで、実際の値はサーバー側で管理する方法が普及している。

クッキーの属性

属性 説明 セキュリティ的に大事
Domain ブラウザがクッキー値を送信するサーバーのドメイン
Path ブラウザがクッキー値を送信するURLのディレクトリ
Expires クッキー値の有効期限、指定しない場合はブラウザの終了まで
Secure SSLの場合のみクッキーを送信
HttpOnly この属性が指定されたクッキーはJavaScriptからはアクセスできない
Domain属性
  • 複数のサーバーに送信されるクッキーを生成したい場合につかう
  • 異なるドメインに対するクッキーは設定できないように制限されている(さもなくば、セッションIDの固定化攻撃として利用されてしまう)
Set-Cookie: x=123; Domain=example.jp
// a.example.jp:クッキーが送信される
// b.example.jp:クッキーが送信される
// a.example.com:クッキーが送信されない

👮💭 Domain属性の設定に注意

  • 未指定状態の場合、クッキーを生成したサーバーのみにクッキーが送られるので安心
  • 不用意に設定すると、クッキーの漏洩につながり脆弱性の原因になる(通常は設定しない)

たとえば、a.example.jpb.example.jpのレンタルサーバのWebサイトがあるとする。a.example.jpサイトが発行するクッキーに以下を設定してしまうと、

Set-Cookie: x=123; Domain=example.jp

b.example.jpにもクッキーが漏洩するということ。

Secure属性
  • この属性がついたクッキーはSSL通信の場合飲みにサーバに送信される
  • この属性がついていないと、常にサーバに送信される
  • クッキーのSSL送信を保証する目的で指定される
HttpOnly属性
  • この属性が指定されたクッキーはJavaScriptからはアクセスできない
  • クロスサイト・スクリプティングでセッションIDを盗み出す攻撃を難しくする
  • これをつけることによる悪影響はないため、常に付与すると良い
session.cookie_httponly = on

👮💭 セッションIDの要件

さもないとなりすまし(セッションハイジャック)に遭う。

  • 第三者がセッションIDを推測できないこと
  • 第三者からセッションIDを強制されないこと
  • 第三者にセッションIDが漏洩しないこと

第三者がセッションIDを推測できないこと

  • 推測できないIDにするために、暗号論的擬似乱数生成器を用いて生成する
  • 自分で自作せず、開発ツールの提供するセッション管理機構を利用すること

**TIPS: **参考 CRYPTREC | CRYPTREC暗号リスト(電子政府推奨暗号リスト)

第三者からセッションIDを強制されないこと

  • 悪いやつが正規利用者にセッションIDを強制することを、セッションIDの固定化攻撃という
  • 防止するには、認証のタイミングでセッションIDを変更すること

第三者にセッションIDが漏洩しないこと

漏洩の原因

  • クッキー発行の際の属性に不備がある
  • ネットワーク的にセッションIDが盗聴される
  • クロスサイト・スクリプティングなどのアプリケーションの脆弱性により漏洩する
  • PHPやブラウザなど、プラットフォームの脆弱性により漏洩する
  • セッションIDをURLに保持している場合は、Refererヘッダから漏洩する
分類 攻撃対象 攻撃手法 脆弱性
セッションIDの推測 アプリケーション セッションIDの推測 自作セッション管理機構の脆弱性
セッションIDの推測 ミドルウェア セッションIDの推測 ミドルウェアの脆弱性
セッションIDの盗み出し アプリケーション XSS XSS脆弱性
セッションIDの盗み出し アプリケーション HTTPヘッダ・インジェクション HTTPヘッダ・インジェクション脆弱性
セッションIDの盗み出し アプリケーション Refererの悪用 URL埋め込みのセッションID
セッションIDの盗み出し ミドルウェア アプリケーションと同様 ミドルウェアの脆弱性
セッションIDの盗み出し ネットワーク ネットワーク盗聴 クッキーのセキュア属性不備ほか
セッションIDの強制 アプリケーション セッションIDの固定化攻撃 セッションIDの固定化脆弱性

👮💭 クッキーモンスター問題

  • 古いブラウザだと、co.jpのクッキーが作れる問題があった
  • 問題のあるブラウザを使っていると、セッションIDの固定化攻撃の影響を受けやすくなる

こうかなぁ~と思う攻撃手法

  1. ユーザAが攻撃者から送られてきた偽装メールを閲覧する。
  2. メールにはamazon.co.jpへのリンクが貼られれている。しかし、実際にはこのリンクは攻撃者のサイトへのリンクである。
  3. ユーザAがそのリンクを閲覧する。
  4. リンク先の攻撃用サイトでは、ユーザAのブラウザの脆弱性を利用して、co.jp用のセッションIDをブラウザのクッキーに付与する。
  5. ユーザAがamazon.co.jpの正規のサイトにログインする際に、攻撃者から付与されたセッションIDを使ってログインする。
  6. 攻撃者はタイミングを見計らって、攻撃に使用したセッションIDを使ってamazon.co.jpのサイトに行く。
  7. 攻撃者はユーザAの認証を使って、悪いことができる。 上記の例は結構極端で、ちゃんとしたサイトなら、ログイン時にセッションIDを変更しているだろうし 当然amazon.co.jpでもこの手法で攻撃者が不正ログインできるわけがないと思います。 ここでは、便宜上amazon.co.jpを利用させていただきました。

本来、trap.example.co.jpサーバ(攻撃者のサイト)がSet-Cookieの際に、Domain=co.jpとしても、 このクッキーはブラウザに無視されますが、脆弱性のある古いブラウザでは、.co.jpドメインのクッキーが作れてしまうという問題が過去にあったようで、これがクッキーモンスター問題と言われているようです。

IE8では地域型ドメインに対するクッキーモンスター問題があるようです。


HTML

  • ステートレス(クライアントの状態を覚えておけない)
  • ブラウザからのリクエストメッセージは改変できる(HTTPレイヤーでは、テキストボックス、ラジオボタンの選択値、hiddenの値も書き換え可能)

hiddenパラメータ

  • <input>タグのtype属性でtype="hidden"を指定すると、 ブラウザ上に表示されない非表示データを送信することができる
  • 完全に隠しきれているわけではなく、HTMLソースを表示すれば見ることができる
  • HTMLがステートレスなので、ここに値を記録しておくことが行われる
<input type="hidden" name="userid" value="12345">
<input type="hidden" name="hyouka" value="good">
<input type="hidden" name="riyu" value="1">

👮💭 hiddenパラメータをつかうメリット

  • 利用者自身から書き換え可能だが、第三者による書き換えや情報漏洩に対してはつよい

**TIPS: **(後述)本人から書き換えられてまずいものは、セッション変数に保存する


入力処理

Webアプリケーションの「入力」では以下を行う。

  1. 文字エンコーディングの検証と変換
  2. 入力検証

入力値検証とアプリケーション要件

入力値検証の基準は、アプリケーションの要件で決まる。
入力値検証自体はセキュリティの向上には直接的にはつながらないが、保険になる。

  • 制御文字のチェック
  • 文字数のチェック(最大文字数の指定)
  • どのパラメータを検証するか(hidden、ラジオボタンのselect要素、HTTPヘッダのReferer)
  • 正規表現チェック

正規表現

'/\A[a-z0-9]{1,5}\z/ui'
要素 説明
\A データの先頭
\z データの末尾
^ 行の先頭
$ 行の末尾
u UTF-8コーディングであることを示す
i 大文字・小文字を区別せずマッチング
[a-zA-Z] 英字
[a-zA-Z0-9] 英数字
{1,5} 量指定子、1文字以上5文字以下
[xxx] xxxの文字にマッチング
[^xxx] xxx以外の文字にマッチング

**TIPS: **iがある時はどちらか大文字・小文字のいずれかのみの指定で良い


いろいろな脆弱性

  • 処理に起因するものと、出力に起因するものがある
  • (ミドルウェアをのぞいて)入力に起因する脆弱性はない
  • 出力関連の脆弱性は「インジェクション」と単語が付きがち
脆弱性名 インターフェース 手口 データの終端
クロスサイト・スクリプティング HTML JavaScriptの注入 <"など
HTTPヘッダ・インジェクション HTTP HTTPレスポンスヘッダの注入 改行
SQLインジェクション SQL SQL命令の注入 'など
OSコマンド・インジェクション シェルスクリプト コマンドの注入 `;
メールヘッダ・インジェクション sendmailコマンド メールヘッダ、本文の注入・改変 改行

👮💭 バイナリセーフとヌルバイト攻撃

バイナリセーフ

  • 入力値がどんなバイト列であっても正しく扱える
  • 値ゼロのバイト(ヌルバイト)が現れても正しく処理できる

ヌルバイト攻撃

  • PHPやその他のスクリプト言語のヌルバイトを扱えない関数を突いた攻撃
  • XSSやディレクトリ・トラバーサルと組み合わせて悪用される

PHPやその他のスクリプト言語では、ヌルバイトを扱えない関数がある。
たとえば、PHPのereg

if (ereg('^[0-9] + $', $hoge)) == FALSE {
  // 整数値じゃない
}

という処理に

http://example.com/43/43-002,php?p=1%00<script>alert('XSS')</script>

というURLを実行してみると%00がヌルバイトのため、ereg関数は、そこで文字列が終わっていると判断する。

👮💭 クロスサイト・スクリプティング(XSS)

  • Webアプリケーション嬢のHTMLやJavaScriptの生成部分で発生する
  • 攻撃用のJavaScriptが、攻撃対象のサイトとは別のサイト(罠サイト)にある場合は、反射型XSS
  • 攻撃用のJavaScriptが、攻撃対象のDBなどに保存されている場合は、持続型XSS

**TIPS: ** 反射型XSSは、入力値をそのまま表示するページで発生することが多い。
**TIPS: ** 持続型XSSは、罠サイトに誘導する手間が省ける。SNSが典型的なターゲットになる。

攻撃手法

クッキーの盗み出し

  • ブラウザ上で悪いスクリプトが実行されることにより、クッキー値を盗まれる
  • 受動的攻撃により別人のクッキー値を盗み出す

例:

  1. 罠サイトのiframe要素の中に脆弱サイトのページを表示する
  2. 脆弱なサイトでXSS攻撃を行い、クッキー値をクエリ文字列に付与して、情報取集ページに遷移
  3. 情報取集ページから受け取ったクッキー値をメールで攻撃者が受け取る

JavaScriptによる攻撃

  • ブラウザ上で悪いスクリプトが実行されることにより、被害者の権限でWebアプリケーションの機能を悪用される
  • Ajaxの流行によりXSSとJavaScriptの組み合わせで攻撃しやすくなっている
  • javascriptスキームによるJavaScriptの起動

画面の書き換え

  • Webサイト上に偽の入力フォームが表示され、フィッシングにより個人情報を盗まれる

例:

  1. </form>タグにより、元サイトのform要素を終了させる
  2. 新しいform要素を開始して、styleを指定しソレっぽく見せて画面を改変する
  3. action要素には罠サイトのURLを指定して、誘導する

原因

  • HTMLの特殊記号(メタ文字)を正しく扱っていない
  • JavaScriptの文字列リテラルのエスケープ摹れ

対策

最低限の対策。

  • メタ文字を正しく扱う
  • HTMLの<&lt;としてエスケープする
  • HMTLの属性値を"で囲み、<""&を文字参照にする
  • JavaScriptの\\\にエスケープかつ、結果をHTMLエスケープする
  • JavaScriptの''\'にエスケープかつ、結果をHTMLエスケープする
  • JavaScriptの""にエスケープかつ、結果をHTMLエスケープする
  • JavaScriptの改行を\nにエスケープかつ、結果をHTMLエスケープする

👮💭 セッションハイジャック

  • セッションIDを生成している箇所で発生する

攻撃手法

Refererを介する

以下の項目を満たすサイトで漏洩しがち。

  • URL埋め込みのセッションIDを使える
  • 外部サイトへのリンクがあるもしくはリンクを利用者が作成可能

例:

  1. URL付きメールを送信して、ターゲットを罠サイトに誘導
  2. まんまと罠サイトを閲覧すると、Webメールに埋め込まれたセッションIDがRefererとして罠サイトに漏洩
  3. 受け取ったRefererを元に、利用者へのなりすましを行う

原因

  • セッションIDがURLに埋め込まれる直接の原因は、不適切な設定やプログラミング

対策

  • セッションIDをURLに埋め込まない
  • セッションIDはクッキーに埋め込む(それでもセッションIDの固定化は発生しうる)

👮💭 セッションIDの固定化

  • セッションIDを外部から強制する

攻撃手法

例:

  1. ターゲットのセッションIDを入手する
  2. ターゲットには、1で入手したセッションIDを矯正する
  3. ターゲットは標的アプリケーションにログインする
  4. 攻撃者は強制したセッションIDをつかって、標的アプリケーションにアクセスする

原因

  • セッションIDが外部から強制できること

対策

  • セッションIDをURLに埋め込まない
  • セッションIDはクッキーに埋め込む(それでもセッションIDの固定化は発生しうる)
  • クッキーモンスター問題のブラウザは使わせない
  • クッキーモンスター問題の発生する地域型ドメインを使わない
  • XSSやHTTPヘッダ・インジェクション、その他クッキー書き換えの脆弱性をなくす
  • 認証後にセッションIDを変更する、できない場合はトークンにとり対策する
  • 認証前には、セッション変数に秘密情報を保存しない

👮💭 セッションIDの要件

対策については、上記項目も参照。

👮💭 HTTPヘッダ・インジェクション

  • すべてのHTTPレスポンスヘッダの出力時に発生しうる脆弱性
  • なりすましや偽ページの表示、キャッシュ汚染などの影響がある

**TIPS: **HTTPレスポンス分散攻撃では、HTTPヘッダ・インジェクションにより、複数のレスポンスを生成して、プロキシサーバに偽のコンテンツをキャッシュさせる。

攻撃手法

  • 任意のクッキー生成
  • 偽画面の表示

原因

  • 外部から指定された改行をそのまま出力してしまうこと

対策

  • HTTPヘッダの出力部分を手作りせずにライブラリやAPIを利用する
  • レスポンスヘッダの文字列中に改行コードが含まれていないかチェックする(含まれていたらエラーとする)
  • クッキー値の改行はパーセントエンコードする
  • 外部からのパラメータをHTTPレスポンスヘッダとして出力しない
  • リダイレクトやクッキー出力を専用のAPIに任せる

👮💭 クッキーの不適切な利用による脆弱性

  • 一般的にはクッキーに保存するにはセッションIDのみで、データ自体はWebサーバのメモリやファイル、DBに保存する
  • クッキーに保存するべき出ないデータを保存していることにより、脆弱性につながる

原因

  • クッキー値はアプリケーションの利用者によって書き換えができる
  • ユーザーIDや権限情報をクッキーに保存している

対策

  • クッキーには、データは保存しない
  • セッションやサーバを跨って情報を保存する必要がある場合(ログイン状態の保持機能など)のみトークンの保存に、クッキーを利用する
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment