Project ICKX Webアプリケーション開発・運用ガイドライン 参考版

# 概要

この文書はProject ICKXにおけるWebアプリケーションの開発・運用におけるガイドライン(以降、本ガイドラインという)の議論用参考版です。

## 注意事項

元が**弊サークル内向けの制限無し版**のため、**最初から全てを網羅・把握することは困難**な内容となっています。

ご自身の環境において「**今出来ていない**」「**良く判らない**」項目があった場合でも、ご自身の環境において「これら全てを実施しなければならない」という**話ではありません**のでご留意ください。

仮にご自身の環境に取り込む場合は**段階を分けて**、**出来る所からやり**、**特に意識しなくても出来るようになったら次の段階を実施する**ことがコツとなります。

## 本ガイドラインの趣旨

本ガイドラインはWebアプリケーションの開発・運用に対する従来の理解に対して、弊サークルの解釈を加えることにより、議論の活発化を図ることを趣旨としています。

現時点においてセキュリティが「重視する・しないなど、プロダクトの価値の外に置かれている」「プログラマ個人の技能に立脚するもの」などの言説が多くみられます。<br>
それらに対しての我々が持つ異なる価値観からの提案を考えたことが本ガイドラインを公開するに至った当初の経緯となります。

[本ガイドラインが要求すること](#本ガイドラインが要求すること)でも触れているように、**セキュリティはプロダクトの価値と不可分**です。<br>
「重視する・しない」ではなく、**セキュリティが成された上で初めてプロダクトが成り立つ**ものとなります。

また、**個人の技能・判断で行った蓄積**では継続的にセキュリティを確保することはできません。

よくある例としては「ここはデータベースから取得した値しか出力されないからescapeは要らない」などです。<br>
技能が足りていない場合は**データベースに保存された値が汚染されている**ケースの見落としが発生、攻撃が成立するなどし、また、判断については**逐次「ここはOK、ここはNG」といった判断**が必要となるため、判断の誤りや見落としがあった場合に攻撃が成立するなどします。

この例においてはガイドラインとして**一律にコンテキストにそったescapeを行うこと**を定め、実施していれば攻撃を防げました。

"**くさりの丈夫さは一番弱い輪で決まる**"とも言う通り、ムラのある対応はムリを生み、防護がムダになります。

そのため、セキュリティを確保するためには**規約を定め、それが実施されている事を検証し続ける**ことが要求されます。<br>
また、**規約を適宜改定**することで個人の技能に寄らない、ムラの無い防護を継続的に提供することが出来ます。

これが実現できれば、システム全体で一律の防護を展開することが可能となります。

その前提において、本ガイドラインをご一読頂ければと思います。

なお、本来はトップレベルのガイドラインはフレームワークとして具体を持たず指針のみとし、具体的な内容は参照として疎結合にするべきなのですが、本ガイドラインにおいては見通しを優先し、具体を直接記載しています。

## 本ガイドラインが要求すること

本ガイドラインは次の情報セキュリティにおける七つの性質を確保することを要求します。

- 機密性：許可された対象に対してのみ情報が公開され、使用可能であり、許可されていない対象に対しては情報が非公開、使用不可である状態を確保すること。
- 完全性：情報が正確であり、改ざん・破壊・消去などされていない、完全な状態であることを確保すること。
- 可用性：許可された対象が要求した時点で中断することなく情報にアクセス・使用ができる状態を確保すること。
- 真正性：情報がその通りのものであることの確実性を確保すること。
- 責任追跡性：情報に対する操作が操作者自身及び操作の一意な追跡性を確保すること。
- 否認防止：操作や事象に対して、否認が出来ない証明を確保すること。
- 信頼性：意図した動作、意図した結果を得られる状態を確保すること。

# 開発における要求

本ガイドラインは次の原則の実施を要求します。

- リスクアセスメントの実施
- 信頼性設計の適用
- エラープルーフ化の実施
- 明示的な許可が無い物はすべて拒否・禁止
- コンテクストに立脚した信頼境界線の定義と境界線入出力の定義
- 認証・認可に対するレベルの定義と実施

## リスクアセスメントの実施

本ガイドラインはリスクアセスメントの実施を要求します。

本ガイドラインで言うリスクとは、人やシステム、ビジネスに対して悪影響を与える可能性の積です。
そのため、予測・想定されるリスクの可能性・頻度・規模を割り出す必要があります。

次のプロセスを経ることで、リスク対応が可能な状態を確保します。

- リスク特定：リスクの発見、認識、記録
- リスク分析：特定したリスクの特質の解明、リスクレベルの決定
- リスク評価：分析したリスクがリスク基準に対して受け入れ可能かどうかを決定

リスク評価後は「発生源自体の除去」「発生頻度の漸減」「発生後の結果の変更」「状態を保有し続ける」などのリスク軽減・回避施策をとり、より安全な状態を実現します。

## 信頼性設計の適用

本ガイドラインは次の手法を考慮し、信頼性のある設計を要求します。

- フェイルセーフ
  - 故障時は安全な側へ移行するようにする<br>
    例）攻撃と見なせるリクエスト場合、例外として処理を終了する<br>リリース直後のみあり得るユーザエラーとの識別が困難な場合は異常検出用ログに記載の上、以降の処理で最終判断させる
  
- フォールトトレラント
  - 構成要素中それぞれでエラーが発生しても、システム全体としては機能し続けるようにする<br>
  例）トランザクションを達成するために不要な要素（広告など）でエラーが発生しても、トランザクションを完了できるようにする
  
- フールプルーフ
  - 誤った操作を行っても致命的な結果が起こらないようにする
  
- フェイルソフト
  - 動作しない機能が発生した場合に機能を切り離し、被害を最小化かつ機能が縮退した状態でもサービス提供を続行できるようにする

- フェイルオーバー
  - システムで異常が発生した場合に冗長待機系に切り替え、サービス提供を続行できるようにする<br>
  例）APIが停止した場合にセカンダリに接続しに行くようにする

- アクティブセーフティ（予防安全）
  - エラーを未然に防げるようにする<br>
    例）かもしれない実装、値に対する警告、変数型の定義、値オブジェクト・エンティティの活用

- パッシブセーフティ（受動安全）
  - エラーが発生した場合にシステムの健全性、トランザクションの進行などへの影響を最小限にする

- 損傷許容度設定
  - 「どの程度の内容までならば、対応する、しない」の判断をできるようにする<br>
    頻度、深刻度で構成された四象限マトリックスが必要となる<br>
    例）過去5年に一回（低頻度）かつ悪影響のある発火はない（低深刻度）のため今回のリリースには含めない

## エラープルーフ化の実施

本ガイドラインはヒューマンエラーの発生防止と、それでも発生した場合の影響波及を防止するために、あらかじめしくみや手順を設計に織り込むことを要求します。

- 発生防止
  - 排除：エラーの原因を事前に取り除くこと<br>
  例）エラーの原因あるいは可能性のある業務そのものを不要にする

  - 代替化：人の作業を機器やシステムなどに代替させること<br>
  例）ログ集計やBI向けデータ取得

  - 容易化：作業をしやすくこと<br>
  例）ルールに準じた色の使用により高速に判断させたり、shellの使用ではなくWebツールを使用する

- 波及防止
  - 異常検出：エラーを可能な限り速やかに検出し、迅速な対応につなげること<br>
  迅速な対応につなげるために「狼少年」にならないようにすること<br>
  エラーは「出ているか」「出ていないか」で判断できるようにすること<br>
  パフォーマンスなど累積し、兆候を見つけて初めて異常を検出できる対象があることに注意すること<br>
  兆候から検出する場合は閾値を設け「出ているか」「出ていないか」の判断ができるようにすること<br>

  - 影響緩和：エラーが発生しても、その影響を可能な限り小さく、他に波及しないようにすること<br>
  迅速に非常態勢に移行することで他部署への影響を最小化するなど

## 明示的な許可が無い入出力はすべて拒否・禁止

本ガイドラインは明示的な許可が無い入出力はすべて拒否・禁止することを要求します。

## コンテクストに立脚した信頼境界線の定義と境界線入出力の定義

本ガイドラインはコンテクストに立脚した信頼境界線の定義と境界線入出力の定義及びその検証を要求します。<br>
原則として入力、出力が信頼境界線となります。

## 認証・認可に対するレベルの定義と実施

本ガイドラインは認証（Authentication）、認可（Authorization）を分離しそれぞれに対するレベルを定義し、運用することを要求します。

単一のエンティティに対して、同時に複数の認可が与えられる場合も考慮した設計が推奨されます。

# 規約

本ガイドラインは次の規約の遵守を要求します。

- 入力値検証
- データの正規化
- 出力
- 認証・認可
- SESSION・COOKIE管理
- TLSの利用
- 監視

## 入力値検証

本ガイドラインはシステム外部からの入力値は全て検証（Validation）を行い、検証失敗の場合は検証エラーレベルに応じた応答をすることを要求します。

フロントエンドインターフェースでの入力内容確認はUX向上のための施策でしかなく、それを検証としてはなりません。<br>
そのため、検証は必ずバックエンドで行うことを要求します。

また、システム内部でも信頼性境界を超える入力の場合、検証（Validation）が必要となる場合があります。

### 入力値検証細則

- 規定値を出力し、受け取る項目の場合、規定値に存在する値かどうかで検証することを要求します。
- 項目そのものが送られてきていない場合、攻撃を受けているとみなします。
- 入力値のエンコーディングが適切か検証することを要求します。
- データベースを利用する場合はプリペアドステートメントを利用することを要求します。
  - 実装に依存しますが、ユーザランド実装によるプリペアドステートメントの使用は推奨されません。
  - LIKEの構築など、不可避な場合を除き生クエリを使用してはなりません。
  - カラムの自由指定を行いたい場合は、入力値をそのまま使うのではなく、カラムリストに該当のカラムがある事を検証し、存在した場合はカラムリスト側の文字列をクエリに使用することを要求します。

### 検証エラーレベル

検証エラーレベルは次の4レベルの使用が推奨されます。

- ユーザエラー<br>ユーザ入力時にルールにマッチしなかった場合のエラー<br>前提として次の画面に遷移させるためにエラーを修正して貰う必要があるため「**次の画面へ進むにはどうしたらよいか**」をエラーメッセージとして提示することを要求します。
- ロギングユーザエラー<br>ユーザエラーとしての動作に加え、ログの保存を要求します。
- ロギングパススルー<br>ユーザエラーとしての検証は行うが、ユーザエラーの表示はせず、ログの保存を要求します。
- 例外<br>来るべき値が来ていないなど、**仕様に則っていない**または**攻撃と見なせる**リクエストに対するエラー<br>何が原因でそれが起きたのかを知る必要があるため、「**何を与えられた結果どうなった**」をエラーメッセージとして提示することを要求します。

## データの正規化

本ガイドラインはシステム外部からの入力値は検証した値を元に適切なキャストを行い、以降の処理に用いることを要求します。

## 出力

本ガイドラインは規格に則ったフォーマッターを用いた出力を行うことを要求します。

### 出力細則

- 出力する箇所においてコンテキストに応じたエンクロージング及びエスケープを行うことを要求します。
- CSRFが成立しない実装にする事を要求します。
- iframeやクリックジャッキングが成立しないhttp response header出力を行うことを要求します。
- エスケープにおいて、コンテキスト境界をまたぐ内容の出力は行ってはなりません。
　例）HTMLタグそのものの出力<br>`name="value"`などHTML属性名と属性値がセットとなった出力
- URLに付与するパラメータは`http_build_query`など、システム標準かつ安全が確認されている処理で作成、付与することを要求します。
- 連続する画面間のデータの受け渡しにhiddenフィールドを使用してはなりません。

## 認証・認可

### 認証（Authentication）

認証にはTLSが利用可能な前提において、次の認証方式を利用できます。

- BASIC認証
- Bearer認証
- HTMLフォーム認証
- クライアント認証

実現が不可能な場合を除き、タイムアウトとログアウトを実装する事を要求します。

#### パスワード

認証に用いるパスワードは次の項目を満たす必要があります。

- パスワードの文字種は半角英数字記号スペースを利用できる事を要求します
- パスワードは最低長は8文字以上であることを要求します
  - パスワードは最低長は8文字よりも長い事が推奨されます
- パスワードの最大長はストレージ側が持つ最大長未満に制約してはなりません
- パスワードはSHA256以上の強度を持つアルゴリズムでハッシュ化し保存する事を要求します
- ハッシュを作成する場合はソルトの設定とストレッチングを行うことを要求します
- パスワードは変更可能である事を要求します
  - パスワード変更時には既存のパスワードの確認を要求します
  - パスワードの変更があった旨を被認証者に通知する事を要求します
- 定期的なパスワード更新の強制は行ってはなりません
- 特定の文字種の使用の強制は行ってはなりません
- 「任意の語を複数種類混在させて利用する」事を推奨します

### 認可（Authorization）

本ガイドラインは認可（Authorization）は認証が成功したのちに設定する事を要求します。

## SESSION・COOKIE管理

本ガイドラインは全てのクッキーにおいて次の設定を要求します。

- session_nameは標準から変更することを要求します
- session_idは標準から変更することを要求します
- session_idなどの文字列を除き、クッキーに記載するデータはAES256以上の強度をもつアルゴリズムで暗号化することを要求します
- 無期限クッキーを発行してはなりません

## TLSの利用

本ガイドラインは信頼性境界を超える全ての通信をTLSで保護することを要求します。

## 監視

本ガイドラインは操作に対するログの保持を要求します。<br>
また、標準から離れた操作が行われた場合の警報発報を要求します。