# 体系的に学ぶ 安全なWebアプリケーションの作り方

## 概要

### 本

* [体系的に学ぶ 安全なWebアプリケーションの作り方 | 徳丸 浩](https://amzn.to/2S268sV)
* 参考
  * [【正誤情報】体系的に学ぶ安全なWebアプリケーションの作り方 第2版](https://www.sbcr.jp/support/14647/)

### かかった時間

* 37.8 時間

### 感想

* Web アプリケーションの脆弱性とその対策について、基本的なものを一通り学べた
* 実習環境で脆弱性サンプルを動作させながら学べるのがよかった
* 若干飽きるところもあったけど…

## 読書メモ

### 1: Web アプリケーションの脆弱性とは

#### 1.1: 脆弱性とは「悪用できるバグ」

* 悪用の例
  * 個人情報などの秘密情報を勝手に閲覧する
  * Web サイトの内容を書き換える
  * サイトを閲覧した利用者の PC をウイルスに感染させる
  * 別の利用者になりすまし、秘密情報の閲覧、投稿、買い物、送金などを行う
  * Web サイトのコンピュータ資源を勝手に使われる(暗号通貨のマイニングなど)
  * Web サイトを利用不能にする
  * オンラインゲームなどで無敵になることができる、アイテムを好きなだけとれる
  * 自分の個人情報を確認したら、他人の個人情報が見えてしまう

#### 1.2: 脆弱性があるとなぜ駄目なのか

* 経済的損失
* 法的な要求
* 利用者が回復不可能なダメージを受ける場合が多い
* Web サイト利用者に嘘をつくことになる
* ボットネットワーク構築に荷担する

#### 1.3: 脆弱性が生まれる理由

* 脆弱性の発生原因は以下の 2 種類に分類できる
  * バグによるもの
  * チェック機能の不足によるもの

#### 1.4: セキュリティバグとセキュリティ機能

* アプリケーションのセキュリティを確保するためには、バグをなくすだけでは不十分な場合がある
  * HTTPS で暗号化していない状態はバグではないが、盗聴される可能性がある
* 積極的に安全性を強化する機能のことを本書では「セキュリティ機能」と呼ぶ

#### 1.5: 本書の構成

#### 1.6: セキュリティガイドラインとの対応

### 2: 実習環境のセットアップ

* wasbook をインストールしたが、起動時に「VirtualBox VM quit unexpectedly.」のメッセージでエラーが出た
  * Settings > Audio にいって "Enable Audio" のチェックを外したら起動できるようになった
  * Ubuntu 20.04 ではないが同じ症状の記事
    * [How to fix "VirtualBox VM quit unexpectedly" when running my Ubuntu 20.04 LTS VM on MacOS Catalina 10.15 in VirtualBox? - Unix & Linux Stack Exchange](https://unix.stackexchange.com/questions/609077/how-to-fix-virtualbox-vm-quit-unexpectedly-when-running-my-ubuntu-20-04-lts-vm)

### 3: Web セキュリティの基礎

#### 3.1: HTTP とセッション管理

* なぜ 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: 従来どおりの動作(クッキーを送る)

#### 3.2: 受動的攻撃と同一オリジンポリシー

* 能動的攻撃(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 属性

#### 3.3: CORS(Cross-Origin-Resource Sharing)

* CORS は従来の同一オリジンポリシーに依存するアプリケーションとの互換性を保ちながら、異なるオリジンとのデータ交換を可能にする
* シンプルなリクエスト
  * Access-Control-Allow-Origin
    * Access-Control-Allow-Origin とは、クロスオリジンからの読み出しを許可するための仕掛けで、情報の提供元が HTTP レスポンスヘッダとして出力する
  * シンプルなリクエストの要件
    * HTML フォームから送られるリクエストを基準として、HTML フォームの場合に比べて過度にリスクが増加しない範囲で条件が選択されている
    * 以下の条件をすべて満たすもの
      * メソッドは下記のうちのいずれか
        * GET
        * HEAD
          * HTTP の HEAD メソッドは、指定されたリソースを HTTP GET メソッドでリクエストした時に返されるヘッダーをリクエストする
          * [HEAD - HTTP | MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/Methods/HEAD)
        * 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 リクエストを送信する
  * [OPTIONS - HTTP | MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/Methods/OPTIONS)
* 認証情報を含むリクエスト
  * デフォルトでは、クロスオリジンに対するリクエストには HTTP 認証やクッキーなどの認証に用いられるリクエストヘッダは自動的に送信されない
  * クッキーなど認証用のヘッダを伴うクロスオリジンリクエストは、下記の両方を満たす必要がある
    * XMLHttpRequest オブジェクトの withCredentials プロパティを true にする
    * レスポンスヘッダとして Access-Control-Allow-Credentials: true を返す

### 4: Web アプリケーションの機能別に見るセキュリティバグ

#### 4.1: Web アプリケーションの機能と脆弱性の対応

* 脆弱性はどこで発生するのか
  * 脆弱性の例
    * HTML の出力(クロスサイト・スクリプティング)
    * HTTP ヘッダの出力(HTTP ヘッダ・インジェクション)
    * SQL 文の呼び出し(発行)(SQL インジェクション)
    * シェルコマンドの呼び出し(OS コマンド・インジェクション)
    * メールヘッダおよび本文の出力(メールヘッダ・インジェクション)
  * Web アプリケーションの機能と脆弱性の対応
    * 脆弱性には処理に起因するものと出力に起因するものがある
    * 入力に起因する脆弱性はない
    * 出力に起因する脆弱性には「インジェクション」という単語がつくものが多い
* インジェクション系脆弱性とは
  * データの中に引用符やデリミタなど「データの終端」を示すマークを混入させて、その後の文字列の構造を変化させる

#### 4.2: 入力処理とセキュリティ

* Web アプリケーションの「入力」では何をするか
  * 入力処理では入力値に対して以下の処理を行う
    * a: 文字エンコーディングの妥当性検証
    * b: 文字エンコーディングの変換(必要な場合のみ)
    * c: 入力値(パラメータ文字列)の妥当性検証
* 文字エンコーディングの検証
  * PHP では mb\_check\_encoding 関数が利用できる
* 文字エンコーディングの変換
  * 文字エンコーディングの変換手段は言語によって異なる
* 入力値の検証
  * 目的
    * 入力値検証がないと以下のような現象が起こってしまう
      * 数値のみを受け付ける項目に英字や記号を入力して、データベースのエラーになる
      * 更新処理が途中でエラーになり、データベースの不整合が発生する
      * 利用者が多数の項目を入力して実行ボタンをクリックしたら内部エラーとなり、入力を最初からやり直すはめになる
      * メールアドレスの入力を忘れているのにアプリケーションがメール送信処理を実行する
    * 目的は以下
      * 入力値の間違いを早期に発見して再入力を促すことにより、ユーザビリティを向上する
      * 間違った処理を継続することによるデータの不整合などを防ぎ、システムの信頼性を向上させる
  * 入力値検証とセキュリティ
    * 入力値検証の主目的はセキュリティのためではない。セキュリティの役に立つのは以下のようなケース
      * SQL インジェクション対策が漏れていたパラメータがあるが、英数字のみ許可していたので実害には至らない
      * PHP のバイナリセーフではない関数を使っているが、入力段階で制御文字をチェックしているので実害には至らない
        * [バイナリセーフ | IT用語辞典](https://garop.com/69/)
      * 表示処理の関数に文字エンコーディングの指定を怠っているが、入力段階で不正な文字エンコーディングをチェックしているので実害には至らない
  * バイナリセーフという考え方とヌルバイト攻撃
    * バイナリセーフとは、入力値がどんなバイト列であっても正しく扱えることを意味するが、典型的には値ゼロのバイト(ヌルバイト)が現れても正しく処理できることを指す
    * ヌルバイトが特別扱いされる理由は、C 言語および Unix や Windows の API ではヌルバイトを文字列の終端とみなす取り決めがあるため
    * そのため、C 言語で開発された PHP やその他のスクリプト言語では、ヌルバイトを文字列の終端としてそれ以降を切り詰めてしまう関数がある。このような関数をバイナリセーフでない関数という
  * 入力値検証だけでは対策にならない
  * 入力値検証の基準はアプリケーション要件
    * 制御文字のチェック
      * 制御文字というのは、改行やタブなど、通常表示されることのない ASCII コード 0x20 未満および 0x7F(DELETE) の文字のこと
    * 文字数のチェック
    * 数値の最小値・最大値のチェック
    * その他の注意点
      * 入力項目が指定されていない(項目自体がない)ケース
      * 配列形式で入力されているケース
  * どのパラメータを検証するか
  * PHP の正規表現関数

#### 4.3: 表示処理に伴う問題

* 表示処理が原因で発生するセキュリティ上の問題には以下がある
  * クロスサイト・スクリプティング
  * エラーメッセージからの情報漏洩

**4.3.1: クロスサイト・スクリプティング(基本編)**

* 概要
  * クロスサイト・スクリプティング(Cross-Site Scripting) は、しばしば XSS と省略される
    * [クロスサイトスクリプティングとは？仕組みと事例から考える対策](https://cybersecurity-jp.com/security-measures/18427)
  * 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 を検出したときに、ページの読み込みを停止するためのもの
      * [X-XSS-Protection - HTTP | MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-XSS-Protection)
    * 入力値検証
    * クッキーに HttpOnly 属性を付与する
      * この属性は JavaScript からのクッキーの読み出しを禁止するもの
      * [HTTP Cookie - HTTP | MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/Cookies)

**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 種類がある
  * エラーメッセージに攻撃者にとって有益なアプリケーションの内部情報が含まれる
  * 意図的な攻撃として、エラーメッセージに秘密情報(個人情報など)を表示させられる
* さらに進んだ学習のために
  * [教科書に載らないWebアプリケーションセキュリティ － ＠IT](https://www.atmarkit.co.jp/fcoding/index/webapp.html)
  * [Masato Kinugawa Security Blog](https://masatokinugawa.l0.cm/)

#### 4.4: SQL 呼び出しに伴う脆弱性

**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 インジェクションの保険的対策
    * 詳細なエラーメッセージの抑止
    * 入力値の妥当性検証
    * データベースの権限設定
* さらに進んだ学習のために
  * [安全なSQLの呼び出し方](https://www.ipa.go.jp/files/000017320.pdf)
* 参考: プレースホルダが使えない場合の対策
  * 以下の 2 点を実施する
    * 文字列リテラル内で特別な意味を持つ記号文字をエスケープする
    * 数値リテラルは数値以外の文字が混入しないようにする

#### 4.5:「重要な処理」の際に混入する脆弱性

* Web アプリケーションには、ログインした利用者のアカウントにより、取り消しできない重要な処理が実行できるものがある
  * そのような処理を本書では「重要な処理」と表記する

**4.5.1: クロスサイト・リクエストフォージェリ(CSRF)**

* 概要
  * 「重要な処理」の受付に際しては、利用者の意図したリクエストであることを確認する必要があるが、この確認処理が抜けていると、罠のサイトなどを閲覧しただけで、利用者のブラウザから勝手に「重要な処理」を実行させられる場合がある
    * このような問題を引き起こす脆弱性をクロスサイト・リクエストフォージェリ(CSRF)脆弱性と呼ぶ
  * [3分でわかるXSSとCSRFの違い](https://qiita.com/wanko5296/items/142b5b82485b0196a2da)
  * 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: セッション管理の不備

**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 など
    * Web メールからの攻撃の例
      * 攻撃者はターゲットアプリケーションの利用者に対して、URL つきのメールを送信する
      * 利用者が攻撃者のサイトを閲覧すると、Web メールの URL に埋め込まれていたセッション ID が、攻撃者のサイトに Referer として漏洩する
  * 攻撃ではなく事故としてセッション ID が漏洩するケース
    * 利用者が URL を書き込めないサイトの場合、攻撃者が自分のサイトに利用者を誘導するのは難しいが、その場合でも外部サイトへのリンクがあれば、それら外部サイトに対してセッション ID が漏洩することになる
  * 影響
    * セッションハイジャックの影響と同じ
* 脆弱性が生まれる原因
  * URL 埋め込みのセッション ID は、意図的に設定しているケースと、不注意による設定のケースがある
  * 意図的にセッション ID を URL に埋め込む理由としては以下の 2 つ
    * 2000 年前後に主にプライバシー上の理由から「クッキー有害論」が起こり、クッキーを避けようという機運が一部にあった
    * NTT ドコモ社の携帯電話ブラウザが過去にクッキーに対応していなかったので、携帯電話向け Web アプリケーションは今でも URL 埋め込みのセッション ID が主流であった
* 対策
  * URL 埋め込みのセッション ID を使わないためには、クッキーにセッション ID を保存するよう設定する

**4.6.4: セッション ID の固定化**

* 概要
  * セッション ID を外部から強制する方法があり、セッション ID の固定化攻撃と呼ばれる
  * セッション ID の固定化攻撃は以下の手順で行われる
    * 1: セッション ID を入手する
    * 2: 被害者に対して、1 で入手したセッション ID を強制する
    * 3: 被害者は標的アプリケーションにログインする
    * 4: 攻撃者は、被害者に強制したセッション ID を使って標的アプリケーションにアクセスする
* 攻撃手法と影響
  * セッション ID の固定化攻撃の説明
  * ログイン前のセッション ID の固定化攻撃
    * 認証を必要としていないページでセッション変数を利用していると、セッション ID の固定化攻撃が可能となる
    * この場合、利用者のログイン状態に成りすましておらず、利用者の権限を悪用できるわけではないことから、攻撃による影響は、利用者が入力した情報の漏洩に限定される
  * セッションアダプション
    * PHP には未知のセッション ID を受け入れるという特性がある
      * この特性はセッションアダプション(Session Adoption)と呼ばれる
  * クッキーのみにセッション ID を保存するサイトのセッション ID の固定化
    * クッキーのセッション ID を外部から設定することは容易ではないが、ブラウザや Web アプリケーションに脆弱性があれば、可能になる
    * 以下は、クッキーを第三者が設定できる脆弱性の例
      * クッキーモンスターバグ(ブラウザの脆弱性、3.1 節参照)
      * クロスサイト・スクリプティング脆弱性(4.3 節参照)
      * HTTP ヘッダ・インジェクション脆弱性(4.7.2 項参照)
    * また通信路上に攻撃者が存在する場合、OWASP ZAP のようなプロキシツールを用いて、クッキーを改変できる
    * サイト全体が HTTPS で暗号化されている場合でも、平文の HTTP でクッキーを設定すれば、そのクッキーは HTTPS でも有効
  * セッション ID の固定化攻撃による影響
    * セッション ID の固定化攻撃が成立すると、攻撃者は罠に引っかかった利用者としてログインしている状態なので、当該利用者としてできる操作や情報閲覧はすべて可能となる
* 脆弱性が生まれる原因
  * セッション ID の固定化に対する脆弱性が生まれる第一の原因は、セッション ID を外部から強制できるところ
  * 本来であれば、以下をすべて実施することが本質的な対策になる
    * セッション ID を URL に埋め込みにしない
    * クッキーモンスターバグのあるブラウザを使わない(使わせない)
    * クッキーモンスターバグの発生しやすい都道府県型 JP ドメイン名と地域型 JP ドメイン名を使わない
    * クロスサイト・スクリプティング脆弱性をなくす
    * HTTP ヘッダ・インジェクション脆弱性をなくす
    * その他、クッキーを書き換えられる脆弱性をなくす
  * しかし、現実にはこれらをすべて満たすことは困難
    * セッション ID が外部から強制されることは許容し、セッション ID の固定化が行われても、セッションハイジャックは防ぐように対策することが一般的
* 対策
  * Web アプリケーション側でセッション ID の固定化攻撃に対策する方法としては、以下が用いられる
    * 認証後にセッション ID を変更する
  * セッション ID の変更ができない場合はトークンにより対策する
    * Web アプリケーションの開発言語やミドルウェアによっては、セッション ID を明示的に変更できないものがある
    * このような場合、対策としてトークンを使用する方法がある
    * ログイン時に乱数文字列(トークン)を生成し、クッキーとセッション変数の両方に記憶させる方法
    * 各ページの認証確認時に、クッキー上のトークンとセッション変数のトークンの値を比較し、同一である場合のみ認証されていると認識する
      * 同一でない場合は認証エラーと処理する
    * トークンが外部に出力されるタイミングはログイン時のクッキー生成のみであるので、トークンは攻撃者にとっては未知の情報であり、知る手段はない
  * ログイン前のセッション ID の固定化攻撃の対策
    * ログイン前にセッション変数を使っていると、セッション ID の固定化攻撃に完全に対策することは困難
    * ログイン前にはセッション管理機構を使わず、hidden パラメータで値を引き回すことが、現実的で効果的な対策となる

#### 4.7: リダイレクト処理にまつわる脆弱性

* リダイレクト処理に際して発生する代表的な脆弱性としては以下がある
  * オープンリダイレクト脆弱性
  * HTTP ヘッダ・インジェクション脆弱性

**4.7.1: オープンリダイレクト**

* 概要
  * Web アプリケーションの中には、パラメータにより指定した URL にリダイレクトできる機能を備えるものがある
  * その中で任意のドメインにリダイレクトできる脆弱性をオープンリダイレクト脆弱性と呼ぶ
    * オープンリダイレクト脆弱性は、利用者が知らないうちに別ドメインに遷移する場合、フィッシングという詐欺に悪用される可能性がある
  * フィッシングとは、著名な Web サイトなどを偽装したサイトに利用者を誘導して、個人情報などを入力させる手口
  * オープンリダイレクト脆弱性の対策は、外部から URL 指定できるリダイレクト機能が本当に必要かどうかを見直し、可能であればリダイレクト先を固定にすること
    * リダイレクト先の固定化ができない場合は、リダイレクト先を許可されたドメインのみに制限することで対策する
* 攻撃手法と影響
* 脆弱性が生まれる原因
  * 原因は以下の 2 点
    * リダイレクト先の URL を外部から指定できる
    * リダイレクト先のドメイン名のチェックがない
  * オープンリダイレクトが差し支えない場合
    * 以下の 2 点が揃っている場合、脆弱性ではない
      * もともと外部のドメインに遷移する仕様であること
      * 利用者にとって外部ドメインに遷移することが自明であること
    * この条件に当てはまる例としては、バナー広告など
* 対策
  * 以下のいずれかを実施すること
    * リダイレクト先の URL を固定にする
    * リダイレクト先の URL を直接指定せず番号指定にする
      * ページ番号と URL を対応させ、ページ番号で指定する
    * リダイレクト先のドメイン名をチェックする

**4.7.2: HTTP ヘッダ・インジェクション**

* 概要
  * HTTP ヘッダ・インジェクション脆弱性は、リダイレクトやクッキー発行など、外部からのパラメータを元に HTTP レスポンスヘッダを出力する際に発生する脆弱性
  * レスポンスヘッダを出力する際のパラメータ中に改行を挿入する攻撃によって、被害者のブラウザ上で以下のどちらか、あるいは両方が引き起こされる
    * 任意のレスポンスヘッダの追加
    * レスポンスボディの偽造
  * Web アプリケーションに HTTP ヘッダ・インジェクション脆弱性があると、以下の影響がある
    * 任意のクッキーの生成
    * 任意の URL へのリダイレクト
    * 表示内容の改変
    * 任意の JavaScript 実行による XSS と同様の被害
  * HTTP ヘッダ・インジェクション脆弱性の対策
    * HTTP ヘッダの出力部分を手作りせず、ヘッダ出力用のライブラリや API を利用すること
    * さらに、レスポンスヘッダを構成する文字列中に改行コードが含まれていないかをチェックし、改行コードが含まれている場合は、エラーとして処理を中止すること
* 攻撃手法と影響
  * 外部ドメインへのリダイレクト
  * 任意のクッキー生成
    * 外部から任意のクッキー値を生成されることの悪影響の例としては、4.6 節で説明したセッション ID の固定化攻撃との組み合わせで、利用者に対する成りすまし攻撃が挙げられる
  * 偽画面の表示
* 脆弱性が生まれる原因
  * HTTP レスポンスヘッダはテキスト形式で 1 行に 1 つのヘッダが定義できる。すなわち、ヘッダとヘッダは改行で区切られる
    * この性質を悪用して、リダイレクト先 URL やクッキー値として設定されるパラメータ中に改行を挿入した場合に、改行がそのままレスポンスとして出力されることが、HTTP ヘッダ・インジェクション脆弱性の原因
* 対策
  * 1: 外部からのパラメータを HTTP レスポンスヘッダとして出力しない
    * 以下の方針に従えば、外部パラメータを直接ヘッダとして出力する機会は大幅に減少する
      * リダイレクト先を URL として直接指定するのではなく、固定にするか番号などで指定する
      * Web アプリケーション開発ツールの提供するセッション変数を使って URL を受け渡す
  * 2: 以下の両方を実施する
    * リダイレクトやクッキー生成を専用 API にまかせる
    * ヘッダ生成するパラメータの改行文字をチェックする
      * 改行文字に対する処理方法には以下がある
        * URL 中の改行はエラーとする
        * クッキー値の改行はパーセントエンコードする

**4.7.3: リダイレクト処理にまつわる脆弱性のまとめ**

* リダイレクト処理にはできるだけ専用の API(ライブラリ関数)を使用する
* 以下のいずれかを実施する
  * リダイレクト先を固定にする(推奨)
  * 外部から指定するリダイレクト先の URL は、必ず文字種とドメイン名をチェックする

#### 4.8: クッキー出力にまつわる脆弱性

* クッキーにまつわる脆弱性は大別すると以下の 2 種類
  * クッキーを利用すべきでない目的でクッキーを使っている
  * クッキーの出力方法に問題がある
* クッキー出力時に発生しやすい脆弱性は以下
  * HTTP ヘッダ・インジェクション脆弱性
  * クッキーのセキュア属性不備

**4.8.1: クッキーの不適切な利用**

* Web アプリケーションで、ページをまたがる情報を保存する方法としては、PHP や Servlet コンテナなどが提供するセッション管理機構が用いられる。一般的にセッション管理機構ではセッション ID のみをクッキーに保存し、データ自体は Web サーバーのメモリやファイル、データベースなどに保存する
  * 一方、クッキーに保存すべきでないデータをクッキーに保存することにより、脆弱性が発生する場合がある
* クッキーに保存すべきでない情報
  * セッション変数は外部から書き換えができないのに対して、クッキー値はアプリケーションの利用者によって書き換えができる
    * このため、書き換えられると困る情報をクッキーに保存すると脆弱性の原因になる
  * 書き換えられると困る情報の典型例は、ユーザ ID や権限情報
* 脆弱性とはならない場合でも、一般的にクッキーにデータを保存しないことを推奨する

**4.8.2: クッキーのセキュア属性不備**

* 概要
  * クッキーには Secure という属性があり、これを指定したクッキーは HTTPS の場合のみブラウザからサーバーに送信される
  * アプリケーションが HTTPS 通信を利用していても、セキュア属性のついていないクッキーは平文で送信される場合があり、盗聴される可能性がある
  * クッキーにはセッション ID などセキュリティ上重要な情報が格納されている場合が多いので、クッキーが盗聴されると成りすましの被害に直結する
  * クッキーのセキュア属性不備への対策は、クッキーのセキュア属性を設定すること
    * しかし、HTTP と HTTPS の混在するサイトでは、セッション ID に対してクッキーのセキュア属性を設定すると、アプリケーションが動かなくなる場合がある
    * この場合は、セッション ID とは別に、トークンをセキュア属性つきクッキーとして発行して、ページ前に確認する方法がある
* 攻撃手法と影響
* 脆弱性が生まれる原因
  * セキュア属性をつけない主な原因は以下の 2 種類
    * 開発者がセキュア属性について知らない
    * セキュア属性をつけるとアプリケーションが動かなくなる
* 対策
  * セッション ID のクッキーにセキュア属性をつける
  * トークンを用いた対策
    * セッション ID を保持するクッキーにセキュア属性が付けられない場合
    * トークンを保持するクッキーにセキュア属性をつけることによって、HTTP のページと HTTPS のページでセッションを共有しつつ、仮にセッション ID を盗聴された場合でも、HTTPS のページはセッションハイジャックを防止できる
      * 4.6.4 のセッション ID の固定化で紹介したやり方と同じ
  * トークンにより安全性が確保できる理由
    * トークンは認証成功時に一度だけサーバーから出力される
    * トークンは HTTPS のページで生成される(サーバー -> ブラウザ)
    * トークンは確実に暗号化されてブラウザから送信される(ブラウザ -> サーバー)
    * HTTPS のページを閲覧するにはトークンが必須
* セキュア属性以外の属性値に関する注意
  * Domain 属性
    * 指定しないのが最も安全な状態
  * Path 属性
    * ディレクトリごとに異なるセッション ID を発行したい場合には Path 属性の指定が有効
  * Expires 属性
    * セッション ID のクッキーには、通常 Expires 属性をつけず、ブラウザ終了と同時にクッキーが削除される状態にする
  * HttpOnly 属性
    * HttpOnly 属性をつけたクッキーは JavaScript から参照できなくなる

#### 4.9: メール送信の問題

**4.9.1: メール送信の問題の概要**

* メール送信の問題については以下が知られている
  * メールヘッダ・インジェクション脆弱性
    * メールヘッダ・インジェクションとは、メールメッセージの宛先や件名などヘッダフィールドに改行を挿入することにより、新たなフィールドを追加したり、本文を改竄したりする攻撃手法
  * hidden パラメータによる宛先保持
    * 無料で提供されるメール送信用フォームなどには、カスタマイズを簡単に行うことを目的として、メールの送信先などを hidden パラメータとして指定するものがある
    * このようなフォームでは、hidden パラメータの送信先アドレスを任意のアドレスに指定することにより、迷惑メールの送信に悪用される可能性がある
      * 送信先メールアドレスなどは、hidden パラメータに保持するのではなく、サーバー上の安全な場所に保持すべき
  * メールサーバーによる第三者中継
    * メールサーバーの設定に問題があると、そのメールサーバーの発信者でも受信者でもない、第三者のメールを中継する場合がある
    * 最近のメールサーバーソフトは、デフォルト状態で第三者中継を許さない設定になっており、正しい手順でメールサーバーを設定している限り問題ないはず

**4.9.2: メールヘッダ・インジェクション**

* 概要
  * メールヘッダ・インジェクション脆弱性による影響は以下の通り
    * 件名や送信元、本文を改変される
    * 迷惑メールの送信に悪用される
    * ウイルスメールの送信に悪用される
  * 対策は、メール送信専用のライブラリを使用した上で、以下のいずれかを実施する
    * 外部からのパラメータをメールヘッダに含ませないようにする
    * 外部からのパラメータには改行を含まないようにチェックする
* 攻撃手法と影響
  * 攻撃 1: 宛先の追加
  * 攻撃 2: 本文の改竄
  * メールヘッダ・インジェクション攻撃で添付ファイルをつける
* 脆弱性が生まれる原因
  * メールヘッダ・インジェクション脆弱性が生まれる理由を理解するには、まずメールのメッセージ形式を知る必要がある
  * メールのメッセージ形式は、ヘッダとボディを空行で区切るという HTTP と似た形式
  * ヘッダの各フィールドは改行で区切られているので、外部から指定するパラメータに改行を挿入できれば新たなヘッダを追加できる
  * このように、メールのメッセージヘッダでは、改行に特別な意味があるが、アプリケーションが改行をチェックしていない場合には、ヘッダや本文を追加・変更できる
    * これがメールヘッダ・インジェクション脆弱性の発生原因
* 対策
  * まず、メール送信には専用のライブラリを使用すること
  * その上で、以下のいずれかの実施を推奨する
    * 外部からのパラメータをメールヘッダに含ませないようにする
    * 外部からのパラメータには改行を含まないようにメール送信時にチェックする
  * メールヘッダ・インジェクションに対する保険的対策
    * メールアドレスのチェック
      * Web サイトごとに、メールアドレスの仕様を要件として定め、その要件にマッチしているかどうかを入力値検証として検査すればよい
    * 件名のチェック
      * 「制御文字以外にマッチする」正規表現を用いてチェックすれば良い
      * 改行文字も制御文字の一種なので、これでチェックできる
* さらに進んだ学習のために
  * [3分間HTTP&メールプロトコル基礎講座](https://www.amazon.co.jp/3%E5%88%86%E9%96%93HTTP-%E3%83%A1%E3%83%BC%E3%83%AB%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB%E5%9F%BA%E7%A4%8E%E8%AC%9B%E5%BA%A7-%E7%B6%B2%E9%87%8E-%E8%A1%9B%E4%BA%8C/dp/4774140813)

#### 4.10: ファイルアクセスにまつわる問題

* Web アプリケーションには、サーバー上のファイル名を外部からパラメータの形で指定できるものがある。この種のアプリケーションには以下の攻撃が可能になる場合がある
  * Web サーバー内のファイルに対する不正アクセス(ディレクトリ・トラバーサル)
  * OS コマンドの呼び出し(OS コマンド・インジェクション)

**4.10.1: ディレクトリ・トラバーサル**

* 概要
  * 外部からパラメータの形でサーバー上のファイル名を指定できる Web アプリケーションでは、ファイル名に対するチェックが不十分であると、アプリケーションの意図しないファイルに対して閲覧や改竄、削除ができる場合がある
    * この脆弱性をディレクトリ・トラバーサル脆弱性と呼ぶ
  * ディレクトリ・トラバーサル脆弱性による影響は以下の通り
    * Web サーバー内のファイルの閲覧
      * 重要情報の漏洩
    * Web サーバー内のファイルの改竄、削除
      * Web コンテンツ改竄によるデマ、誹謗中傷の書き込み
      * マルウェアのサイトに誘導する仕組みの書き込み
      * スクリプトファイルや設定ファイル削除によるサーバー機能停止
      * スクリプトファイル改竄による任意のサーバースクリプト実行
  * 対策は以下のいずれか
    * 外部からファイル名を指定できる仕様を避ける
    * ファイル名にディレクトリ名が含まれないようにする
    * ファイル名を英数字に限定する
* 脆弱性が生まれる原因
  * 以下の 3 つがある
    * ファイル名を外部から指定できる
    * ファイル名として、絶対パスや相対パスの形で異なるディレクトリを指定できる
    * 組み立てたファイル名に対するアクセスの可否をチェックしていない
* 対策
  * 以下のいずれかを実施する
    * 外部からファイル名を指定できる仕様を避ける
      * ファイル名を固定にする
      * ファイル名をセッション変数に保持する
      * ファイル名を直接指定するのではなく、番号などで間接的に指定する
    * ファイル名にディレクトリ名が含まれないようにする
      * ファイル名にディレクトリ名が含まれないようにすれば、アプリケーションの想定したディレクトリのみにアクセスすることになり、ディレクトリ・トラバーサル脆弱性の余地はなくなる
    * ファイル名を英数字に限定する
      * ファイル名の文字種を英数字に限定すれば、ディレクトリ・トラバーサル攻撃に用いる記号文字が使えなくなるので、ディレクトリ・トラバーサルの対策になる

**4.10.2: 意図しないファイル公開**

* 概要
  * 外部から閲覧されると困るファイルを Web サーバーの公開ディレクトリに配置している場合がある
  * この場合、ファイルに対する URL がわかると、秘密ファイルの閲覧が可能になる
  * 意図しないファイル公開による影響は以下の通り
    * 重要情報の漏洩
* 脆弱性が生まれる原因
  * 意図しないファイル公開が起こる原因は、非公開のファイルを公開ディレクトリに置いたこと
  * 公開ディレクトリに置かれたファイルが外部から閲覧できる条件は以下の通り
    * ファイルが公開ディレクトリに置かれている
    * ファイルに対する URL を知る手段がある
    * ファイルに対するアクセス制限がかかっていない
  * ファイルに対する URL を知る手段には以下がある
    * ディレクトリ・リスティングが有効
      * [ディレクトリリスティングを無効にしよう。ApacheWEBサーバーの脆弱性](https://lpeg.info/security/directory_listing.html)
    * ファイル名が日付やユーザ名、連番など類推可能
    * user.dat、data.txt などのありがちな名前
    * エラーメッセージや、他の脆弱性によりファイルのパス名がわかる
    * 外部サイトからリンクされるなどして検索エンジンに登録される
  * ファイルに対するアクセス制限のみで閲覧を禁止することは危険
    * 設定をうっかり変更してしまうミスがありうる
* 対策
  * 根本対策は、非公開ファイルを公開ディレクトリに置かないこと
  * そのためには以下を推奨する
    * アプリケーションの設計時に、ファイルの安全な格納場所を決める
    * レンタルサーバーを契約する場合は、非公開ディレクトリが利用できることを確認する

#### 4.11: OS コマンド呼び出しの際に発生する脆弱性

**4.11.1: OS コマンド・インジェクション**

* 概要
  * Web アプリケーションの開発に用いる言語の多くはシェル経由で OS コマンドを呼び出す機能を提供しており、シェルを呼び出せる機能の使い方に問題があると、意図しない OS コマンドが実行可能になる場合がある
    * これを OS コマンド・インジェクション脆弱性と呼ぶ
  * 典型的には、以下のような攻撃シナリオ
    * 1: 攻撃用ツールを外部からダウンロードする
    * 2: ダウンロードしたツールに実行権限を与える
    * 3: OS の脆弱性を内部から攻撃して管理者権限を得る
    * 4: Web サーバーは攻撃者の思いのままになる
  * Web サーバーの悪用は様々だが、例えば以下の悪用が可能
    * Web サーバー内のファイルの閲覧・改竄・削除
    * 外部へのメールの送信
    * 別のサーバーへの攻撃(踏み台と呼ばれる)
    * 暗号通貨の採掘(マイニング)
* 攻撃手法と影響
* 脆弱性が生まれる原因
  * 脆弱性が生まれる原因は、以下の 3 つすべてを満たすこと
    * シェルを呼び出す機能(system, open)のある関数を利用している
    * シェル呼び出しの機能のある関数にパラメータを渡している
    * パラメータ内に含まれるシェルのメタ文字をエスケープしていない
* 対策
  * 以下のいずれかによって対策することを推奨する。優先して採用すべき順に以下
    * OS コマンド呼び出しを使わない実装方法を選択する
    * シェル呼び出し機能のある関数の利用を避ける
    * 外部から入力された文字列をコマンドラインのパラメータに渡さない
    * OS コマンドに渡すパラメータを安全な関数によりエスケープする
  * 参考: OS コマンドに渡すパラメータをシェルの環境変数経由で渡す
  * OS コマンド・インジェクション攻撃への保険的対策
    * パラメータの検証
      * パラメータ文字列の文字種の制限
    * アプリケーションの稼働する権限を最小限にする
    * Web サーバーの OS やミドルウェアのパッチ適用

#### 4.12: ファイルアップロードにまつわる問題

**4.12.1: ファイルアップロードの問題の概要**

* アップローダに対する攻撃には、以下がある
  * アップロード機能に対する DoS 攻撃
  * アップロードされたファイルをサーバー上のスクリプトとして実行する攻撃
    * 外部から送り込まれたスクリプトが実行された場合、4.11 節で説明した OS コマンド・インジェクション攻撃と同じ影響があり得る
    * 具体的には情報漏洩、ファイル改竄、他サーバーへの攻撃など
  * 仕掛けを含むファイルを利用者にダウンロードさせる攻撃
    * 利用者がそのファイルを閲覧すると、利用者の PC 上で JavaScript などのクライアントスクリプトの実行や、マルウェア感染などが起こる
  * 閲覧権限のないファイルのダウンロード

**4.12.2: アップロードファイルによるサーバー側スクリプト実行**

* 概要
  * アップローダの中には利用者がアップロードしたファイルを Web サーバーの公開ディレクトリに保存するものがある
  * 加えて、ファイルの拡張子として、php、asp、aspx、jsp などサーバー側で実行可能なスクリプト言語の拡張子が指定できると、アップロードしたファイルをスクリプトとして Web サーバー上で実行できる
  * 外部から送り込んだスクリプトが実行されると、OS コマンド・インジェクションと同様の影響がある
    * Web サーバー内のファイルの閲覧・改竄・削除
    * 外部へのメールの送信
    * 別のサーバーへの攻撃(踏み台と呼ばれる)
    * 暗号通貨の採掘(マイニング)
  * アップロードファイルによるサーバー側スクリプト実行を防止するには、以下のいずれか、あるいは両方を実施する
* 攻撃手法と影響
* 脆弱性が生まれる原因
  * 以下の両方に該当すること
    * アップロードしたファイルが公開ディレクトリに保存される
    * アップロード後のファイル名として、「.php」「.asp」「.aspx」「.jsp」などサーバースクリプトを示す拡張子が指定できる
* 対策
  * 上記のどちらか一方をつぶせば対策になるが、対策抜けが生じる可能性がある
  * このため、ファイルを公開ディレクトリに保存しないという方法を説明する
  * アップロードされたファイルを公開ディレクトリに保存しない場合、このファイルはスクリプト経由でダウンロードする

**4.12.3: ファイルダウンロードによるクロスサイト・スクリプティング**

* 概要
  * アップロードしたファイルを利用者がダウンロードする際に、ブラウザがファイルタイプを誤認する場合がある
    * 例えばアプリケーションが PDF ファイルを想定しているにもかかわらず、PDF データ中に HTML タグが含まれていると、条件によってはブラウザが HTML ファイルとして認識してしまい、PDF ファイルに埋め込まれた JavaScript を実行する場合がある
    * これが、ファイルダウンロードによるクロスサイト・スクリプティング(XSS)
  * この脆弱性を悪用する攻撃者は、HTML や JavaScript を仕込んだ画像ファイルや PDF ファイルなどをアップロードして公開する
    * 利用者のブラウザがこのファイルを HTML として認識すると XSS 攻撃が成立する
  * 対策は以下の通り
    * ファイルの Content-Type を正しく設定する
    * レスポンスヘッダ X-Content-Type-Options: nosniff を指定する
    * ダウンロードを想定したファイルには、レスポンスヘッダとして Content-Disposition: attachment を指定する
    * PDF を扱う場合は、4.12.4 項の対策をあわせて実施する
* 攻撃手法と影響
* 脆弱性が生まれる原因
  * ファイルダウンロードによる XSS が生まれるのは Content-Type の間違った指定が原因
    * Content-Type の指定が間違っていると、ブラウザがコンテンツを HTML と解釈し、コンテンツ中の JavaScript が実行されてしまう可能性がある
    * 仮に Content-Type が間違っていない場合でも、ブラウザが扱うことのできない Content-Type の場合には XSS になる場合がある
  * Content-Type と IE の挙動の関係
    * ダウンロードコンテンツを IE が処理する場合、その Content-Type が IE の扱えるものかどうかで挙動が変わる
      * IE の扱うことのできる Content-Type の場合は、IE は Content-Type に従って処理する
      * 扱えない種類である場合は、IE は URL に含まれる拡張子からファイルタイプを判定する
* 対策
  * ファイルアップロード時の対策
    * 拡張子が許可されたものかチェックする
  * ファイルダウンロード時の対策
    * Content-Type を正しく設定する(必須)
    * レスポンスヘッダ X-Content-Type-Options: nosniff を指定する(必須)
      * これを指定することにより、Content-Type ヘッダのみから Content-Type を解釈するようになる
      * X-Content-Type-Options: nosniff を指定すると、仮に Content-Type が PDF として正しくなくても text/html でなければ JavaScript の実行までは至らない
    * 必要に応じて Content-Disposition ヘッダを指定する
      * ダウンロードしたファイルをアプリケーションで開くのではなく、ダウンロードできさえすれば良い場合は「Content-Disposition: attachment」というレスポンスヘッダを指定する方法もある
        * この場合は Content-Type も「application/octet-stream」にすると、ファイルタイプ上も「ダウンロードすべきファイル」という意味になる
    * PDF を扱う場合は、4.12.4 項の対策をあわせて実施する
  * その他の対策
    * 仕様策定時に、以下のようなチェックを行うかどうか検討するとよい
      * ファイルサイズ以外の縦横サイズ、色数などのチェック
      * 画像として読み込めるかどうかのチェック
      * ウィルス・スキャン(詳しくは 8.4)
      * コンテンツの内容チェック(自動あるいは手動)
        * アダルトコンテンツ
        * 著作権を侵害するコンテンツ
        * 法令、公序良俗に反するコンテンツ
        * その他

**4.12.4: PDF の FormCalc によるコンテンツハイジャック**

* 概要
  * PDF は FormCalc と呼ばれるスクリプト言語が使用でき、PDF ドキュメントに FormCalc スクリプトを埋め込むことができる
    * Adobe Acrobat Reader に実装された FormCalc には URL 関数という機能があり、HTTP リクエストを呼び出し、結果を受け取ることができる
  * この FormCalc の URL 関数を用いた仕掛けを組み込んだ PDF ファイルをアップロードすることにより、正規ユーザーに成りすましを行う攻撃手法が考案されている
* 攻撃手法と影響
* 脆弱性が生まれる原因
  * Acrobat Reader の仕様が見直されることが本筋だが、Web アプリケーション側で対応をとらざるを得ないのが現状
* 対策
  * 以下の両方を実施すること
    * PDF ファイルはブラウザ内で開かず、ダウンロードを強制する
    * PDF を object 要素や embed 要素では開けない仕組みを実装する
      * ファイルのダウンロードを強制するレスポンスヘッダを指定しても、罠のサイトで object 要素や embed 要素を用いている場合、これらのレスポンスヘッダは無視され、FormCalc スクリプトが動いてしまう
      * やり方はいくつかあるが、もっとも単純な方法として、ファイルダウンロードを POST リクエストに限定するというものがある
      * オブジェクトの単なる参照は GET メソッドを用いるのが HTTP のルールだが、Adobe Acrobat Reader のセキュリティ上好ましくない仕様の対処なので、ルールからの逸脱は許容することにする

#### 4.13: インクルードにまつわる問題

**4.13.1: ファイルインクルード攻撃**

* 概要
  * PHP などのスクリプト言語には、スクリプトのソースの一部を別ファイルから読み込む機能がある
    * このファイルを外部から指定できる場合、アプリケーションが意図しないファイルを指定することにより、脆弱となる場合がある
    * これをファイルインクルード脆弱性と呼ぶ
  * ファイルインクルード攻撃による影響は以下
    * Web サーバー内のファイルの閲覧による情報漏洩
    * 任意スクリプトの実行による影響。典型的には以下
      * サイト改竄
      * 不正な機能実行
      * 他サイトへの攻撃(踏み台)
  * ファイルインクルード脆弱性の対策は以下のいずれかを実施する
    * インクルードするパス名に外部からのパラメータを含まない
    * インクルードするパス名に外部からのパラメータを含める場合は、英数字限定にする
* 攻撃手法と影響
  * ファイルインクルードによる情報漏洩
  * スクリプトの実行 1: ファイルインクルード攻撃(RFI)
  * スクリプトの実行 2: セッション保存ファイルの悪用
    * RFI が禁止されている場合でも、Web サーバー上に任意の内容を書き込める場合には、ファイルインクルード攻撃によりスクリプトを実行される可能性がある
    * 考えられるシナリオは以下
      * ファイルのアップロードが可能なサイト
      * セッション変数の保存先としてファイルを使用しているサイト
    * いずれもファイル名を推測できることが条件
* 脆弱性が生まれる原因
  * 以下の 2 つ
    * インクルードファイル名を外部から指定できる
    * インクルードすべきファイル名かどうかの妥当性チェックをしていない
* 対策
  * ファイルインクルード脆弱性の対策はディレクトリ・トラバーサル脆弱性の場合と同様
    * 外部からファイル名を指定する仕様を避ける
    * ファイル名を英数字に限定する

#### 4.14: 構造化データの読み込みにまつわる問題

**4.14.1: eval インジェクション**

* 概要
  * 文字列をソースコードとして解釈実行する eval と呼ばれる機能や関数があり、各言語のソースコードをデータとして扱える
  * eval の利用法に問題がある場合、外部から送り込んだスクリプトを実行される場合がある
    * このような攻撃を eval インジェクション攻撃と言う
  * 影響例は以下
    * 情報漏洩
    * サイト改竄
    * 不正な機能実行
    * 他サイトへの攻撃(踏み台)
    * 暗号通貨の採掘(マイニング)
  * 対策は以下のいずれかを実施すること
    * eval に相当する機能を使わない
    * eval の引数には外部からのパラメータを含めない
    * eval に与える外部からのパラメータを英数字に限定する
* 攻撃手法と影響
* 脆弱性が生まれる原因
  * eval を用いることがそもそも危険である
  * eval に与えるパラメータのチェックがされていない
* 対策
  * eval(同等機能を含む)を使わない
  * eval の引数に外部からのパラメータを指定しない
  * eval の与える外部からのパラメータを英数字に限定する
    * スクリプトの注入に必要な記号文字が使えなくなるので、スクリプト注入ができなくなる

**4.14.2: 安全でないデシリアライゼーション**

* 概要
  * アプリケーション内部の構造を持ったデータを保存・伝送する目的でバイト列に変換することをシリアライズと言い、シリアライズされたデータから元のデータに戻すことをデシリアライズと言う
  * シリアライズされたデータが信頼できない場合、デシリアライズ処理の際に意図しないオブジェクトがアプリケーション内に生成され、場合によっては任意のコードを実行されてしまう
  * 安全でないデシリアライゼーションによる影響は、OS コマンド・インジェクション攻撃と同じ
  * 影響例は以下
    * 情報漏洩
    * サイト改竄
    * 不正な機能実行
    * 他サイトへの攻撃(踏み台)
    * 暗号通貨の採掘(マイニング)
  * 対策は、以下のいずれかを実施すること
    * シリアライズ・デシリアライズ機能を使わない
    * デシリアライズ処理には外部からのパラメータを含めない
* 攻撃手法と影響
* 脆弱性が生まれる原因
* 対策
  * 以下が考えられる
    * シリアライズ形式ではなく、JSON 形式によりデータを受け渡す
    * クッキーや hidden パラメータではなくセッション変数など書き換えできない形でシリアライズ形式のデータを受け渡す
    * HMAC などの改竄検知の仕組みを導入してデータが改竄されていないことを確認する

**4.14.3: XML 外部実体参照(XXE)**

* 概要
  * XML には外部実体参照という機能があり、外部ファイルの内容を取り込むことができる
  * XML データを外部から受け取るプログラムは、外部実体参照の形で Web サーバー内部のファイルなどを不正に読み取られる可能性がある
    * この攻撃を XML 外部実体参照攻撃と呼び、XML 外部実体参照攻撃ができてしまう脆弱性を XML 外部実体参照脆弱性と呼ぶ
  * XML 外部実体参照という用語は長いので、以降は XXE(XML External Entity) と省略する
* 攻撃手法と影響
* 脆弱性が生まれる原因
  * XML の外部実体参照を使うと、XML 中に外部のファイルを流し込むことができることは XML がもともと持つ機能
  * したがって、XXE は XML の機能を悪用するものであり、プログラムにコーディング上のバグがあるというわけではない
* 対策
  * 外部実体参照を禁止する指定を行うことが基本

#### 4.15: 共有資源やキャッシュに関する問題

**4.15.1: 競合状態の脆弱性**

* 概要
  * 共有資源とは、複数のプロセスやスレッドから同時に利用している変数、共有メモリ、ファイル、データベースなどのこと
  * 共有資源に対する排他制御が不十分な場合、競合状態の脆弱性の原因となる場合がある
  * 影響の代表例として以下がある
    * 別人の個人情報などが画面に表示される
    * データベースの不整合
    * ファイルの内容の破壊
  * 対策は以下のいずれかを実行すること
    * 可能であれば共有資源の利用を避ける
    * 共有資源に対する適切な排他制御を行う
* 攻撃手法と影響
* 脆弱性が生まれる原因
  * 以下の 2 つ
    * 変数 name は共有変数である
    * 共有変数 name の排他制御をしていない
* 対策
  * 以下のいずれかを実施する
    * 可能であれば共有資源を使用しない
    * 共有資源に対して排他制御を行う

**4.15.2: キャッシュからの情報漏洩**

* 概要
  * キャッシュは有効な技術だが、過剰にキャッシュが働いてしまうと、個人情報漏洩などの原因になる
* 脆弱性が生まれる原因
  * アプリケーション側のキャッシュ制御不備
  * キャッシュサーバーの設定不備
* 対策
  * キャッシュからの情報漏洩の原因は、不適切なキャッシュ制御にあり、典型的には「キャッシュすべきでないリソースをキャッシュした」ことが原因になる
  * 以下の両方を実施すること
    * アプリケーション側でキャッシュ制御用の適切なレスポンスヘッダを設定する
    * キャッシュサーバー側でキャッシュ制御の適切な設定を行う

#### 4.16: Web API 実装における脆弱性

**4.16.1: JSON と JSONP の概要**

* JSON とは
  * Web API で用いられる Ajax(Asynchronous JavaScript + XML) は、その名が示すようにもともと XML をデータの受け渡しに使っていたが、XML は表現がやや冗長であるという問題があった
    * このため、XML に代わるデータ交換形式として、JavaScript のオブジェクトリテラルの形式が注目され、これをデータ交換形式に発展させたものが JSON(JavaScript Object Notation)
* JSONP とは
  * JavaScript の XMLHttpRequest は、もともと同一オリジンポリシーの制約があり、異なるオリジンからのデータを取得できないという課題があった
    * この課題を解決するために CORS が規定されたが、CORS ができる前に同一オリジンポリシーの枠内で異なるオリジンのサーバーからデータを取得するいくつかの方法が考案された。その代表的な方法の 1 つが JSONP(JSON with Padding)
  * JSONP は XMLHttpRequest ではなく、script 要素を用いて外部の JavaScript を直接実行することによりデータを取得する

**4.16.2: JSON エスケープの不備**

* 概要
  * API において JSON 文字列生成時のエスケープ処理に不備があると、意図しない JavaScript が JSON データに混入する場合がある
* 攻撃手法と影響
* 脆弱性が生まれる原因
  * 以下の 2 つの条件が揃うこと
    * JSON 文字列の生成時に適切なエスケープ処理などが行われていない
    * JSON の評価に eval 関数などを用いているか、JSONP を用いている
* 対策
  * 文字列連結による JSON データ生成をやめ、信頼できるライブラリを用いて JSON を生成する
  * eval 関数ではなく、JSON.parse などの安全な API で JSON を解釈する
* また、保険的対策として以下を強く推奨する
  * JSONP を避け、CORS を用いた Web API に移行する

**4.16.3: JSON 直接閲覧による XSS**

* 概要
  * JSON を返す Web API は、通常 XMLHttpRequest によるアクセスを想定したものだが、API が返すレスポンスデータをブラウザで直接閲覧させることにより攻撃が可能になる場合がある
* 対策
  * MIME タイプを正しく設定する(必須)
  * レスポンスヘッダ X-Content-Type-Options: nosniff を出力する(強く推奨)
  * 小なり記号などを Unicode エスケープする(推奨)
  * XMLHttpRequest など CORS 対応の機能だけから呼び出せるようにする(推奨)

**4.16.4: JSONP のコールバック関数名による XSS**

* 概要
  * JSONP は JSON データを引数とするコールバック関数呼び出しの形式をとるが、このコールバック関数の名前は固定ではなく外部から指定できるようにするケースが多い
  * 外部から指定したパラメータにより表示内容(関数名)が制御できることから、コールバック関数名によるクロスサイト・スクリプティングが可能になる場合がある
* 脆弱性が生まれる原因
  * 以下の 2 つ
    * 外部から指定されたコールバック関数名を検証しないでそのまま表示している
    * MIME タイプを text/javascript とするべきところを text/html としている
* 対策
  * コールバック関数名の文字種と文字数を制限する
    * 攻撃に必要な「<」などが使用できなくなれば、攻撃を回避できる
  * MIME タイプを正しく設定する
    * JSONP の MIME タイプは text/javascript なので、JSONP を返す API も MIME タイプとしては text/javascript を返すべき
    * この場合、ブラウザはレスポンスを HTML として解釈しないので、script 要素は解釈されず、JavaScript としての実行もされない

**4.16.5: Web API のクロスサイト・リクエストフォージェリ**

* Web API に対する CSRF 攻撃経路
  * GET リクエストによる攻撃
    * CSRF 脆弱性はサーバー側の「重要な処理」、すなわち副作用に伴う API が対象になるので、本来 GET リクエストで「重要な処理」を受け付けないように実装すべきだが、現実には GET リクエストで更新処理などの「重要な処理」を受け付ける API は見かける
    * GET リクエストで CSRF 攻撃ができる場合は、パラメータは攻撃者が自由に設定できる
  * HTML フォームによる攻撃
    * HTML フォームからの CSRF 攻撃では、POST 値の送信方式としては以下の MIME タイプのみが使える
      * text/plain: エンコードせずそのまま送信(通常使用されない)
      * application/x-www-form-urlencoded: 通常のフォーム
      * multipart/form-data: ファイルアップロードで用いる形式
  * クロスオリジン対応の XMLHttpRequest による攻撃(シンプルなリクエスト)
  * XMLHttpRequest による攻撃(プリフライトリクエストが必要なケース)
* 対策
  * 代表的な方法
    * CSRF トークン(セッション変数にトークンを保持)
    * 二重送信クッキー
    * カスタムリクエストヘッダによる対策
  * 加えて、共通の対策として書きを実施する
    * 入力データの MIME タイプ(application/json など)を検証する
    * CORS を適切に実装する
  * CSFR トークン
    * API 呼び出しの JavaScript にトークンを渡す方法が問題になる。具体的には以下の方法がある
      * Web ページに hidden パラメータやカスタムデータ属性で保存し、JavaScript から参照する
      * CSRF トークンを返す API を用意する

**4.16.6: JSON ハイジャック**

* 概要
  * JSON データを script 要素で受け取ることはできず、JSONP は JSON をコールバック関数の引数にすることで、アプリケーションからデータを受け取れる形にしている
  * しかし、なんらかの方法で JSON データを script 要素で受け取ることができないかが研究されており、その手法は JSON ハイジャックと呼ばれる
  * JSON ハイジャックはブラウザがたいさくすべきものと考えられるが、過去に JSON ハイジャックができる脆弱性が報告されていることから、アプリケーション側でも JSON ハイジャック対策をしておいたほうが好ましい
* 攻撃手法と影響
* 対策
  * X-Content-Type-Options: nosniff ヘッダの付与(強く推奨)
    * script タグで読み込むコンテンツの MIME タイプを厳格にチェックし、JSON や CSV などの読み込みを拒否する
  * リクエストヘッダ X-Requested-With: XMLHttpRequest の確認(推奨)

**4.16.7: JSONP の不適切な利用**

* JSONP はもともと Ajax の同一オリジンポリシーの制限をすり抜けるために考案されたという事情もあり、使い方を間違えると簡単に脆弱性に直結してしまう
* このため、JSONP は極力使用をやめ、CORS 対応の API に移行することが望ましい
* JSONP による秘密情報提供
  * JSONP には CORS のようなアクセス制御の仕組みがないため、JSONP による情報公開は公開情報の提供にとどめ、秘密情報の提供は避けるべき
* 脆弱性が生まれる原因
  * JSONP には呼び出し元のオリジンに対する制御の機能がないこと
* 対策
  * JSONP をやめ、CORS 対応の XMLHttpRequest を用いること
  * もはや JSONP を用いる積極的な理由はない

**4.16.8: CORS の検証不備**

* CORS はよく考えられた仕様で、素直にこれを使う限りはオリジンに関する問題が起きる余地はない
  * しかし、利用者側の無知や手抜きなどにより、問題が起こる場合はある
* オリジンとして "\*" を指定する
  * 公開情報を提供するなどでオリジンの制限がない場合はこれでいいが、非公開情報を扱う場合はこれだと情報漏洩の危険性がある
* オリジンのチェックをわざと緩和してしまう
  * 開発に際しては個々のヘッダの意味を理解した上で、本当に必要な許可だけ与えるべき

**4.16.9: セキュリティを強化すべきレスポンスヘッダ**

* Web API に限らず、HTTP レスポンスヘッダとして常に出力しておくだけでブラウザのセキュリティ機能を強化する仕組みが用意されている
* 代表的なもの
  * X-Frame-Options
    * これを指定すると frame や iframe の内部に表示できなくなる
  * X-Content-Type-Options
    * X-Content-Type-Options: nosniff という形で使用する
    * これによりブラウザは、MIME タイプの解釈を厳密にすることで、MIME タイプをブラウザに誤認させるタイプの攻撃や JSON ハイジャック攻撃などを緩和する
  * X-XSS-Protection
    * 下記の 2 点の役割がある
      * 利用者が XSS フィルタの有効化・無効化設定をしていても、当該ページについて XSS フィルタの設定を上書きする
      * XSS フィルタの動作モードを指定する
  * Content-Security-Policy(CSP)
    * Content Security Policy は主にクロスサイト・スクリプティング攻撃を緩和するためのセキュリティ機能としてブラウザに実装されつつある
    * 最も基本的かつ厳しい設定は `Content-Security-Policy: default-src 'self'`
    * この指令により、スクリプト、画像、CSS などのすべてのメディアをサイト自身のオリジンからのみ読み込むようになる
  * Script-Transport-Security(HTTP Strict Transport Security; HSTS)
    * HTTP Script Transport Security は HTTPS で接続を強制するための指令
    * ただし、HSTS をいったん指定すると、HTTPS をやめることが難しくなることや、自己署名証明書など信頼できない証明書が使えなくなるというデメリットもあるため、HSTS は計画的な導入を推奨する

#### 4.17: JavaScript の問題

**4.17.1: DOM Based XSS**

* 概要
  * 4.3 でも XSS について説明したが、これはサーバー側のプログラムの不備が原因で発生するものだった
  * 一方、JavaScript による処理の不備が原因で XSS となる場合もあり、DOM Based XSS と呼ばれている
* 攻撃手法と影響
  * innerHTML による DOM Based XSS
  * document.write による DOM Based XSS
  * XMLHttpRequest の URL 未検証の問題
  * jQuery のセレクタの動的生成による XSS
  * javascript スキームによる XSS
* 脆弱性が生まれる原因
  * DOM 操作の際に外部から指定された HTML タグなどが有効になってしまう機能を用いている
  * 外部から指定された JavaScript が動く eval などの機能を用いている
  * XMLHttpRequest の URL が未検証である
  * location.href や src 属性、href 属性の URL が未検証である
* 対策
  * 以下のいずれかを行う
    * 適切な DOM 操作あるいは記号のエスケープ
    * eval、setTimeout、Function コンストラクタなどの引数に文字列形式で外部からの値を渡さない
    * URL のスキームを http か https に限定する
    * jQuery のセレクタは動的生成しない
    * 最新のライブラリを用いる
    * XMLHttpRequest の URL を検証する

**4.17.2: Web ストレージの不適切な使用**

* Web ストレージとは
  * 近年のブラウザでは、クッキーよりも高性能なストレージとして、Web ストレージを用意している
  * クッキーは自動的にリクエスト毎にサーバーに送信されるが、Web ストレージは JavaScript から書き込み、読み出し、削除ができるだけでサーバーへの送信は自動的には行われない
  * Web ストレージには、localStrage と sessionStrage の 2 種類がある
    * localStrage は永続的なストレージ、sessionStrage はブラウザのタブが開いている間だけ保持されるストレージ
* Web ストレージには何を保存してよいか
  * Web ストレージは JavaScript により読み書きできるストレージであり、JavaScript からのアクセスを禁止できない
  * そのため、Web アプリケーションにクロスサイト・スクリプティング脆弱性があると、Web ストレージの内容は漏洩することになる
    * この点は httpOnly 属性をつけたクッキーとは異なる特性
  * Web ストレージの内容が XSS により漏洩しやすいという特性から、重要な情報は Web ストレージには保存しないようにする
* Web ストレージの不適切な利用例
  * Web ストレージに秘密情報を保存していた
  * Web ストレージに保存した情報が、XSS や postMessage により漏洩する
  * Web ストレージが XSS や postMessage 経由で改ざんされる
  * Web ストレージを経由した DOM Based XSS

**4.17.3: postMessage 呼び出しの不備**

* postMessage とは
  * iframe や window\.open で開いたウィンドウなど、複数のウィンドウが異なるオリジンで協調して動作する環境で、メッセージやデータのやり取りを行う汎用的な仕組みが postMessage
* メッセージ送信先の未確認
  * これだと罠のサイトにも秘密情報を送信してしまう
* メッセージ送信元の未確認

**4.17.4: オープンリダイレクト**

* オープンリダイレクトについては 4.7.1 ですでに説明したが、オープンリダイレクト脆弱性が混入するのはサーバー側の処理に限らず、JavaScript の処理によっても混入する可能性がある
* 対策
  * 基本的にサーバーサイドのものと考え方は同じだが、処理を複雑にしないという意味から、以下のいずれかにするとよい
    * リダイレクト先の URL を固定にする
    * リダイレクト先 URL を直接指定せず番号などで指定する

### 5: 代表的なセキュリティ機能

#### 5.1: 認証

* 認証(Authentication)とは、利用者が確かに本人であることをなんらかの手段で確認すること

**5.1.1: ログイン機能**

* ログイン機能に対する攻撃
  * SQL インジェクション攻撃によるログイン機能のバイパス
  * SQL インジェクション攻撃によるパスワードの入手
  * ログイン画面に対するパスワード試行
  * ソーシャルエンジニアリングによるパスワード入手
  * フィッシングによるパスワード入手
* ログイン機能が破られた場合の影響
  * Web アプリケーションが不正ログインされると、攻撃者は利用者の持つ権限をすべて利用できることになる
* 不正ログインを防ぐためには
  * 必要不可欠な条件は以下の 2 つ
    * SQL インジェクションなどセキュリティバグ(狭義の脆弱性)をなくす
    * パスワードを予測困難なものにする
  * 積極的なパスワードポリシーのチェック
    * 桁数に関するもの(例: 8 桁以上)
    * 文字種に関するもの
    * ユーザ ID と同じパスワードの禁止
    * パスワード辞書に載っているありがちな単語の禁止

**5.1.2: パスワード認証を狙った攻撃への対策**

* オンラインでのブルートフォース攻撃への対抗策としては、アカウントロックが有効
* 基本的なアカウントロック
  * 以下のように実装する
    * ユーザ ID ごとにパスワード間違いの回数を超える
    * パスワード間違いの回数が上限値を超えると、アカウントをロックする。ロックされたアカウントはログインする
    * アカウントロックが発生した場合はメールなどで対象利用者と管理者に通知する
    * 正常にログインした場合は、パスワード間違いのカウンタをクリアする
  * ロックされたアカウントの再有効化は、以下のルールで行うと良い
    * アカウントロックから 30 分経過した場合、自動的に再有効化される
    * 管理者が、なんらかの方法で本人確認した後に再有効化する
* パスワード認証に対する攻撃のバリエーションと対策
  * 辞書攻撃
    * パスワードの可能性をすべて試すのではなく、使用頻度の高いパスワード候補から順に試す方法
  * ジョーアカウント探索
    * ユーザ ID と同じ文字列をパスワードに設定しているアカウントをジョーアカウントという
  * リバースブルートフォース攻撃
    * 通常のブルートフォース攻撃がユーザ ID を固定して、パスワードの方を入れ替えながらログイン試行するのに対して、リバースブルートフォース攻撃はパスワードの方を固定して、ユーザ ID を取り替えながらログイン試行する
  * パスワードスプレー攻撃
    * ID もパスワードも固定せずに、少数のパスワード候補を ID を変えながら試していく攻撃
  * パスワードリスト攻撃
    * 攻撃対象サイトとは別のサイトから漏洩した ID とパスワードの一覧を用いてログイン試行する攻撃
  * パスワードを狙った攻撃への対策
    * 二段階認証の実装
    * 積極的なパスワードチェック
      * パスワード登録時に辞書によるチェックを行い、ありがちなパスワードやユーザ ID と同じパスワードを拒否する
    * ログイン失敗率の監視

**5.1.3: パスワードの保存方法**

* パスワードの保護の必要性
  * パスワードの悪用により、情報漏洩以外の被害が発生する可能性がある。以下が代表的なもの
    * パスワードリスト攻撃への悪用
    * 該当利用者の権限で使える機能の悪用(物品購入、送金など)
    * 該当利用者の権限でのデータの投稿、変更、削除
* 暗号化によるパスワード保護と課題
  * 暗号を使う場合は以下が課題となる
    * 安全な暗号アルゴリズムの選定
    * 暗号化・複合処理の安全な実装
    * 鍵の生成
    * 鍵の保管
    * 暗号アルゴリズムが危殆化した場合の再暗号化
* メッセージダイジェストによるパスワード保護と課題
  * メッセージダイジェストとは
    * 任意の長さのデータを固定長のデータ(メッセージダイジェスト、あるいはハッシュ値)に圧縮する関数をハッシュ関数といい、セキュリティ上の要件を満たすハッシュ関数を暗号学的ハッシュ関数という
  * メッセージダイジェストを用いてパスワードを保護する
    * メッセージダイジェストの状態で保存し、ログイン時にはメッセージダイジェストのまま照合する
    * メッセージダイジェストによりパスワードが安全に保存できる理由は、ハッシュ関数の以下の特性によるもの
      * ハッシュ値から元データを得ることが困難(一方向性)
      * 異なる入力から得られるハッシュ値が一致する確率が極めて低い(衝突耐性)
  * 脅威 1: オフラインブルートフォース攻撃
  * 脅威 2: レインボーテーブル
    * パスワードのハッシュ値をあらかじめ総当りで算出して表にしておき、解読の際は表の参照を行えば、高速に検索できる
  * 脅威 3: ユーザ DB 内にパスワード辞書を作られる
    * 攻撃者がダミーのユーザを多数登録して、ユーザ DB 上に「パスワード辞書」を作ってしまう
  * ハッシュ解読対策の考え方
    * 対策 1: ソルト
      * ソルトはハッシュの元データに追加する文字列のこと
      * ソルトにより、見かけのパスワードを長くするとともに、ソルトをユーザごとに異なるものにすることで、パスワードが同じでも異なるハッシュ値が生成される
    * 対策 2: ストレッチング
      * ブルートフォース攻撃に対抗するためには、ハッシュ計算の速度を遅くする必要がある
      * 2 つのアプローチがある
        * 1 つは、ハッシュ計算を繰り返し行うこと(ストレッチングと呼ばれる)
        * もう 1 つは、パスワード保存に適した専用の「遅い」ハッシュ関数を用いること
    * password\_hash 関数の利用

**5.1.4: 自動ログイン**

* 従来、自動ログインはセキュリティの観点から「好ましくないもの」と言われてきた
* しかし、筆者はサイトの性格によっては自動ログインを許容してもよいと考えている
  * Web の利用が浸透した結果、ログイン状態を継続することを前提としたサービスが増加した(例: Google)
  * 頻繁にログイン、ログアウトが要求されると、利用者が単純なパスワードをつけがちで、かえって危険度が増す
* 自動ログインの安全な実装方法
  * 以下の 3 種類が考えられる
    * セッションの寿命を延ばす
    * トークンを使う
    * チケットを使う
  * セッションの寿命を延ばす
    * この場合、ログイン状態を保持しないユーザについてもセッションタイムアウトの時間が伸びる
  * トークンによる自動ログイン
    * ログイン時にトークンを発行
    * ログイン状態の確認と自動ログイン
    * ログアウト
  * 認証チケットによる自動ログイン
    * 認証チケットとは、認証情報(ユーザ名、有効期限など)をサーバーの外に持ち出せるようにしたもの
  * 3 方式を比較すると、トークン方式がもっとも好ましいと考えられる。トークン方式のメリットは以下
    * 自動ログインを選択しない利用者に影響を与えない
    * 複数端末からログインしている場合に一斉にログアウトできる
    * 管理者が、特定利用者のログイン状態をキャンセルできる
    * クライアント側に秘密情報が渡らないので解析されるリスクがない
* 自動ログインのリスクを低減するには
  * 自動ログインのデメリットとして、認証状態が長く続くために、XSS や CSRF などの受動的攻撃のリスクが高まることがある
  * これに対しては、重要情報の閲覧や、重要な処理に先立ちパスワード入力を要求する方法がある

**5.1.5: ログインフォーム**

* ログインフォームの一般的なガイドラインは以下
  * パスワード入力欄はマスク表示する
  * HTTPS を利用する

**5.1.6: エラーメッセージの要件**

* エラーメッセージには攻撃者のヒントとなる情報は含むべきでない
* ID とパスワードのどちらが間違いかわかるとまずい理由
  * 攻撃者の探索が簡単になってしまう
* ID とパスワードを二段階で入力するサイトの増加
  * ユーザの負担を減らすことにより、複雑なパスワードをつけるように誘導する

**5.1.7: ログアウト機能**

* ログアウト処理の要件は以下の通り
  * ログアウト処理は副作用があるので POST メソッドでリクエストする
  * ログアウト処理ではセッションを破棄する
  * 必要な場合、CSRF 対策の対象とする

#### 5.2: アカウント管理

**5.2.1: ユーザ登録**

* 以下のようなセキュリティ上の注意点がある
  * メールアドレスの受信確認
  * ユーザ ID の重複防止
  * ユーザの自動登録への対処(任意)
  * パスワードに関する注意
* メールアドレスの受信確認
  * 実際にメール送信して確認するしかない。具体的には以下の方法がある
    * メールにトークン付き URL を添付して、その URL から処理を継続する
    * メールアドレスを入力した後、トークン(確認番号)入力画面に遷移する。トークンは指定したメールアドレスにメール送信される
* ユーザ ID の重複防止
  * ユーザ ID は一意でなければならないが、Web サイトの脆弱性診断をしていると、まれに重複して登録できてしまうサイトがある
  * 事例 1: パスワードが違えば同じ ID で登録できるサイト
  * 事例 2: ユーザ ID に一意制約をつけられないサイト
* ユーザの自動登録への対処
  * インターネット経由で自由にユーザ登録できる Web サイトの場合、外部から自動操作により大量に新規ユーザを作成される場合がある
  * CAPTCHA による自動登録対策
    * コンピュータによる自動応答ではないことの確認をするために、わざと文字をゆがめた画像を表示させ、利用者に文字列を入力してもらう方法

**5.2.2: パスワード変更**

* パスワード変更の機能的な注意点としては以下がある
  * 現在のパスワードを確認する
  * パスワード変更時にはメールでその旨を通知する
  * 管理者が設定したパスワードや IoT 製品などの初期パスワードは利用者の初回ログイン時にパスワード変更に誘導する

**5.2.3: メールアドレスの変更**

* メールアドレス変更に必要な機能的対策
  * 新規メールアドレスに対する受信確認
  * 再認証
  * メール通知

**5.2.4: パスワードリセット**

* 管理者向けパスワードリセット機能
  * 利用者がパスワードを忘れた際に、管理者に問い合わせして対処してもらう場合がある。このような問い合わせに対応できるように管理者向けパスワードリセット機能が必要になる
  * 利用者からの問い合わせでパスワードをリセットする場合、以下の順序で運用を行う
    * 1: 問い合わせを受け付け、利用者の本人確認を行う
    * 2: 管理者がパスワードをリセットし、利用者に仮パスワードを伝える
    * 3: 利用者は仮パスワードでログインし、直ちにパスワードを変更する
  * 管理者向けパスワードリセット機能の要件は以下の通り
    * 本人確認の際に照会する情報表示機能(本人確認は電話か書面などで)
    * 仮パスワード発行機能。仮パスワードは画面表示せず、メールで利用者に送信される
    * 仮パスワードではパスワード変更のみができる
* 利用者向けパスワードリセット機能
  * 本人確認の方法
    * 通常、登録済みメールアドレスのメールを受け取れることで本人確認するが、加えて二段階認証に用いるスマホアプリの生成する数字を確認することで本人確認を強化する
  * パスワードの通知方法
    * 実現方法として以下の 4 種類が用いられる
      * A: 現在のパスワードをメールで通知する
      * B: パスワード変更画面の URL をメールで通知する
      * C: 仮パスワードを発行して、メールで通知する
      * D: パスワード変更画面に直接遷移する
    * 本書では C または D を推奨する

**5.2.5: アカウントの停止**

* アカウントを停止すべき状況の例
  * 利用者本人からの依頼(PC を盗まれた、スマートフォンを落としたなど)
  * 不正アクセスを受けている場合

**5.2.6: アカウントの削除**

* アカウントの削除は、通常取り消しできない処理なので、成りすましユーザからの悪用防止と CSRF 脆弱性対策を目的として、パスワードの確認(再認証)を要求するとよい

#### 5.3: 認可

**5.3.1: 認可とは**

* 認可とは、認証された利用者に対して権限を与えること。権限の例をいかに示す
  * 認証された利用者のみに認可された機能
    * 退会処理、送金、新規ユーザ作成など
  * 認証された利用者のみに許可された情報の閲覧
  * 認証された利用者のみに許可された編集操作

**5.3.2: 認可不備の典型例**

* 情報リソースの URL を知っていると認証無しで情報が閲覧ができる
* 情報リソースの ID を変更すると権限外の情報が参照できる
* メニューの表示・非表示のみで制御している
* hidden パラメータやクッキーに権限情報を保持している

**5.3.3: 認可制御の要件定義**

* ユーザと権限の対応を設計時に明確にしておくと、開発やテストを正確に実施できる

**5.3.4: 認可制御の正しい実装**

* 正しい認可制御は、情報の操作に先立って以下を確認する
  * この機能を実行(画面を表示)してよいユーザであるか
  * リソースに対する操作(参照、変更、削除など)の権限はあるか
* ユーザ情報は、外部から書き換えのできないセッション変数に保持する

#### 5.4: ログ出力

**5.4.1: ログ出力の目的**

* アプリケーションのログがセキュリティ上も重要である理由は以下の 3 点
  * 攻撃や事故の予兆をログから把握し、早期に対策するため
  * 攻撃や事故の事後調査のため
  * アプリケーションの運用監査のため

**5.4.2: ログの種類**

* Web アプリケーションに関係するログには以下の種類がある
  * Web サーバーのログ
  * アプリケーションログ
  * データベースのログ
* いずれも重要だが、この項ではアプリケーションログについてさらに詳しく説明する。アプリケーションが生成するログは以下のように分類できる
  * エラーログ
  * アクセスログ
  * デバッグログ
    * デバッグログは開発環境やテスト環境で取得すべきもので、本番環境ではデバッグログを取得するべきではない

**5.4.3: ログ出力の要件**

* ログに記録すべきイベント
  * ログイン・ログアウト
  * アカウントロック
  * ユーザ登録・削除
  * パスワード変更
  * 重要情報の参照
  * 重要な操作(物品の購入、送金、メール送信など)
* ログの出力項目
  * アクセス日時
  * リモート IP アドレス
  * ユーザ ID
  * アクセス対象(URL、ページ番号、スクリプト ID など)
  * 操作内容(閲覧、変更、削除など)
  * 操作対象(リソース ID など)
  * 操作結果(成功あるいは失敗、処理件数など)
* ログの保護
  * ログが改竄・削除されるとログが目的を達成できないため、ログに対する不正アクセスができないよう保護する必要がある
* ログの出力先
  * ログ専用のサーバーを用意することが望ましいが、費用がかかるので要件として検討する
* ログの保管期間
* サーバーの時刻合わせ
  * NTP(Network Time Protocol)というプロトコルを用いてサーバーの時刻を合わせることがよく行われる

**5.4.4: ログ出力の実装**

* ログ特有の要求を考慮して設計されたログ出力用のライブラリが開発されている

### 6: 文字コードとセキュリティ

#### 6.1: 文字コードとセキュリティの概要

* 文字コードとは、以下の 2 つの概念を合わせたもの
  * 文字集合
  * 文字エンコーディング(文字符号化方式)

#### 6.2: 文字集合

* 文字集合とは
  * 文字集合(character set)とは、その名の示すように文字を集めたもの
* US-ASCII と ISO-8859-1
  * ISO-8859-1 は US-ASCII を 8 ビットに拡張する形で、英語以外のフランス語やドイツ語など西ヨーロッパ言語の表記に必要なアクセント記号つきのローマ字や記号類を追加したもの
* JIS で規定された文字集合
  * JIS X 0201 は US-ASCII を 8 ビットに拡張することで、片仮名および日本語表記に必要な記号を追加した文字集合
* マイクロソフト標準キャラクタセット
  * JIS X 0201 と JIS X 0208 に加えて、NEC および日本 IBM の拡張文字集合を統合したもの
* Unicode
  * 世界共通の文字集合を制定したいという機運が高まり、Unicode が制定された
* 異なる文字が同じコードに割り当てられる問題
* 文字集合の扱いが原因で起こる脆弱性

#### 6.3: 文字エンコーディング

* 文字エンコーディングとは
  * 歴史的に US-ASCII や ISO-8859-1、JIS X 0201 などの 1 バイト文字集合が先に普及したため、US-ASCII などとの互換性を保ちつつ、JIS X 0208 や Unicode など 2 バイト以上の文字集合を併用する必要性が生じた
  * このための符号化を「文字エンコーディング」あるいは「文字符号化方式」という
* Shift\_JIS
  * 日本で PC が普及し始めた 1980 年代初頭に、PC で漢字を扱うための新しい文字エンコーディングの要求が出てきた。この要求に対して、JIS X 0201 の空き領域に JIS X 0208 をマッピングする形で Shift\_JIS が作られた
* EUC-JP
  * EUC-JP は Unix 上で日本語データを使うために作られた文字エンコーディング
* ISO-2022-JP
  * ISO-2022-JP は 7 ビットの文字エンコーディングで、エスケープシーケンスという符号により文字集合(US-ASCII と JIS X 0208)を切り替える方式。「JIS コード」と呼ばれる場合もある
* UTF-16
  * Unicode はもともと 16 ビット内に世界中のすべての文字を収めるという想定で設計されていたので、文字エンコーディングとして、16 ビットのスカラ値をそのまま利用する方式(UCS-2)が普及していた
  * その後、Unicode が 21 ビットに拡張された際に、UCS-2 と互換性を残しながら BMP(Basic Multilingual Plane) 外の文字をサポートする符号化方式として、UTF-16 が考案された
* UTF-8
  * UTF-8 は Unicode の文字エンコーディングの 1 つで、US-ASCII と互換性のある符号化方式
  * 符号化後の文字データは 1 バイトから 4 バイトの可変長になる

#### 6.4: 文字エンコードによる脆弱性の発生要因まとめ

* 文字コードに起因する脆弱性については以下の 3 つのタイプに分類される
  * 文字エンコードとして不正なバイト列による脆弱性
  * 文字エンコーディングの扱いの不備による脆弱性
  * 文字集合の変更に起因する脆弱性

#### 6.5: 文字コードを正しく扱うために

* 文字コードを正しく扱うためには、以下の 4 つのポイントがある
  * アプリケーション全体を通して文字集合を統一する
  * 入力時に不正な文字エンコーディングをエラーにする
  * 処理の中で文字エンコーディングを正しく扱う
    * マルチバイト文字に対応した処理系・関数のみを使う
    * 関数の引数として文字エンコーディングを明示する
  * 出力時に文字エンコーディングを正しく指定する
    * HTTP レスポンスヘッダの Content-Type を正しく指定する
    * データベースの文字エンコーディングを正しく指定する
    * その他、文字エンコーディングの指定が必要な箇所はもれなく指定する
* その他の対策: 文字エンコーディングの自動判定を避ける

### 7: 脆弱性診断入門

#### 7.1: 脆弱性診断の概要

* Web サイトに対する脆弱性診断には大別してプラットフォーム診断とアプリケーション診断がある
* プラットフォーム診断とは、Web サイトを構成するサーバーやネットワーク機器などに既知の脆弱性がないかを調べるもの
  * 診断対象となるソフトウェアは、OS やミドルウェアなど
* アプリケーション診断とは、Web アプリケーションに対して未知の脆弱性がないかを確認するもの
  * 脆弱性は一種のバグなので、アプリケーション診断はバグを探す作業に似ている
  * アプリケーション診断は大別して動的診断(ブラックボックス診断)とソースコード診断(ホワイトボックス診断)がある
  * 動的診断とは Web アプリケーションを実際に動かすことによる診断、ソースコード診断とはアプリケーションを動かさずにソースコードを確認することによる診断

#### 7.2: 脆弱なサンプルアプリケーション Bad Todo

#### 7.3: 診断ツールのダウンロードとインストール

* この章では以下のツールを使用する(ZAP 以外について説明する)
  * OWASP ZAP
  * Nmap
  * OpenVAS
  * RIPS
* Nmap
  * Nmap は有名なセキュリティ検査ソフトで、特にポートスキャンという機能が有名
  * ポートスキャンとは、サーバーやネットワーク機器などのポートを検索して外部から利用できるものを列挙すること
* OpenVAS
  * OpenVAS は、著名な脆弱性診断 Nessus がオープンソースからクローズドソースにライセンス変更された際に、オープンソース版の Nessus から分岐して開発が進められているオープンソースの脆弱性診断ツール
* RIPS
  * RIPS はオープンソース(GPLv3)で開発が進められていた PHP 用のソースコード脆弱性診断ツール

#### 7.4: Nmap によるポートスキャン

#### 7.5: OpenVAS によるプラットフォーム脆弱性診断

#### 7.6: OWASP ZAP による自動脆弱性スキャン

#### 7.7: OWASP ZAP による手動脆弱性診断

#### 7.8: RIPS によるソースコード診断

#### 7.9: 脆弱性診断実施上の注意

* 脆弱性診断は不正アクセスに極めて類似したアクセスを含んでおり、場合によっては診断対象に悪影響を与える危険性もある
* 診断前の注意点
  * 可能な限り診断専用の環境で脆弱性診断を実施する
  * 必要に応じてバックアップを取得しておく
  * 診断を実施した時のリクエストにおける IP アドレスを関係者に開示する
  * クラウドサービス上の Web アプリに診断する場合には、そのクラウドサービスのルールに則る
  * 診断を実施する場合、運用チームや監視サービス業者に事前に通知する
  * 診断作業によりメールなどの通知が発生する場合は、通知が来ることと診断による通知の見分け方を関係部門に連絡する
* 診断作業中の注意点
  * 診断時には定期的にサイトの状況を確認し、サイト停止、データの破壊などが認められた場合には直ちに診断を中断して、サイト管理者に状況調査を依頼する
  * 診断の内容を適宜メモし、ツールのログを保全する
  * 問い合わせ機能などを診断する際は、診断作業による問い合わせであることがわかるように問い合わせタイトルや本文に記載する
* 診断後の注意点
  * 作業が終了したこと、診断作業終了後も報告書作成などで診断対象サイトにアクセスする場合があることを関係者に連絡する
  * 診断作業により生成したデータや診断用アカウントなどは可能な範囲で削除する

#### 7.10: まとめ

#### 7.11: 脆弱性診断報告書のサンプル

### 8: Web サイトの安全性を高めるために

#### 8.1: Web サーバーへの攻撃経路と対策

* Web サイトのセキュリティを強化するためには、アプリケーションの脆弱性を解消するだけでは不十分で、Web サーバーなど基盤ソフトウェアの安全性を高めることも重要

**8.1.1: 基盤ソフトウェアの脆弱性をついた攻撃**

**8.1.2: 不正ログイン**

**8.1.3: 対策**

* Web サーバーへの攻撃の対策としては以下が重要
  * 適切なサーバー基盤を選定する
  * 機能提供に不要なソフトウェアは稼働させない
  * 脆弱性の対処をタイムリーに行う
  * 一般公開する必要のないポートやサービスはアクセス制限する
  * 認証の強度を高める

#### 8.2: 成りすまし対策

**8.2.1: ネットワーク的な成りすましの手口**

* DNS に対する攻撃
* ARP スプーフィング
  * ARP(Address Resolution Protocol)の偽応答を返すことで、IP アドレスを偽装する手法

**8.2.2: フィッシング**

* フィッシング(Phishing)とは、正規サイトにそっくりな入力画面を用意してメールなどで利用者を誘導し、ID とパスワードや個人情報などを入力させて盗み取る手法のこと

**8.2.3: Web サイトの成りすまし対策**

* Web サイトの成りすましを防ぐには以下が有効
  * ネットワーク的な対策
    * 同一セグメント内に脆弱なサーバーを置かない
    * DNS 運用の強化
  * TLS(Transport Layer Security) の導入
    * TLS は、一般的に通信回線の暗号化機能と理解されているが、もう 1 つの重要な機能として、第三者機関によるドメイン名の正当性の証明がある
  * 確認しやすいドメイン名の採用

#### 8.3: 盗聴・改竄対策

**8.3.1: 盗聴・改竄の経路**

* Web サイトのアクセスに対する盗聴・改竄の主な経路として以下がある
  * 無線 LAN の盗聴・改竄
  * ミラーポートの悪用
  * プロキシサーバーの悪用
  * 偽の DHCP サーバー
  * ARP スプーフィングと DNS キャッシュポイズニング

**8.3.2: 中間者攻撃**

* 前項で説明した盗聴・改竄経路の中には、盗聴用の機器により通信を中継させるタイプのものがある
* この中継型の盗聴の場合には、通信路が暗号化されていても盗聴・改竄が可能。この手法を中間者攻撃と呼ぶ

**8.3.3: 対策**

* 通信の盗聴・改竄を防ぐには、前述のように、正規の証明書を導入して TLS を運用することに尽きる
* TLS 利用時の注意点
  * 入力画面から HTTPS にする
  * クッキーのセキュア属性に注意
  * 画像や CSS、JavaScript なども HTTPS で指定する
  * frame、iframe を使わない
  * ブラウザのデフォルト設定でエラー表示されないようにする
  * アドレスバーを隠さない
  * ステータスバーを隠さない
  * コンテキストメニュー(右クリックメニュー)を無効化しない

#### 8.4: マルウェア対策

* この節では Web サイトのマルウェア(ウイルスなどの不正プログラム)対策について説明する

**8.4.1: Web サイトのマルウェア対策とは**

* Web サイトのマルウェア対策には以下の 2 つの意味がある
  * Web サーバーがマルウェアに感染しないこと
    * 影響は以下
      * 情報漏洩
      * サイト改竄
      * 不正な機能実行
      * 他サイトへの攻撃(踏み台)
  * Web サイトを通じてマルウェアを公開しないこと
    * 影響は以下
      * Web サイトを閲覧した利用者の PC がマルウェアに感染する

**8.4.2: マルウェアの感染経路**

* 2017 年に報告された感染経路だと、電子メール 89.7%、ネットワーク 9.2%

**8.4.3: Web サーバーのマルウェア対策の概要**

* Web サーバーに対するマルウェア感染対策は、その感染経路から、以下が重要
  * サーバーの脆弱性対処をタイムリーに行う
  * 出所不明なプログラムをサーバーに持ち込まない
  * サーバー上では運営に直接関係のない操作(Web やメールの閲覧など)を無効化しない
  * サーバーに USB メモリなどの外部メディアを装着しない
  * Web サーバーのネットワークを執務スペースの LAN と切り離す
  * サーバーに接続するクライアント PC にウイルス対策ソフトを導入してパターンファイルを最新に保つ
  * Windows Update などによりクライアント PC に最新のセキュリティパッチを導入する

**8.4.4: Web サーバーにマルウェアを持ち込まない対策**

* Web サーバーにマルウェアが持ち込まれる経路には以下がある
  * Web アプリケーションのファイルアップロード機能の悪用
  * Web サイトの脆弱性を悪用したコンテンツ改竄
  * FTP など管理ソフトに対する不正ログイン
  * マルウェアに感染した管理用 PC からの感染
  * 正規コンテンツがマルウェアに感染していた場合
* マルウェア対策の要否を検討する
* ポリシーを定めて、利用者に告知する
* ウイルス対策ソフトによる対処

### 9: 安全な Web アプリケーションのための開発マネジメント

#### 9.1: 開発マネジメントにおけるセキュリティ対策の全体像

* 開発マネジメントは、開発体制と開発プロセスの両面からおさえる必要がある

#### 9.2: 開発体制

* 開発標準の策定
  * 良い開発標準は次の通り
    * 厚すぎないこと(実効性の高い項目に絞る)
    * 参照すべきページがすぐ見つかること
    * 実施すべき内容が明確であること
    * 継続的に改善していること
  * 開発標準に記載すべき重要項目は以下の通り
    * 脆弱性ごとの対処方法
    * 認証、セッション管理、ログ出力などの実装方法
    * 各フェーズでのレビューとテストの方法
    * 出荷(公開)判定基準
* 教育
  * 開発標準を守らせるポイントは以下の通り
    * 開発標準自体の工夫(前述)
    * チーム内の開発標準教育
    * 設計レビュー、コードレビューによる遵守状況チェック
  * 開発標準の教育内容は以下がポイント
    * 事件事例の紹介(対策モチベーション向上のため)
    * 主要な脆弱性の原理と影響
    * 遵守すべき事項
  * また、開発チーム内にセキュリティ担当者を育成することが望ましい。セキュリティ担当者の主な業務は以下
    * 開発標準の作成、メンテナンス
    * 開発標準の教育
    * レビューへの参加
    * セキュリティテスト
    * 脆弱性情報の監視

#### 9.3: 開発プロセス

**9.3.1: 企画段階の留意点**

* 企画段階では、安全なアプリケーション開発に必要な予算を見積もり、確保することが重要

**9.3.2: 発注時の留意点**

* アプリケーションの発注にあたっては、RFP(Request For Proposal: 提案依頼書)を作成して、提案と見積もりを要求する
  * セキュリティ要件も RFP に記述する
  * 以下のように具体的に要求するとよい
    * 対処の必要な脆弱性名を列挙する
    * 検収方法・基準を明示する
    * 追加で必要な対策があれば提案するよう求める
    * セキュリティテスト方法の提案を求め、テスト結果を成果物として要求する
    * 検収後に発見された脆弱性の対応方法と費用負担を明確にする
    * 開発体制についての説明を求める
    * 開発標準とセキュリティテスト報告書のサンプルを要求する

**9.3.3: 要件定義時の留意点**

* 要件定義時においても、セキュリティ機能とセキュリティバグを分けて整理することが重要
* 以下を中心に検討するとよい
  * 認証、アカウント、認可の要件
  * ログ管理の要件
  * その他のセキュリティ機能についての要件
  * 基盤ソフトウェアの選定とパッチ適用の方針決定
  * 開発標準のセキュリティ要求に対するギャップ分析

**9.3.4: 基本設計の進め方**

* 基本設計で実施すべき重要項目は以下
  * セキュリティ機能に対する具体化
  * 方式設計として開発標準の詳細化、テスト方式の決定
  * 画面設計時のセキュリティ機能の確認
    * CSRF 対策の必要な画面の洗い出し
    * HTTPS にするページの洗い出し
    * 認可制御を要するページの洗い出し

**9.3.5: 詳細設計・プログラミング時の留意点**

* 詳細設計以降は、基本設計に従って設計、開発するだけ

**9.3.6: セキュリティテストの重要性と方法**

* 発注者側でも、検収としてセキュリティの検査をすることが求められる
* セキュリティテストの方法には以下がある
  * 専門家に依頼する
  * 専用ツールを用いて診断する
  * 自力で診断する

**9.3.7: 受注者側テスト**

* 開発プロセスにセキュリティテストを組み込むことを強く推奨する

**9.3.8: 発注者側テスト(検収)**

* セキュリティ要件に対する検収の方法としては以下が考えられる
  * 受注者のセキュリティ検査報告書を精査する(書類チェック)
  * 第三者(専門家)に検査を依頼する
  * 自ら検査する

**9.3.9: 運用フェーズ**

* このフェーズでの重要項目は以下の 2 点
  * ログの監視
  * 脆弱性対処
* また年 1-2 回程度の頻度で定期的に Web サイトを脆弱性診断することもよく行われている。Web サイトを定期的に診断する目的は以下の通り
  * 前回の診断以降に追加されたページや機能に対する診断
  * 新しく発見された攻撃手法への対応チェック

**9.3.10: アジャイル型開発型プロセスへの適用**

* アジャイル型プロセスのスピード感を損なわずにセキュリティを高めるには、以下の 2 点が重要
  * イテレーションの外で実施できるポリシー策定や教育はあらかじめ済ませておく
  * テストなど自動化できる箇所を極力自動化する
