運用保証(2部構成の1)
ソフトウェア工学を土木工学と不利に比較することは、一種の決まり文句になっています。 よく投げかけられる挑発は、次のようなものです。
正しい橋、つまり私たちが渡るときに足元で崩れ落ちない橋を確実に建設できるのに、なぜ正しいデスクトップアプリケーション、つまりクラッシュせず、セキュリティホールも含まないアプリケーションを確実に書けないのでしょうか?
その含意は、土木技術者は厳格な基準を継続的に満たしている一方で、ソフトウェア技術者は同じ熟練度に到達できていない、というものです。 この論法は表面的には説得力があるように見えます。 私たちは皆、バグのあるソフトウェアを使ったことがありますが、橋が崩落するのを実際に見たことがある人はほとんどいません1。
心配はいりません。私たちソフトウェア側の人間も、まだ面目を保てます。 この議論には少なくとも2つの欠陥があります。
-
悪意のある行為者を無視しています。 ソフトウェアは容赦ない攻撃にさらされており、その攻撃者は熟練した敵対者である可能性があります。デバイスの脱獄を試みるパワーユーザーであれ、マルウェアキャンペーンを収益化しようとするサイバー犯罪者であれ同じです。これらの敵対者に耐えることは、ネットワーク接続されたあらゆるシステムにとって基本的な設計要件です。一方で橋は、設計上、解体作業員や放火犯に耐性を持つ必要はありません。
-
誤った同等性に依存しています。 静的解析における「状態爆発」への言及を思い出してください。ソフトウェアには固有の組合せ的複雑性があります。さらに、ソフトウェアライブラリやフレームワークは、建設資材や建築技術よりもはるかに速いペースで変化します。橋には年単位で測られる期間にわたる保守が必要ですが、ソフトウェアシステムは2週間のスプリントで新機能を追加できます。この動的な複雑性は、セキュリティと信頼性のリスクをいっそう高めるだけです。
ここまで、この章ではソフトウェア保証を非常に頑丈な橋を建設することのように扱ってきました。 メモリ安全性と一般的な正しさについて論じた以外には、現実世界で悪意のある行為者と戦うために実際に何が必要なのか(上記の1つ目の欠陥に相当)には触れていません。 また、セキュリティが静止した標的であることも暗黙のうちに仮定してきました(上記の2つ目の欠陥に相当)。
より大きな視点
静的解析と動的テストは、純粋に予防的な手段です。 実際には、ほとんどのソフトウェアには、継続的な現場でのセキュリティサポートが必要です。 Rustの厳格なコンパイラを満足させること、手動レビューを受けること、網羅的な動的テストスイートに合格すること――これらはすべて、高保証製品を出荷するための前提条件にすぎません。
本番環境で稼働し始めたら、それらの製品はライフサイクル全体にわたってサポートされる必要があります。 運用保証が主題になります。 私たちは、絶えず変化する環境の中で悪意のある行為者に対応できなければなりません。
OPSECについて話しているのですか?
**運用セキュリティ(OPSEC)**は、もともとベトナム戦争時代の軍事用語でした2。 現代のIT用語では、機密情報が敵対者に漏れることを防ぐ手段を広く指します。 例としてパスワード管理を考えてみましょう。
同じ覚えやすいパスワードを複数のサイトで再利用しますか?
それは悪いOPSECです。本来は分離されているシステムに有効な認証情報を漏らしていることになります。
いずれか1つのサイトがパスワード保存のベストプラクティス(ソルト付きハッシュ3など)を使用しておらず侵害された場合、攻撃者はあなたのパスワードを再利用して、あなたの複数のアカウントを乗っ取る可能性があります(メールアドレス/ユーザー名を再利用していると仮定)。
各Webサイトで、一意で長く、ランダムに生成されたパスワードを使用しますか?
それは良いOPSECです。認証情報を漏らしていません。
単一サイトの侵害は、他のアカウントのセキュリティには影響しません。
運用保証はより広い概念であり、機密データの機密性を超えた目標を持ちます。 OPSECは運用保証のサブセットと考えることができます。 前の例に戻りましょう。
ランダムで一意なパスワードを使用することに加えて、常に多要素認証(MFA)を有効にし、ログをレビューしますか?
それは良い運用保証です。認証を強化し、定期的に過去の監査を実施し、機密性を保護しています。
過去のデータに、奇妙な地理的位置のIPからのログイン試行が現れていることに気づいた場合、それは侵害の試みを示している可能性があります。
運用保証の分解
運用上の施策は、「構造化ロギング」4から「リモートアテステーション」5まで幅広く及びます。 ツールや技術の広がり全体を捉えるのは難しいため、ここでは3つの大きなカテゴリに分け、網羅的ではない例を示します。
システムライフサイクル
製品やサービスを最新の状態に保つためのプロセスとツールです。 比較的新しい「DevSecOps」6という包括的概念に含まれます。 例は次のとおりです。
- 継続的インテグレーション/継続的デプロイメント(CI/CD)におけるセキュリティスキャン
- 暗号化され、認証された無線経由のファームウェアアップデート
- バージョン管理され、フォールトトレラントな分散インフラストラクチャ(例:コンテナ化されたマイクロサービス)
- 資産インベントリ
ホストベースのサポート
個々のマシンを保護するための技術です。企業の従業員が使用するクライアントであれ、顧客向けサービスを実行するサーバーであれ対象になります。 例は次のとおりです。
- サンドボックス化
- 強化されたメモリアロケータ
- エンドポイント検知・対応(EDR)ツール
- アプリケーション固有のベストプラクティス設定
ネットワークベースのサポート
企業ネットワークをリモート攻撃から保護し、足掛かりの獲得に成功した攻撃者の移動を制限するための技術です。 例は次のとおりです。
- セキュアなAPIゲートウェイ
- Webアプリケーションファイアウォール(WAF)
- セキュリティ情報イベント管理(SIEM)システム
- 仮想プライベートネットワーク(VPN)インフラストラクチャとゼロトラストアーキテクチャ
運用保証は私たちのライブラリとどのように関係するのでしょうか?
この本の中心的な焦点は、堅牢なデータ構造ライブラリを書くことです。 初期の章で非常に広い範囲を扱うため、見失いやすい点です! 私たちの旅の終盤では、運用保証におけるシステムライフサイクルの構成要素について実践的な経験を積みます。
私たちのライブラリを他のプログラミング言語、すなわち C と Python から利用可能にするバインディングを開発することで、高速で安全な Rust コンポーネントを既存のコードベースに統合するプロセスをシミュレートします。
おそらく、パフォーマンス上の理由から Rust で新機能を書く機会があるかもしれません。 あるいは、セキュリティ上重要でありながらメモリ安全ではないコンポーネントを、Rust の同等物で段階的に置き換えられるかもしれません。 いずれにせよ、Rust コードへのバインディングにより、チームは大規模システムを時間をかけて「堅牢化」(セキュリティ態勢を改善)できます。
要点
この本は「プロダクトセキュリティ」の観点に偏っています。 このセクションの目的は、より大きな全体像、すなわち「エンタープライズセキュリティ」の観点を少し体験してもらうことです。 ソフトウェアセキュリティに関する私たちの議論は、このより広い文脈なしには完全なものにはなりません。
次のセクションでは、システムライフサイクルカテゴリの一側面である、ネイティブクライアント向けのアプリケーションデプロイオプションを紹介します。
私たちは rcli プログラムを独立して動作するようにし、どのエンドユーザーに対しても確実に実行されるようにします。
-
余談ですが、この本の著者のひとりは、崩落の 24 時間足らず前に、実際にピッツバーグの橋を歩いて渡っていました。国として比較的裕福であるにもかかわらず、老朽化し、十分に保守されていないインフラは、米国における深刻な問題です。 ↩
-
Operations security。Wikipedia(2022 年閲覧)。 ↩
-
Password Storage Cheat Sheet。OWASP Foundation(2022 年閲覧)。 ↩
-
エラー(何らかの「悪い」条件に達したシステムイベント)を構造化形式でログに記録すると、本番環境で発生した問題の診断に役立ちます。あるいは、セキュリティインシデントにより効果的に対応できます。 ↩
-
アテステーションとは、特定のマシンが、攻撃者によって挿入または改変されたソフトウェアではなく、事前承認済みの特定のソフトウェア一式を実行していることを証明するためのプロセスです。このトピックに関心がある場合は、「Trusted Platform Module」(TPM)が何を行い、Windows 11 でどのように使われているかを調べてみるとよいでしょう。 ↩
-
What is DevSecOps?。Redhat(2018 年)。 ↩