全コーダー必読。プログラマーだけではなく法を作る人も全員。

突っ込み希望なので、いつもの「惰訳」ではなく「試訳」としました。

Enjoy -- with Care!

Dan the Coder to Err -- and Fix

コードをセキュアにする10の作法 (Top 10 Secure Coding Practices)

  1. 入力を検証せよ(Validate input) - 信頼なきデータソースからの入力は、全て検証するようにしましょう。適切な入力検証は、大部分のソフトウェア脆弱性を取り除きます。外部データは疑って掛かりましょう。これらにはコマンドライン引数、ネットワークインターフェース、環境変数、そしてユーザーの管理下にあるファイルが含まれます[Seacord 05]。
  2. コンパイラーの警告レベルは最高に(Heed compiler warnings) - コンパイラーの警告レベルは最大にして、それでも警告が出ないようにしましょう[C MSC00-A, C++ MSC00-A]。
  3. セキュリティーポリシーを設計に織り込め(Architect and design for security policies) - セキュリティーポリシーを実装し、強要するようなアーキテクチャーをソフトェアデザインに織り込みましょう。例えば、異なる場合には異なる特権レベルが必要とされる場合、システムを二つに分離し、それぞれのシステムにそれぞれの権限を与えるようにしましょう。
  4. シンプルイズベスト(Keep it simple) - システムを可能な限り小さくシンプルに保つようにしましょう[Saltzer 74, Saltzer 75]。複雑なシステムは実装、設定、そして利用においてエラーが混じる可能性を大きくします。そしてシステムが複雑になればなるほど、適切なレベルの品質を保証するのに要する労力も大きくなります。
  5. デフォルトで拒絶(Default deny) - アクセス可否は、設定で拒否ではなく設定で許可としましょう。デフォルトではアクセスは不許可で、何に対してどれだけアクセスを許すかというのを設定していくようにするのです [Saltzer 74, Saltzer 75]。
  6. 最小特権の原則を貫く(Adhere to the principle of least privilege) - 実行においては、それに必要な最小限の特権で行われるようにするべきです。特権レベルを上げる場合も、最小限に留めます。これにより、攻撃者が攻撃できる範囲を最小限に留めることができます [Saltzer 74, Saltzer 75]。
  7. 他のシステムに送るデータは消毒(サニタイズ)しておけ(Sanitize data sent to other systems) - サブシステムに送るデータは、消毒しておきましょう[C STR02-A]。コマンドシェルやリレーショナルデータベースや商用のコンポーネント(COTS)などが相当します。攻撃者は、SQLやコマンドなど、インジェクションを用いてこれらのサブシステムを攻撃することが出来ます。これは入力検証の問題に限りません。なぜならそこで呼び出されるサブシステムが、何のためにそのコンテキストが呼び出されるか理解しているとは限らないからです。コンテキストの解釈は呼び出し側が担っている以上、データを消毒しておく責任も呼び出し側のシステムにあります。
  8. 多重防御を実践せよ(Practice defense in depth) - リスク管理は、多重の防衛戦略の元に行うようにしましょう。別の階層による防御により、セキュリティーの瑕疵がシステム全体の脆弱性に直結することを防ぐことができ、それが実際の攻撃を防ぐことにもなります。例えば、セキュアプログラミングの技法とセキュアな運用の組み合わせは、プログラム中に残った脆弱性が実際の運営で突かれる可能性を低くします [Seacord 05]
  9. 有効な品質保証の手法を用いよ(Use effective quality assurance techniques) - よく出来た品質保証の手法は、脆弱性の発見と排除に役立ちます。侵入テスト(Penetration testing)、 fuzz testing(無意味なデータをあえて流すテスト)、そしてソースコード監査(source code audits)は、この品質保証の手段として組み入れるべきでしょう。外部によるレビューも、独自の視点をもたらしてくれます。例えば、誤った前提条件を発見し修正してくれます [Seacord 05]。
  10. セキュアコーディングの標準を採用せよ(Adopt a secure coding standard) - 使用している言語およびプラットフォームにおけるセキュアコーディングの標準に則って開発するようにしましょう。

ボーナス作法

  1. セキュリティに関する要件を定義しておけ(Define security requirements) - 開発サイクルのなるべく早い時期に、セキュリティに関する要件を定義しておき文章として残すようにしましょう。次の段階へ進むにはその要件を満たすことを検証するようにしましょう。要件が定義されていなければ、作られたシステムを評価することもままなりません。
  2. 脅威をモデル化しておけ(Model threats) - どのソフトウェアがどんな脅威にさらされるのかをあらかじめ想定しモデル化しておきましょう。何が守るべき資産で、どのアプリケーションがそれにアクセスし、それぞれどのような脅威があるのかを場合分けしておくのです。そしてリスクに応じてそれらを分類し、脅威に対抗する手段と戦略をデザイン、コード、そしてテストケースに反映させるのです。 [Swiderski 04]。

ボーナス写真

ウェブで以下の写真を見つけました。この写真に関する権利を誰がお持ちなのかを今も探しています。ご存じの方はご連絡下さい。

circumvent rather than defeat

私がこの写真が好きなのは、システムを破る最も簡単な方法が、突破ではなく回避であることを如実に示しているからです。セキュアでないコーディング作法によるソフトウェアの脆弱性もこの例外ではありません。

参考文献

  • [Saltzer 74] Saltzer, J. H. "Protection and the Control of Information Sharing in Multics." Communications of the ACM 17, 7 (July 1974): 388-402.
  • [Saltzer 75] Saltzer, J. H. & Schroeder, M. D. "The Protection of Information in Computer Systems." Proceedings of the IEEE 63, 9 (September 1975), 1278-1308.
  • [Seacord 05] Seacord, R. Secure Coding in C and C++. Upper Saddle River, NJ: Addison-Wesley, 2006 (ISBN 0321335724 ).
  • [Swiderski 04] Swiderski, F. & Snyder, W. Threat Modeling. Redmond, WA: Microsoft Press, 2004.