====== セキュアなコードの構造 ====== 構造(アーキテクチャー)とは基本設計です。設計のないシステムが問題をかかえるのは当然です。セキュアなコードの構造と論理はシンプルです。 ===== プログラムの基本構造 ===== プログラムの基本構造は全てのソフトウェアに共通です。 * 入力 * 処理 * 出力 この3つに分けることができます。 ===== ソフトウェアのセキュリティ構造 ===== ソフトウェアの基本的なセキュリティ構造はソフトウェア構造に合わせて設計します。セキュアコーディングでは「プログラムが確実に正しく動作することを保証するように設計/実装」します。プログラムが確実に正しく動作するには * 正しい入力(=プログラムが受け入れ可能な入力に限定) * 正しい処理 * 正しい出力(=出力先のプログラム/システムが誤作動しない無害な出力のみ出力) が必要です。 ==== 論理的背景 ==== 「正しい入力」であることを保証することは「正しいプログラムの実行の必須条件」です。例えば、コンピューターが得意な整数演算でさえ「正しい入力」でなければ行なえません。よくある間違いに「プログラムが不正動作しないことを保証するように設計/実装する」があります。この考え方では効率的/体系的に必要なセキュリティレベルを維持できません。 * 「プログラムが不正動作しないことを保証するように設計/実装」= ブラックリスト型の設計 * 「プログラムが確実に正しく動作することを保証するように設計/実装」 = ホワイトリスト型の設計 セキュリティ対策ではホワイトリスト型の設計が基本 ブラックリスト型のセキュリティ対策には、全てのリスクを完璧に把握しなければリスクを管理できない、という致命的な欠点があります。ブラックリスト型の対策はセキュリティ対策では基本的に利用せず、次の説明するホワイトリスト型の対策を採用します。 ホワイトリスト型のセキュリティ対策では、全て検証済みのモノのみを受け入れるためリスク管理が比較的容易、という利点があります。検証ではじかれたモノには「未知のリスク」が含まれている場合がよくあります。ホワイトリスト型の対策/考え方の方が比較にならない程安全であるのあこれが理由です。 ==== ゼロトラスト ==== 想定外のリスクが発生する原因は「誤った信頼」にあります。「誤った信頼のリスク」を最小化するには「何も信頼しないこと」が重要です。信頼性の高いセキュリティ構築には、何も信頼しない、つまり「ゼロトラスト」から構築する必要があります。 何も信頼しない状態から始めるので、まず最初に信頼するモノを作ります。ソフトウェアの場合、自分の書いたコードを信頼できるモノ、にします。それ以外は全て信頼できないモノです。 信頼できないモノの例 * 全ての入力 * 全てのコード(フレームワーク、ライブラリ、OSなど) * 全ての出力 ==== 信頼境界線 ==== 信頼境界線の設計はほぼセキュリティ設計その物です。信頼境界では入力/出力のセキュリティ対策を行います。処理、つまり信頼境界の中でもセキュリティ問題が発生します。しかし、セキュリティ問題の大部分は入力と出力で発生します。このため「境界防御」が最も重要なセキュリティ対策になります。 全ての「境界防御」が重要ですが、最も重要な境界は最も外側に在る境界です。 ==== 信頼境界のコンテクスト ==== 信頼境界線の設定(≒セキュリティ設計)はコンテクスト別に行う必要があります。 * 物理的 * ネットワーク的 * ソフトウェア的 これら3つ組み合わせたコンテクスト * システム があります。この他に * データ を異るコンテクストとして取り扱う必要があります。信頼境界線の解説には「信頼境界を越えるモノは全て信頼できないければならない、これにはデータを含む」とする物があります。信頼できるデータ(受け入れ可能な入力値)は安全なデータ(出力値)であることを意味しません。外部からの入力を受け入れる場合、完全にリスクを廃除できない場合が多くあります。 リスクを完全に廃除できないデータ例: * フリーテキストの入力データ * 添付ファイルなどのデータ これは、信頼境界の問題ではありません。これらの残存リスクの管理がセキュリティ対策の本質です。 ==== ソフトウェアの信頼境界の限界 ==== 信頼境界は自由に引く事が可能です。信頼境界を拡張するためには、拡張対象が「信頼可能であることを保証」すれば良いだけです。しかし、信頼の拡張には限界があります。 ソフトウェアの場合、信頼境界線は同一プロセス/スレッド上のコードを越えることはできません。例えば、インターネットから不特定多数のリクエストを処理するWebシステムの場合、クライアントは信頼できないネットワークで接続された別ハードウェア上の別プロセス/スレッドのコードになります。インターネット上のクライアントはどう頑張っても「信頼可能なモノ」にはできません。 ソフトウェアの信頼境界の限界を越えるには他のコードが動作する物理/ネットワーク環境を含めて信頼可能であることを保証しなければなりません。この場合、完全な信頼性を保証することは不可能です。必ず何らかのリスクを許容することになります。許容したリスクが「許容できないモノでない」ことを注意深く検証することが必要です。 ==== 多層防御 ==== 「境界防御」を行っても全てのリスクを完全かつ完璧に廃除することは、普通は不可能です。このため、複数の境界を作り「多層」で防御します。 ====== ソフトウェア以外のセキュリティ設計 ====== 物理的、ネットワーク的なセキュリティ設計/仕様はソフトウェアにとって非常に重要です。ソフトウェアのみのセキュリティでは、物理的、ネットワーク的な安全性が保証できていない場合に安全性は保証できません。 情報システムの安全性は”全体として保証”しなければなりません。部分的に保証してもあまり意味がありません。物理的、ネットワーク的なセキュリティはソフトウェアのセキュリティと同じです。同じように * ゼロトラスト * ホワイトリスト * 信頼境界線 でセキュリティを管理します。