- Session
- Cookie
- JavaScript
- HTML
- 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 // リクエストボディ
- リンク元のURLを示すヘッダ
Referer
を確認することでアプリケーションが意図した時に遷移を経ていることを確認できる
- URLが秘密情報(セッションIDなど)を含んでいる場合、
Referer
経由で外部に漏洩して、なりすましに悪用されうる
Name | Description |
---|---|
GET | リソースの取得 |
POST | リソースの新規登録 |
PUT | 既存リソースの更新 |
DELETE | リソースの削除 |
PATCH | リソースの一部変更 |
HEAD | リソースのメタ情報の取得 |
- データ更新などの副作用が伴うリクエスト
- 秘密情報を送信する
- 送信するデータの総量が多い
GETだと、以下の可能性があるため。
- URL上に指定されたパラメータがReferer経由で外部に漏洩する
- URL上に指定されたパラメータがアクセスログに残る
- Basic認証
- NTML認証
- Digest認証 などがある。
-
[Browser] ---> [Server]
GET /hoge/fuga.php HTTP/1.1
-
[Browser] <--- [Server]
HTTP/1.1 401 Unauthorized
-
[Browser] ---> [Server]
GET /hoge/fuga.php HTTP/1.1
Authorization: Basic HogehogeFugafuga
- [Browser] <--- [Server]
HTTP/1.1 200 OK
IDとパスワードはブラウザ上で記憶される。
以降、HOSTへのリクエストには、ブラウザが自動的にAuhtorization
ヘッダを付与し、リクエスト毎にIDとパスワードを送出する。
- アプリケーションの状態を覚えておくこと
HTTP認証を使わない場合には、サーバー側で認証状態を保持しておく必要があるため、このセッション管理が必要。
- セッション管理をHTTPで実現する仕組み
- サーバ側からブラウザに対して「名前 = 変数」の組みを覚えておくように指示するもの
- 有効期限を設定できるが、未設定のものはブラウザが終了するまで有効
- 保持できる値の個数や文字列長には制限がある
- 値は利用者本人に参照・変更できるので、秘密情報の格納には不向き
**TIPS: **クッキーに設定するのは「整理番号」としてのセッションIDで、実際の値はサーバー側で管理する方法が普及している。
属性 | 説明 | セキュリティ的に大事 |
---|---|---|
Domain | ブラウザがクッキー値を送信するサーバーのドメイン | ○ |
Path | ブラウザがクッキー値を送信するURLのディレクトリ | |
Expires | クッキー値の有効期限、指定しない場合はブラウザの終了まで | |
Secure | SSLの場合のみクッキーを送信 | ○ |
HttpOnly | この属性が指定されたクッキーはJavaScriptからはアクセスできない | ○ |
- 複数のサーバーに送信されるクッキーを生成したい場合につかう
- 異なるドメインに対するクッキーは設定できないように制限されている(さもなくば、セッションIDの固定化攻撃として利用されてしまう)
Set-Cookie: x=123; Domain=example.jp
// a.example.jp:クッキーが送信される
// b.example.jp:クッキーが送信される
// a.example.com:クッキーが送信されない
- 未指定状態の場合、クッキーを生成したサーバーのみにクッキーが送られるので安心
- 不用意に設定すると、クッキーの漏洩につながり脆弱性の原因になる(通常は設定しない)
たとえば、a.example.jp
とb.example.jp
のレンタルサーバのWebサイトがあるとする。a.example.jp
サイトが発行するクッキーに以下を設定してしまうと、
Set-Cookie: x=123; Domain=example.jp
b.example.jp
にもクッキーが漏洩するということ。
- この属性がついたクッキーはSSL通信の場合飲みにサーバに送信される
- この属性がついていないと、常にサーバに送信される
- クッキーのSSL送信を保証する目的で指定される
- この属性が指定されたクッキーはJavaScriptからはアクセスできない
- クロスサイト・スクリプティングでセッションIDを盗み出す攻撃を難しくする
- これをつけることによる悪影響はないため、常に付与すると良い
session.cookie_httponly = on
さもないとなりすまし(セッションハイジャック)に遭う。
- 第三者がセッションIDを推測できないこと
- 第三者からセッションIDを強制されないこと
- 第三者にセッションIDが漏洩しないこと
- 推測できないIDにするために、暗号論的擬似乱数生成器を用いて生成する
- 自分で自作せず、開発ツールの提供するセッション管理機構を利用すること
**TIPS: **参考 CRYPTREC | CRYPTREC暗号リスト(電子政府推奨暗号リスト)
- 悪いやつが正規利用者にセッション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の固定化攻撃の影響を受けやすくなる
こうかなぁ~と思う攻撃手法
- ユーザAが攻撃者から送られてきた偽装メールを閲覧する。
- メールにはamazon.co.jpへのリンクが貼られれている。しかし、実際にはこのリンクは攻撃者のサイトへのリンクである。
- ユーザAがそのリンクを閲覧する。
- リンク先の攻撃用サイトでは、ユーザAのブラウザの脆弱性を利用して、co.jp用のセッションIDをブラウザのクッキーに付与する。
- ユーザAがamazon.co.jpの正規のサイトにログインする際に、攻撃者から付与されたセッションIDを使ってログインする。
- 攻撃者はタイミングを見計らって、攻撃に使用したセッションIDを使ってamazon.co.jpのサイトに行く。
- 攻撃者はユーザAの認証を使って、悪いことができる。 上記の例は結構極端で、ちゃんとしたサイトなら、ログイン時にセッションIDを変更しているだろうし 当然amazon.co.jpでもこの手法で攻撃者が不正ログインできるわけがないと思います。 ここでは、便宜上amazon.co.jpを利用させていただきました。
本来、trap.example.co.jpサーバ(攻撃者のサイト)がSet-Cookieの際に、Domain=co.jpとしても、 このクッキーはブラウザに無視されますが、脆弱性のある古いブラウザでは、.co.jpドメインのクッキーが作れてしまうという問題が過去にあったようで、これがクッキーモンスター問題と言われているようです。
IE8では地域型ドメインに対するクッキーモンスター問題があるようです。
- ステートレス(クライアントの状態を覚えておけない)
- ブラウザからのリクエストメッセージは改変できる(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アプリケーションの「入力」では以下を行う。
- 文字エンコーディングの検証と変換
- 入力検証
入力値検証の基準は、アプリケーションの要件で決まる。
入力値検証自体はセキュリティの向上には直接的にはつながらないが、保険になる。
- 制御文字のチェック
- 文字数のチェック(最大文字数の指定)
- どのパラメータを検証するか(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
関数は、そこで文字列が終わっていると判断する。
- Webアプリケーション嬢のHTMLやJavaScriptの生成部分で発生する
- 攻撃用のJavaScriptが、攻撃対象のサイトとは別のサイト(罠サイト)にある場合は、反射型XSS
- 攻撃用のJavaScriptが、攻撃対象のDBなどに保存されている場合は、持続型XSS
**TIPS: ** 反射型XSSは、入力値をそのまま表示するページで発生することが多い。
**TIPS: ** 持続型XSSは、罠サイトに誘導する手間が省ける。SNSが典型的なターゲットになる。
- ブラウザ上で悪いスクリプトが実行されることにより、クッキー値を盗まれる
- 受動的攻撃により別人のクッキー値を盗み出す
例:
- 罠サイトの
iframe
要素の中に脆弱サイトのページを表示する - 脆弱なサイトでXSS攻撃を行い、クッキー値をクエリ文字列に付与して、情報取集ページに遷移
- 情報取集ページから受け取ったクッキー値をメールで攻撃者が受け取る
- ブラウザ上で悪いスクリプトが実行されることにより、被害者の権限でWebアプリケーションの機能を悪用される
- Ajaxの流行によりXSSとJavaScriptの組み合わせで攻撃しやすくなっている
javascript
スキームによるJavaScriptの起動
- Webサイト上に偽の入力フォームが表示され、フィッシングにより個人情報を盗まれる
例:
</form>
タグにより、元サイトのform
要素を終了させる- 新しい
form
要素を開始して、styleを指定しソレっぽく見せて画面を改変する - action要素には罠サイトのURLを指定して、誘導する
- HTMLの特殊記号(メタ文字)を正しく扱っていない
- JavaScriptの文字列リテラルのエスケープ摹れ
最低限の対策。
- メタ文字を正しく扱う
- HTMLの
<
を<
としてエスケープする - HMTLの属性値を
"
で囲み、<
、""
、&
を文字参照にする - JavaScriptの
\
を\\
にエスケープかつ、結果をHTMLエスケープする - JavaScriptの
''
を\'
にエスケープかつ、結果をHTMLエスケープする - JavaScriptの
"
を"
にエスケープかつ、結果をHTMLエスケープする - JavaScriptの改行を
\n
にエスケープかつ、結果をHTMLエスケープする
- セッションIDを生成している箇所で発生する
以下の項目を満たすサイトで漏洩しがち。
- URL埋め込みのセッションIDを使える
- 外部サイトへのリンクがあるもしくはリンクを利用者が作成可能
例:
- URL付きメールを送信して、ターゲットを罠サイトに誘導
- まんまと罠サイトを閲覧すると、Webメールに埋め込まれたセッションIDがRefererとして罠サイトに漏洩
- 受け取ったRefererを元に、利用者へのなりすましを行う
- セッションIDがURLに埋め込まれる直接の原因は、不適切な設定やプログラミング
- セッションIDをURLに埋め込まない
- セッションIDはクッキーに埋め込む(それでもセッションIDの固定化は発生しうる)
- セッションIDを外部から強制する
例:
- ターゲットのセッションIDを入手する
- ターゲットには、1で入手したセッションIDを矯正する
- ターゲットは標的アプリケーションにログインする
- 攻撃者は強制したセッションIDをつかって、標的アプリケーションにアクセスする
- セッションIDが外部から強制できること
- セッションIDをURLに埋め込まない
- セッションIDはクッキーに埋め込む(それでもセッションIDの固定化は発生しうる)
- クッキーモンスター問題のブラウザは使わせない
- クッキーモンスター問題の発生する地域型ドメインを使わない
- XSSやHTTPヘッダ・インジェクション、その他クッキー書き換えの脆弱性をなくす
- 認証後にセッションIDを変更する、できない場合はトークンにとり対策する
- 認証前には、セッション変数に秘密情報を保存しない
👮💭 セッションIDの要件
対策については、上記項目も参照。
- すべてのHTTPレスポンスヘッダの出力時に発生しうる脆弱性
- なりすましや偽ページの表示、キャッシュ汚染などの影響がある
**TIPS: **HTTPレスポンス分散攻撃では、HTTPヘッダ・インジェクションにより、複数のレスポンスを生成して、プロキシサーバに偽のコンテンツをキャッシュさせる。
- 任意のクッキー生成
- 偽画面の表示
- 外部から指定された改行をそのまま出力してしまうこと
- HTTPヘッダの出力部分を手作りせずにライブラリやAPIを利用する
- レスポンスヘッダの文字列中に改行コードが含まれていないかチェックする(含まれていたらエラーとする)
- クッキー値の改行はパーセントエンコードする
- 外部からのパラメータをHTTPレスポンスヘッダとして出力しない
- リダイレクトやクッキー出力を専用のAPIに任せる
- 一般的にはクッキーに保存するにはセッションIDのみで、データ自体はWebサーバのメモリやファイル、DBに保存する
- クッキーに保存するべき出ないデータを保存していることにより、脆弱性につながる
- クッキー値はアプリケーションの利用者によって書き換えができる
- ユーザーIDや権限情報をクッキーに保存している
- クッキーには、データは保存しない
- セッションやサーバを跨って情報を保存する必要がある場合(ログイン状態の保持機能など)のみトークンの保存に、クッキーを利用する