体系的に学ぶ 安全なWebアプリケーションの作り方
- 37.8 時間
- Web アプリケーションの脆弱性とその対策について、基本的なものを一通り学べた
- 実習環境で脆弱性サンプルを動作させながら学べるのがよかった
- 若干飽きるところもあったけど…
- 悪用の例
- 個人情報などの秘密情報を勝手に閲覧する
- Web サイトの内容を書き換える
- サイトを閲覧した利用者の PC をウイルスに感染させる
- 別の利用者になりすまし、秘密情報の閲覧、投稿、買い物、送金などを行う
- Web サイトのコンピュータ資源を勝手に使われる(暗号通貨のマイニングなど)
- Web サイトを利用不能にする
- オンラインゲームなどで無敵になることができる、アイテムを好きなだけとれる
- 自分の個人情報を確認したら、他人の個人情報が見えてしまう
- 経済的損失
- 法的な要求
- 利用者が回復不可能なダメージを受ける場合が多い
- Web サイト利用者に嘘をつくことになる
- ボットネットワーク構築に荷担する
- 脆弱性の発生原因は以下の 2 種類に分類できる
- バグによるもの
- チェック機能の不足によるもの
- アプリケーションのセキュリティを確保するためには、バグをなくすだけでは不十分な場合がある
- HTTPS で暗号化していない状態はバグではないが、盗聴される可能性がある
- 積極的に安全性を強化する機能のことを本書では「セキュリティ機能」と呼ぶ
- wasbook をインストールしたが、起動時に「VirtualBox VM quit unexpectedly.」のメッセージでエラーが出た
- Settings > Audio にいって "Enable Audio" のチェックを外したら起動できるようになった
- なぜ HTTP を学ぶのか
- Web の特性に由来する脆弱性を理解するためには、HTTP やセッション管理についての理解が不可欠
- GET と POST の使い分け
- GET
- GET メソッドは参照(リソースの取得)のみに用いる
- GET メソッドは副作用がないことが 期待される
- 秘密情報の送信には POST メソッドを用いること
- 秘密情報を POST で送信すべきという理由は、GET の場合は以下の可能性があるため
- URL 上に指定されたパラメータが Referer 経由で外部に漏洩する
- URL 上に指定されたパラメータがアクセスログに残る
- URL 上のパラメータがブラウザのアドレスバーに表示され他人にのぞかれる
- パラメータつきの URL を利用者がソーシャルネットワークなどで共有してしまう
- 以下が 1 つでも当てはまる場合に POST メソッドを用い、1 つも当てはまらない場合には GET メソッドを利用するとよい
- データ更新など副作用を伴うリクエストの場合
- 秘密情報を送信する場合
- 送信するデータの総量が多い場合
- ステートレスな HTTP 認証
- クッキーとセッション管理
- HTTP とういプロトコルはステートレスなもので、サーバー側では状態を保持しない
- しかし、アプリケーションでは状態を保持したい要求がたびたびある
- HTTP 認証を使えば、ブラウザ側で ID とパスワードを記憶してくれるが、HTTP 認証を使わない場合は、サーバー側で認証状態を覚えておく必要がある
- これらアプリケーションの状態を覚えておくことをセッション管理という
- このセッション管理を HTTP で実現する目的でクッキー(cookie)という仕組みが導入された
- クッキーによるセッション管理
- クッキーは少量のデータをブラウザ側で覚えておけるものだが、アプリケーションデータを保持する目的でクッキーそのものに値を入れることはあまり行われない
- 理由
- クッキーが保持できる値の個数や文字列 長には制限がある
- クッキーの値は利用者本人には参照・変更できるので、秘密情報の格納には向かない
- セッション ID に求められる要件
- 第三者がセッション ID を推測できないこと
- 第三者からセッション ID を強制されないこと
- 認証後にセッション ID を変更すればよい
- 第三者にセッション ID が漏洩しないこと
- セッション ID をネットワーク盗聴から保護するには TLS(Transport Layer Security) による暗号化が有効
- クッキーの属性
- Domain 属性
- ブラウザがクッキー値を送信するサーバーのドメイン
- Domain 属性を指定しない場合、クッキーを生成したサーバーにのみクッキーが送られる
- Domain 属性を指定しない状態が最もクッキーの送信範囲が狭く、安全な状態といえる
- Domain を不用意に設定すると脆弱性の原因になる
- 例えば example.com がレンタルサーバー事業者であり、foo.example.com と bar.example.com がレンタルサーバー上で運営されている Web サイトであるとする。foo.example.com サイトが発行するクッキーに Domain = example.com と指定してしまうと、このクッキーは bar.example.com にも漏洩してしまう
- Domain 属性は通常は設定しない
- Secure 属性
- Secure という属性をつけたクッキーは、HTTPS 通信の場合のみサーバーに送信される
- 一方、Secure 属性のついていないクッキーは、HTTPS 通信かどうかに関係なく、常にサーバーに送信される
- クッキーの Secure 属性は、クッキーの HTTPS 送信を保証する目的で指定される
- HttpOnly 属性
- HttpOnly 属性は、JavaScript からアクセスできないクッキーを設定する
- クッキーとして格納されたセッション ID を盗み出す攻撃の典型例は、クロスサイト・スクリプティング攻撃により JavaScript を悪用してクッキーを盗み出すというもの
- クッキーに HttpOnly 属性をつけておくと、JavaScript によりクッキーを盗み出すことができなくなる
- HttpOnly 属性をつけることによる悪影響は通常ないので、セッション ID には HttpOnly 属性をつけるようにするといい
- SameSite 属性
- 最近のブラウザには、主にクロスサイド・リクエストフォージェリ(CSRF)脆弱性対策を目的として、SameSite 属性が機能として追加されている
- SameSite 属性は値として Strict、Lax、None のいずれかを指定できる
- Strict: 他のドメインへのリクエストを送る場合、Strict が指定されたクッキーはセットされない
- Lax: top-level navigation でかつ GET メソッドであれば、他のドメインへのリクエストであってもクッキーをセットする
- None: 従来どおりの動作(クッキーを送る)
- 能動的攻撃(active attack)
- 能動的攻撃とは、攻撃者が Web サーバーに対して直接攻撃すること
- 能動的攻撃の代表例として、SQL インジェクション攻撃がある
- 受動的攻撃(passive attack)
- 受動的攻撃とは、攻撃者がサーバーを直接攻撃するのではなく、Web サイトの利用者に罠を仕掛けることにより、罠を閲覧したユーザを通してアプリケーションを攻撃する手法
- 単純な受動的攻撃
- 罠サイトに利用者を誘導する
- 典型例として、いわゆる「怪しいサイト」を閲覧してマルウェア(ウイルスなどの不正プログラム)に感染させる
- 正規サイトを悪用する受動的攻撃
- 攻撃の手順
- あらかじめ正規サイトを攻撃してコンテンツに仕掛けを仕込む
- 正規サイトの利用者が仕掛けを含むコンテンツを閲覧すると、マルウェア感染などが起こる
- 攻撃する側のメリット
- 罠サイトに誘導する手間がいらない
- 正規サイトは利用者が多いので被害が拡大する可能性が高い
- 正規サイトの機能を不正利用することにより攻撃者にメリットが得られる
- 利用者の個人情報を盗むことにより攻撃者にメリットが得られる
- 正規サイトに罠を仕込む手法。よくある 4 種類
- FTP などのパスワードを不正入手してコンテンツを書き換える(8.1 節参照)
- Web サーバーの脆弱性をついた攻撃によりコンテンツを書き換える(8.1 節参照)
- SQL インジェクション攻撃によりコンテンツを書き換える(4.4 節参照)
- SNS など利用者が投稿できるサイト機能のクロスサイト・スクリプティング脆弱性を悪用する(4.3 節参照)
- サイトをまたがった受動的攻撃
- 手順
- 利用者が罠サイトを閲覧する
- 罠サイトから、仕掛けを含む HTML をダウンロードする
- HTML の仕掛けが発動して、正規サイトに攻撃のリクエストを送信する
- 正規サイトから JavaScript などの仕掛けを含むレスポンスが返る
- ブラウザはどのように受動的攻撃を防ぐか
- ここまで説明した受動的攻撃に対しては、ブラウザと Web サイトそれぞれで対策を行う必要がある
- 本書の 4 章以降では Web サイト側について説明するが、それはブラウザのセキュリティに問題がないことを前提としている
- サンドボックスという考え方
- ブラウザ上では JavaScript や Java アプレットなどサイトを閲覧した状態でプログラムを実行する機能が提供されている
- 利用者のブラウザ上で悪意のあるプログラマが動かないように、JavaScript などは安全性を高めるための機能を提供している
- 基本的な考え方 2 種類
- 利用者に配布元を確認させた上で、利用者が許可した場合のみ実行する
- プログラムの「できること」を制限するサンドボックスという環境を用意する
- 前者は ActiveX コントロールや署名付きアプレットで採用されている考え方だが、一般的なアプリケーションを用いるには利用者の負担が大きく、セキュリティ上の問題が出やすいため、提供元からのサポートが終了しつつある
- サンドボックスは JavaScript や Java アプレット、Adobe Flash Player などで採用されている考え方
- JavaScript のサンドボックスでは以下のように機能が制限される
- ローカルファイルへのアクセス禁止
- プリンタなどの資源の利用禁止(画面表示は可能)
- ネットワークアクセスの制限(同一オリジンポリシー)
- 同一オリジンポリシー
- JavaScript などのクライアントスクリプトからサイトをまたがったアクセスを禁止するセキュリティ上の制限であり、ブラウザのサンドボックスに用意された制限の 1 つ
- JavaScript による iframe アクセスの実験
- ホストが同一であれば、iframe の外側から、iframe の内側の HTML の内容を JavaScript により参照できる
- 同一オリジンである条件
- 以下のすべてを満たす場合
- URL のホストが一致している
- スキーム(プロトコル)が一致している
- ポート番号が一致している
- 同一オリジンポリシーによる保護対象は iframe 内のドキュメントだけでなく、例えば Ajax の実現に使用される XMLHttpRequest オブジェクトでアクセスできる URL にも同一オリジンポリシーの制約がある
- ただし、XMLHttpRequest については、相手側の許可があれば同一オリジンでなくても通信できる CORS という規格が策定された
- アプリケーション脆弱性と受動的攻撃
- ブラウザは同一オリジンポリシーにより受動的攻撃を防止しているが、アプリケーションに脆弱性があると、受動的攻撃を受ける場合がある
- JavaScript 以外のクロスドメインアクセス
- JavaScript 以外のブラウザ機能で、クロスドメインのアクセスが許可されているものについて説明する
- frame 要素と iframe 要素
- クロスドメインのアクセスができるが、JavaScript によってクロスドメインのドキュメントにアクセスすることは禁止されている
- img 要素
- img 要素の src 属性はクロスドメインの指定が可能
- script 要素
- CSS
- form 要素の action 属性
- CORS は従来の同一オリジンポリシーに依存するアプリケーションとの互換性を保ちながら、異なるオリジンとのデータ交換を可能にする
- シンプルなリクエスト
- Access-Control-Allow-Origin
- Access-Control-Allow-Origin とは、クロスオリジンからの読み出しを許可するための仕掛けで、情報の提供元が HTTP レスポンスヘッダとして出力する
- シンプルなリクエストの要件
- HTML フォームから送られるリクエストを基準として、HTML フォームの場合に比べて過度にリスクが増加しない範囲で条件が選択されている
- 以下の条件をすべて満たすもの
- メソッドは下記のうちのいずれか
- GET
- HEAD
- HTTP の HEAD メソッドは、指定されたリソースを HTTP GET メソッドでリクエストした時に返されるヘッダーをリクエストする
- POST
- XMLHttpRequest オブジェクトの setRequestHeader メソッドで設定するリクエストヘッダは以下に限る
- Accept
- Accept-Language
- Content-Language
- Content-Type
- Content-Type ヘッダは以下のいずれかであること
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
- プリフライトリクエスト
- クロスオリジンアクセスにおいて「シンプルなリクエスト」の条件を満たさない場合、ブラウザはプリフライトリクエスト(pre-flight request)という HTTP リクエストを送信する
- 認証情報を含むリクエスト
- デフォルトでは、クロスオリジンに対するリクエストには HTTP 認証やクッキーなどの認証に用いられるリクエストヘッダは自動的に送信されない
- クッキーなど認証用のヘッダを伴うクロスオリジンリクエストは、下記の両方を満たす必要がある
- XMLHttpRequest オブジェクトの withCredentials プロパティを true にする
- レスポンスヘッダとして Access-Control-Allow-Credentials: true を返す
- 脆弱性はどこで発生するのか
- 脆弱性の例
- HTML の出力(クロスサイト・スクリプティング)
- HTTP ヘッダの出力(HTTP ヘッダ・インジェクション)
- SQL 文の呼び出し(発行)(SQL インジェクション)
- シェルコマンドの呼び出し(OS コマンド・インジェクション)
- メールヘッダおよび本文の出力(メールヘッダ・インジェクション)
- Web アプリケーションの機能と脆弱性の対応
- 脆弱性には処理に起因するものと出力に起因するものがある
- 入力に起因する脆弱性はない
- 出力に起因する脆弱性には「インジェクション」という単語がつくものが多い
- インジェクション系脆弱性とは
- データの中に引用符やデリミタなど「データの終端」を示すマークを混入させて、その後の文字列の構造を変化させる
- Web アプリケーションの「入力」では何をするか
- 入力処理では入力値に対して以下の処理を行う
- a: 文字エンコーディングの妥当性検証
- b: 文字エンコーディングの変換(必要な場合のみ)
- c: 入力値(パラメータ文字列)の妥当性検証
- 文字エンコーディングの検証
- PHP では mb_check_encoding 関数が利用できる
- 文字エンコーディングの変換
- 文字エンコーディングの変換手段は言語によって異なる
- 入力値の検証
- 目的
- 入力値検証がないと以下のような現象が起こってしまう
- 数値のみを受け付ける項目に英字や記号を入力して、データベースのエラーになる
- 更新処理が途中でエラーになり、データベースの不整合が発生する
- 利用者が多数の項目を入力して実行ボタンをクリックしたら内部エラーとなり、入力を最初からやり直すはめになる
- メールアドレスの入力を忘れているのにアプリケーションがメール送信処理を実行する
- 目的は以下
- 入力値の間違いを早期に発見して再入力を促すことにより、ユーザビリティを向上する
- 間違った処理を継続することによるデータの不整合などを防ぎ、システムの信頼性を向上させる
- 入力値検証とセキュリティ
- 入力値検証の主目的はセキュリティのためではない。セキュリティの役に立つのは以下のようなケース
- SQL インジェクション対策が漏れていたパラメータがあるが、英数字のみ許可していたので実害には至らない
- PHP のバイナリセーフではない関数を使っているが、入力段階で制御文字をチェックしているので実害には至らない
- 表示処理の関数に文字エンコーディングの指定を怠っているが、入力段階で不正な文字エンコーディングをチェックしているので実害には至らない
- バイナリセーフという考え方とヌルバイト攻撃
- バイナリセーフとは、入力値がどんなバイト列であっても正しく扱えることを意味するが、典型的には値ゼロのバイト(ヌルバイト)が現れても正しく処理できることを指す
- ヌルバイトが特別扱いされる理由は、C 言語および Unix や Windows の API ではヌルバイトを文字列の終端とみなす取り決めがあ るため
- そのため、C 言語で開発された PHP やその他のスクリプト言語では、ヌルバイトを文字列の終端としてそれ以降を切り詰めてしまう関数がある。このような関数をバイナリセーフでない関数という
- 入力値検証だけでは対策にならない
- 入力値検証の基準はアプリケーション要件
- 制御文字のチェック
- 制御文字というのは、改行やタブなど、通常表示されることのない ASCII コード 0x20 未満および 0x7F(DELETE) の文字のこと
- 文字数のチェック
- 数値の最小値・最大値のチェック
- その他の注意点
- 入力項目が指定されていない(項目自体がない)ケース
- 配列形式で入力されているケース
- どのパラメータを検証するか
- PHP の正規表現関数
- 表示処理が原因で発生するセキュリティ上の問題には以下がある
- クロスサイト・スクリプティング
- エラーメッセージからの情報漏洩
4.3.1: クロスサイト・スクリプティング(基本編)
- 概要
- クロスサイト・スクリプティング(Cross-Site Scripting) は、しばしば XSS と省略される
- Web アプリケーションに XSS 脆弱性がある場合には、以下の影響がある
- サイト利用者のブラウザ上で、攻撃者の用意したスクリプトの実行によりクッキー値を盗まれ、利用者がなりすましの被害にあう
- 同じくブラウザ上でスクリプトを実行させられ、サイト利用者の権限で Web アプリケーションの機能を悪用される
- Web サイト上に偽の入力フォームが表示され、フィッシングにより利用者が個人情報を盗まれる
- 攻 撃手法と影響
- XSS によるクッキー値の盗み出し
- その他の JavaScript による攻撃
- 画面の書き換え
- 反射型 XSS と持続型 XSS
- 攻撃用 JavaScript が、攻撃対象サイトとは別のサイト(罠のサイトやメールの URL)にある場合を「反射型 XSS(reflected XSS)」という
- 一方、攻撃用の JavaScript が、攻撃対象のデータベースなどに保存される場合がある。その場合の XSS を「持続型 XSS(stored XSS あるいは persistent XSS)」と呼ぶ
- 脆弱性が生まれる原因
- XSS 脆弱性が生じる原因は、HTML 生成の際に、HTML の文法上特別な意味を持つ特殊記号(メタ文字)を正しく扱っていないことであり、それにより開発者の意図しない形で HTML や JavaScript を注入・変形される現象が XSS
- HTML エスケープの概要
- 例えば HTML で「<」という文字を表示させたい場合は、文字参照により「<」と記述(エスケープ)しなければならない
- 要素内容の XSS
- 引用符で囲まない属性値の XSS
- 引用符で囲った属性値の XSS
- 属性値を引用符で囲っていても、「"」をエスケープしていないと XSS 攻撃が可能
- 対策
- XSS 対策の基本
- 要素内容については「<」と「&」をエスケープする
- 属性値については、ダブルクオートで囲って「<」と「"」と「&」をエスケープする
- レスポンスの文字エンコーディング指定
- Web アプリケーション側で想定している文字エンコーディングとブラウザが想定する文字エンコーディングに差異があると、XSS の原因になりうる
- XSS に対する保険的対策
- X-XSS-Protection レスポンスヘッダの使用
- ブラウザの機能で、反射型 XSS を検出したときに、ページの読み込みを停止するためのもの
- 入力値検証
- クッキーに HttpOnly 属性を付与する
- この属性は JavaScript からのクッキーの読み出しを禁止するもの
4.3.2: クロスサイト・スクリプティング(発展編)
- この項では、様々な状況で発生するクロスサイト・スクリプティング脆弱性について、前項を補足する内容を説明する
- href 属性や src 属性の XSS
- URL を生成する場合の対策
- URL としては以下のいずれかのみを許容するようにチェックするとよい
- http: または https: で始まる絶対 URL
- スラッシュで始まる相対 URL
- リンク先ドメイン名のチェック
- 外部のドメインに対するリンクが自明な場合以外は、以下のどちらかを実施すると良い
- リンク先 URL を検証して、URL が外部ドメインである場合はエラーにする
- 外部ドメインへのリンクであること を利用者に注意喚起するためのクッションページを表示する
- JavaScript の動的生成
- イベントハンドラの XSS
- Web アプリケーションの中には、JavaScript の一部をサーバー側で動的生成する例がある 。典型的には、JavaScript の文字列リテラルを動的生成するケース
- script 要素の XSS
- JavaScript の文字列リテラルの動的生成の対策
- script 要素の外部でパラメータを定義して、JavaScript から参照する方法
- インライン JSONP による方法
- HTML タグや CSS の入力を許す場合の対策
- ブログシステムや SNS を開発する際には、利用者の入力に HTML タグや CSS の入力を許可したい場合がある。しかし、これらの入力を許可すると、XSS の危険性が高まる
- HTML タグや CSS の入力を許可するサイトを開発する場合は、HTML テキストを構文解析して必要な要素のみを抽出するライブラリを使用することが望ましい
4.3.3: エラーメッセージからの情報漏洩
- エ ラーメッセージからの情報漏洩については以下の 2 種類がある
- エラーメッセージに攻撃者にとって有益なアプリケーションの内部情報が含まれる
- 意図的な攻撃として、エラーメッセージに秘密情報(個人情報など)を表示させられる
- さらに進んだ学習のために
4.4.1: SQL インジェクション
- SQL インジェクションは、SQL の呼び出し方に不備がある場合に発生する脆弱性
- アプリケーショ ンに SQL インジェクション脆弱性がある場合、以下のような影響を受ける可能性がある
- データベース内のすべての情報が外部から盗まれる
- データベースの内容が書き換えられる
- 認証を回避される(ID とパスワードを用いずにログインされる)
- その他、データベースサーバー上のファイルの読み出し、書き込み、プログラムの実行などを行われる
- 攻撃手法と影響
- エラーメッセージ経由の情報漏洩
- UNION SELECT を用いた情報漏洩
- SQL インジェクションによる認証回避
- SQL インジェクションによるデータ改竄
- その他の攻撃
- データベースエンジンによっては、SQL インジェクション攻撃によって、以下が可能になる場合がある
- OS コマンドの実行
- ファイルの読み出し
- ファイルの書き出し
- HTTP リクエストにより他のサーバーを攻撃
- 脆弱性が生まれる原因
- 文字列リテラルの問題
- 数値項目に対する SQL インジェクション
- 対策
- SQL 文を組み立てる際に SQL 文の変更を防ぐこと。その方法には以下がある
- プレースホルダにより SQL 文を組み立てる
- アプリケーション側で SQL 文を組み立てる際に、リテラルを正しく構成するなど、SQL 文が変更されないようにする
- プレースホルダによる SQL 文組み立て
- PDO(PHP Data Objects) の安全な利用方法
- 静的プレースホルダと動的プレースホルダの違い
- 静的プレースホルダ
- 値のバインドをデータベースエンジン側で行う
- 動的プレースホルダ
- SQL を呼び出すアプリケーション側のライブラリ内で、パラメータをバインドしてからデータベースエンジンに送る
- 原理的に SQL インジェクションの可能性がないという点で静的プレースホルダのほうが優れている。可能であれば、静的プレースホルダを利用するべき
- SQL インジェクションの保険的対策
- 詳細なエラーメッセージの抑止
- 入力値の妥当性検証
- データベースの権限設定
- さらに進んだ学習のために
- 参考: プレースホルダが使えない場合の対策
- 以下の 2 点を実施する
- 文字列リテラル内で特別な意味を持つ記号文字をエスケープする
- 数値リテラルは数値以外の文字が混入しないようにする
- Web アプリケーションには、ログインした利用者のアカウントにより、取り消しできない重要な処理が実行できるものがある
- そのような処理を本書では「重要な処理」と表記する
4.5.1: クロスサイト・リクエストフォージェリ(CSRF)
- 概要
- 「重要な処理」の受付に際しては、利用者の意図したリクエストであることを確認する必要があるが、この確認処理が抜けていると、罠のサイトなどを閲覧しただけで、利用者のブラウザから勝手に「重要な処理」を実行させられる場合がある
- このような問題を引き起こす脆弱性をクロスサイト・リクエストフォージェリ(CSRF)脆弱性と呼ぶ
- Web アプリケーションに CSRF 脆弱性がある場合の影響の例として、以下がある
- 利用者のアカウントによる物品の購入
- 利用者の退会処理
- 利用者のアカウントによる SNS や問い合わせフォームなどへの書き込み
- 利用者のパスワードやメールアドレスの変更
- 攻撃手法と影響
- 入力-実行パターンの CSRF 攻撃
- パスワードが変更される場合は情報漏洩も
- CSRF 攻撃と XSS 攻撃の比較(p181)
- CSRF はサーバー側の処理を悪用するもの。悪用内容はもともとサーバー側で用意された処理に限定される
- XSS は、仕掛けを含むレスポンスがブラウザで実行されることで攻撃が起きる
- 攻撃の広範さという点では XSS の脅威のほうが大きいが、CSRF は以下の点で注意すべき脆弱性である
- CSRF は設計段階から対策を盛り込む必要がある
- 開発者の認知度が XSS に比べて低く、対策が進んでいない
- 確認画面がある場合の CSRF 攻撃
- hidden パラメータでパラメータ受け渡ししている場合
- セッション変数によりパラメータ受け渡ししている場合
- このパターンを採用しているアプリケーションに対しては、次の 2 段階の攻撃が必要になる
- 1: 確認画面に対してメールアドレスを POST してセッション変数にメールアドレスをセットする
- 2: タイミングを見計らって実行画面を呼び出す
- ファイルアップロードフォームでの CSRF 攻撃
- 脆弱性が生まれる原因
- 以下の Web の性質が背景としてある
- 1: form 要素の action 属性にはどのドメインの URL でも指定できる
- 罠などのサイトからでも、攻撃対象サイトにリクエストを送信できる
- 2: クッキーに保管されたセッションの ID は、対象サイトに自動的に送信される
- 罠経由のリクエストに対しても、セッション ID のクッキー値が送信されるので、認証された状態で攻撃リクエストが送信される
- 対策
- 以下の 2 点を実施する
- 1: CSRF 対策の必要なページを区別する
- 要件定義行程で機能一覧を作成し、CSRF 対策の必要な機能にマークする
- 基本設計行程で画面遷移図を作成し、CSRF 対策の必要なページにマークする
- 開発工程で CSRF 対策を作り込む
- 2: 正規利用者の意図したリクエストを確認できるよう実装する
- 秘密情報(トークン)の埋め込み
- パスワード再入力
- Referer のチェック
- ただし、Referer が送信されないように設定している利用者は、そのページを実行できなくなる
- CSRF 攻撃への保険的対策
- 「重要な処理」の実行後に、対象利用者の登録済みのメールアドレスに対して、処理内容の通知メールを送信することを推奨する
- メール通知では CSRF 攻撃を防ぐことはできないが、万一 CSRF 攻撃を受けた際に利用者が早期に気づくことができ、被害を最小限にとどめることができる
4.5.2: クリックジャッキング
- 概要
- Web アプリケーションの画面上で特定のボタンなどを利用者にクリックさせることができれば、利用者の意図しない投稿やサイトの設定変更ができる場合がある
- 攻撃手法と影響
- Twitter のウェブインテント機能
- クエリー文字列から投稿内容を指定して、投稿フォームにあらかじめ投稿内容を埋めておくことができる
- サンプルスクリプトの説明
- 脆弱性が生まれる原因
- クリックジャッキングはアプリケーションのバグが原因ではなく、HTML の仕様を巧妙に悪用した攻撃と言える
- このため、バグを修正したら防げるというタイプの脆弱性ではない。この点も、CSRF と似た脆弱性と言える
- 対策
- クリックジャッキング対策はアプリケーション単体では困難なため、ブラウザ側の支援が必要になる
- このため、frame および iframe での参照を制限する X-Frame-Options という仕様が Microsoft 社から提唱され、現在では主要ブラウザの最新版で採用されている。この仕様に対応することにより、クリックジャッキング対策が容易にできるようになっている
- X-Frame-Options はレスポンスヘッダとして定義されており、DENY あるいは SAMEORIGIN のいずれかの値をとる
- DENY を指定したレスポンスは frame などの内側で表示されなくなる
- SAMEORIGIN の場合は、アドレスバーに表示されたオリジンと同じオリジンである場合のみ表示される
- 保険的対策
- CSRF の時と同様、「重要な処理」の実行後に、対象利用者の登録済みのメールアドレスに対して、処理内容の通知メールを送信するのがよい
4.6.1: セッションハイジャックの原因と影響
- なんらかの原因で、ある利用者のセッション ID が第三者に知られると、その利用者に成りすましてアクセスされる可能性がある
- 第三者がセッション ID を悪用してなりすますことをセッションハイジャックと呼ぶ
- 第三者がセッション ID を知るための手段は、以下の 3 種類に分類される
- セッション ID の推測
- セッション ID の盗み出し
- セッション ID の強制
- セッション ID の推測
- 連番になっているセッション ID
- 日時やユーザー ID を元にして生成しているセッション ID
- オープンソースのソフトウェアなどセッション ID の生成ロジックが公開されている場合
- セッション ID の盗み出し
- クッキー生成の際の属性の不備により漏洩する
- ネットワーク的にセッション ID が盗聴される
- クロスサイト・スクリプティングなどアプリケーションの脆弱性により漏洩する
- PHP やブラウザなどプラットフォームの脆弱性により漏洩する
- セッション ID を URL 的に保持している場合は Referer ヘッダから漏洩する
- セッション ID の強制
- セッション ID を盗み出す代わりに、セッション ID を利用者のブラウザに設定できれば、攻撃者は利用者のセッション ID を「知っている」状態になり、セッションハイジャックが可能になる
- このような攻撃を「セッション ID の固定化攻撃(Session Fixation Attack)」と呼ぶ
- セッションハイジャックの影響
- 利用者の重要情報(個人情報、メールなど)の閲覧
- 利用者の持つ権限での操作(送金、物品購入など)
- 利用者の ID によるメール、ブログなどへの投稿、設定の変更など
4.6.2: 推測可能なセッション ID
- 概要
- 推測可能なセッション ID による脆弱性を作り込まないためには、セッション管理機構を自作せず、実績のある言語やミドルウェアが提供するセッション管理機構を使用する
- 攻撃手法と影響
- 推測可能なセッション ID に対する攻撃は、次の 3 ステップで行われる
- 1: 対象アプリケーションからセッション ID を集める
- 2: セッション ID の規則性の仮説を立てる
- 3: 推測したセッション ID を対象アプリケーションで試す
- ありがちなセッション ID 生成方法
- 以下を元にする場合が多い
- ユーザ ID やメールアドレス
- リモート IP アドレス
- 日時(UNIX タイムの数値、あるいは年月日時分秒の文字列)
- 乱数
- 上記をそのまま利用する場合もあるが、複数の組み合わせや、エンコード(16 進数や Base64)処理やハッシュ値が利用される場合もある
- このうち、ユーザ ID や日時は外部から推測可能な元データなので、脆弱性の原因になる
- 推測したセッション ID で成りすましを試行する
- 攻撃が成功すれば、セッションが有効なじょうたいになるので、攻撃が成功したと判別できる
- 成りすましの影響
- 重要情報の閲覧、データや文書の投稿・更新・削除、物品の購入、送金など、ターゲットのアプリケーションが持つ機能を利用者の権限により、すべて利用できる
- ただし、重要な処理の前にパスワードの再入力を要求すると、利用者のパスワードはわからないため、セッションハイジャックに対する保険的な対策になる
- 脆弱性が生まれる原因
- アプリケーション側でセッション管理機構を自作していることが脆弱性の原因
- 通常の Web アプリケーション開発では、わざわざセッション ID の生成プログラムを開発する意味はない
- 理由は以下
- 主要な Web アプリケーション開発ツール はセッション管理機構を備えている
- 安全なセッション ID 生成プログラムを開発することは技術的難易度が高い
- 対策
- 最も現実的で効果的な対策は、Web アプリケーション開発ツールが備えるセッション管理機構を利用すること
4.6.3: URL 埋め込みのセッション ID
- 概要
- セッション ID をクッキーに保存せず、URL に埋め込ませる場合がある
- PHP や Java、ASP.NET はセッション ID を URL に埋め込む機能をサポートしている
- セッション ID を URL に埋め込んでいると、Referer ヘッダを経由して、セッション ID が外部に漏洩し、成りすましの原因になる場合がある
- 攻撃手法と影響
- セッション ID が URL 埋め込みになる条件
- Referer によりセッション ID が漏洩する条件
- 以下の 2 点の両方を満たすサイト
- URL 埋め込みのセッション ID を使える
- 外部サイトへのリンクがある。あるいはリンクを利用者が作成できる
- 攻撃のシナリオ
- Referer からのセッション ID 漏洩は、事故として漏れるケースと、意図的な攻撃として脆弱性が狙われるケースがある
- 外部から意図的に攻撃を仕掛けられるのは、利用者がリンクを作成できる場合に限られる
- 具体的には Web メール、掲示板、ブログ、SNS など