ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
環境制約でMacアプリケーションを保護
環境制約を採用してMacアプリケーションのセキュリティを向上させる方法を紹介します。プロセスの起動方法を制限したり、Launch AgentやLaunch Daemonが改ざんされないようにしたり、不要なコードがアドレス空間で実行されないようにしたりする方法を紹介します。
関連する章
- 0:00 - Introduction
- 2:47 - Environment constraints
- 7:48 - Defining constraints
- 10:16 - Adopting constraints
- 16:22 - Wrap-up
リソース
関連ビデオ
WWDC22
WWDC20
-
ダウンロード
♪ ♪
こんにちはロバートです 今日は「環境制約」という macOSの新しい機能について お話します 機能が豊富なMacのアプリは プロセスやファイルだけで語りつくせません フレームワークとライブラリを使用すると アプリ全体または他のデベロッパの コードを再利用できます ヘルパーツールにヘルパーアプリや XPCサービスを利用すると 作業を分割して攻撃対象領域を 減らすことが可能です エージェントの起動やデーモンの起動に ログイン項目の使用で バックグラウンドまたは ユーザーのログイン時に作業できます またアプリ拡張機能を使用すると 他のアプリに便利な機能を提供できます しかしアプリは潜在的に敵対的な環境で 実行されることも多いです アプリのアーキテクトはソフトウェアと 一緒に実行されることもあるので フレームワークを使用する未知の ソフトウェアの潜在的な影響を考慮します ヘルパーツールまたはXPCサービス実行時に 攻撃者がキーチェーンデータに アクセスできる可能性はあるかどうか iCloudデータやその他の権限は どうでしょうか 予期しないコードがプロセスに挿入 された場合 何が起こるでしょう 本当の親子関係と同じように 親プロセスは子の動作に 多大な影響を与えます macOSでは別のプロセスを posix_spawn処理する機能により 親は子へのほぼすべての入力を 制御できるようになります 親プロセスはシステムリソースへの 子のアクセスを制限することもできます このレベルの制御のおかげで 子が予期しないコードを読み込んだり 予期しない機能を実行したりなど 何らかの動作により プロセスが攻撃に対して 脆弱になることもあり得ます しかし親子関係を超えて プロセスは それが生成されるディスク レイアウトを信頼します ディスク上のファイルを変更できる 悪意のあるプロセスは 被害者のプロセスに予期しないデータを フィードする可能性があり 被害プロセスから ランタイム保護を削除したり システム上で永続的な実行を取得したり プロセスの特権を盗んだりします このような脅威に直面して macOSはアプリを保護するツールを 提供しています 特にApp Sandboxを採用して アプリが侵害された場合の 影響を制限できます また強化されたランタイムと ライブラリの検証を採用して 実行時のプロセスの整合性を 保護できます GatekeeperとNotarizationは 顧客システムに既知の悪意あるコードが 存在しないようにするのにも 役立ちます 前に述べた脅威について考えると 既存の保護は実行環境ではなく 実行中のプロセスに 重点を置いていることがわかりました そのため環境制約を導入したのです 環境制約により プロセスが実行できる環境を 新たなレベルで制御できるように なったことを受けて プロセス内でコードを混在させる 方法についても説明します この講演の残りの部分では 環境制約がmacOSの セキュリティアーキテクチャに どう適合するかについて説明し 環境制約がどのように 構造化されているか また アプリに環境制約を どう採用できるかにも触れます その前にmacOSのセキュリティ スタックについてお話します デフォルトではmacOSはこれら すべてのテクノロジーを活用して ブートチェーンを保護し OSの整合性を確保するので 権限分離の強制や悪意のある ソフトウェアからユーザーを保護します macOS Venturaでは オペレーティングシステムの プロセス間の関係をより保護するため 環境制約を導入し始めました これらの機能はOSに新次元の セキュリティを提供します macOS Sonomaでは 環境制約の使用を拡張し アプリでも使用できるようにしました さて環境制約とは何でしょうか 基本的にコードは それが何であるかだけでなく コードがどのように実行されるか 予想を記述しておくことでも あります macOSではさまざまな目的で 環境制約を使用します たとえばプロセスが信頼できるバンドル リソースを使用していることを確認するには OSプロセスが署名済みシステム ボリュームから実行されるようにします 特権デーモンが予期しない引数 または Machポートで実行 されないようにするには システムデーモンは保護されたlaunchd.plistに 基づいてのみ実行する必要があります システムアプリへの攻撃対象領域を 減らすには システムアプリをLaunch Servicesから アプリとして実行する必要があり Background Itemに対する ユーザーの承認を確実に行うために 環境制約を使用した 変更の検出も必要です 「自分のアプリは環境制約を採用する必要が あるだろうか」という疑問があるかと思います 環境制約は完全にオプションですが アプリへの攻撃対象領域が 環境制約によって減少する可能性が あることを強調したいと思います この講演の後半ではより具体的な 使用例について説明します その他にもアプリに複数のプロセスが 存在する場合や さまざまなデベロッパチームによって 署名されたコードをロードする場合も 環境制約が特に役立つ 可能性があります 環境制約にはいくつかの 異なるタイプがあるため 最初に起動制約について説明します 起動制約は特定のバイナリに 埋め込まれ そのプロセスのプロパティを 定義しますが それは親になることができる プロセスのプロパティや またはその親となることができる プロセスのプロパティです こうしたプロパティを 「自己制約」「親プロセスの制約」 「責任プロセスの制約」と 呼びます 3つすべてをバイナリに適用することも 重要なもののみを選択することもできます 必要なプロパティのいずれかが 満たされていない場合 起動制約は埋め込まれた プロセスを実行できません 次にいくつかのプロセスの 関係を説明し 起動制約を使用して それらを 保護する方法について説明します まずMyDemo.appがあなたの アプリであると仮定します MyDemo.appに自己制約を 設定してLaunch Servicesから アプリケーションとして 起動することを要求します アプリがXPCサービスへの接続を リクエストするとlaunchdは XPCサービスを生成し そのXPCサービスの親になりますが アプリはそのXPCサービスに対して 「責任」を負います MyXPCDemo.xpcに責任 プロセス制約を設定して MyDemo.appのみが責任を 負うように指定できます 後でアプリがNSTaskまたはposix_spawnを 使用してヘルパーを起動する場合 そのアプリはそのヘルパーの親であり そのヘルパーに対して責任を負います MyFirstHelperに親プロセス 制約を設定して MyDemo.appのみが その親になることを要求できます 最初のヘルパーが2番目のヘルパーを posix_spawnする場合 最初のヘルパーは2番目の ヘルパーの親になりますが アプリは2番目のヘルパーを 担当します MySecondHelperの場合 MyFirstHelperによってのみ 起動されるように親プロセス制約を 設定したり 責任のあるプロセスの制約を 設定してMyDemo.appのみが その責任を負うことを要求する こともできます 起動エージェントと起動デーモンの launchd plistで 環境制約を指定することもできます SMAppService APIを使用して plistを登録すると OSは制約を満たすプロセスのみを 強制的に登録し plistに代わって起動されます この機能は悪意のあるコードが ユーザーの承認に基づいて 永続的に実行されないようにすることで アプリのバックグラウンド アクティビティの記録を可能にします 最後にライブラリのロード制約を 使用して アドレス空間にロードできるコードを 具体的に制御します ライブラリのロード制約の前に ライブラリの検証を採用するか どうかを選択できます ライブラリの検証により プロセスは署名したコードまたは Appleによって署名されたコードを 読み込めます ライブラリの読み込み制約を 使用すると ライブラリの検証で許可されるよりも 制限の少ないコードセットを記述でき 同時に任意のコードがプロセスに 読み込まれるのを防ぎます ただしApple署名付きコードを 除外することはできないので プロセスに読み込まれないよう 独自のコードを許可するには プロパティをそのように指定する 必要があります 環境制約とは何かと それをどう使用するかに即して それらがどのように定義されるかについて 説明します 環境制約はコードが満たさなければ ならない一連の条件を記述します これらは辞書としてエンコードされ キーはコードに関して真であるか 次のことを示す演算子の いずれかを表します 事実または述語間に 必要な関係です トップレベルでは暗黙的に 各キーと値のペアの結果制約が 満たされるかどうかを決定するために ANDが処理されます これらは辞書であるため 各キーは辞書レベルごとに 1回しか出現できないことに 注意してください 活用したいいくつかの事実を 見てみましょう 左側は関連する環境制約キー 右側はcodedesignコマンド からの出力です signing-identifierキーを 使用すると文字列を指定して これは特定のコード部分に固有である 必要がありますが そのコードのバージョン間で 同じままのものです signing-identifierキーは コードデザイン出力のdentifierフィールドを参照します cdhashキーを使用すると 許可するコードの 一意のハッシュを指定可能で チームidentifierキーを使用して 特定の開発チームによって 署名されたコードを指定できます コードの特定のプロパティを 示しますが 演算子を使用して事実のセットを 論理的に組み合わせるか 事実に対して許容可能な値の セットを定義します ご想像のとおり$and演算子と $or演算子を 使用することで predicateの辞書を指定して 決定後に論理的に結合が 可能になります $and-array演算子と$or-array 演算子は複数の$or述語のANDまたは 複数の$and述語のORが必要な場合 辞書の入れ子を制限します 最後に$in演算子を使用すると 事実を満たす 値の配列を指定できます この制約の例を見てみましょう 左側にあるのは制約のplist表現です 右側はXMLの意味を示す 疑似コード plistの最上位には$or-array というキーがあります 値は3つのタプルの配列です 各タプルには演算子と その演算子が適用される 辞書が含まれているため この制約によりチームidentifierによって 署名されたすべてのコードもしくは 2番目のチームidentifierによって 署名されたライブラリBを許可 または3番目のチームIDによって 署名されたライブラリCが許可されます 最初のタプルについては 単一の要素であるため $or演算子を使用することもできます 制約を定義できるようになったので プロジェクトへの制約導入例を 見てみましょう この説明ではメインアプリを例にとりますが 起動エージェントやヘルパーツールに XPC サービスを含むフレームワーク それと別の開発チームによって 署名されたライブラリです 次に環境の制約によって軽減できる 潜在的な問題を考えてみます キーチェーン データへのアクセスや iCloudコンテナへのアクセスなど ヘルパーツールに何らかの権限を 割り当てている可能性があります ヘルパーツールはアプリによってのみ 起動が可能で他のものでは 起動できないようにしたい場合があります ヘルパーツールに親プロセス制約を 設定することで アプリだけがヘルパーツールを起動 できるようにすることが可能です これを行うにはチームidentifierと メインアプリのsigning identifierを 必要とするコード要件 plistファイルを作成します 次に「Launch Constraint Parent Process Plist」設定で ヘルパーツールの署名構成に 制約を追加します 詳しく見てみましょう 前述のプロパティを備えた Xcodeのデモプロジェクトです MyDemo.appはメインアプリターゲットで demohelperはヘルパーツールです アプリを起動しましょう このボタンを押すとアプリは ヘルパーツールを起動し ヘルパーツールが何らかの処理を 実行してアプリに応答を返します Terminalでデモヘルパーの 署名を見てみましょう
起動制約が設定されて いないので demohelperを実行できます でもここを見てください --cloud引数を指定して demohelperを実行すると demohelperがアプリのiCloud データにアクセスできてしまいます 任意のプロセスがデモヘルパーを 実行してiCloudデータを 変更できるのは望ましくありません Xcodeに戻ってdemohelperに 親制約を設定しましょう
ここではメインのMyDemoを 識別するために 制約plistファイルが設定済みです
署名設定に制約を 追加してみましょう
次にアプリを再構築します
アプリを再起動すると
メインアプリは引き続き ヘルパーを生成できます
ここでTerminalに戻ると
demohelperには 起動制約が追加され Terminalからは実行できなく なっていることが確認できます 起動制約違反により起動が ブロックされると 制約違反を示すクラッシュ レポートが生成されます ここで環境の制約によって軽減できる 他の問題について見ていきます XPCサービスを使用して 異なるプロセス間で 権限分離することを お勧めします XPCサービスを構築する場合 サービスをバンドルから抽出し 他のコードから呼び出すことが 可能です XPCサービスに何らかの特権を 割り当てている場合は 次のことを確認する必要があります 予期されたプロセスのみがその権限に アクセスできるようになっているか 自分のコードだけがそのXPCサービスに アクセスできるようにする 1つの方法は責任プロセスの起動制約を 設定することです ここでは各プロセスのsigning identifierの リストでチームによって署名された コードを許可する起動制約plistを 示しますが それはXPCサービスにアクセスできる バンドル内にあります 「Launch Constraint Responsible Process Plist」設定で 署名構成に制約を追加することも できます 考慮すべきもう一つの問題 それはmacOS Ventura以降 アプリに代わってインストールされる バックグラウンドタスクを承認するように 求められることです これはユーザーがアプリのためにのみ作業が 行われるという設定であることを意味します 攻撃者がplistの実行を想定している コード置換ができる場合 アプリに代わって攻撃者は永続的な バックグラウンド実行を 取得する可能性があります 登録したplistが期待するコードの 実行のみ使用できるようにするには SpawnConstraintキーを使用して launchd plist制約を設定します ここではSpawnConstraintキーを含む 完全なlaunchd plistを確認できます この制約によりチームとDemoMenuBar エージェントが識別されます 最後にライブラリの読み込みに ついて説明します 別の開発チームのライブラリを変更せずに リンクする義務がある場合は 強化されたランタイムで アプリの公証を受ける必要があり disable-library-validation 資格を 採用する必要があります このままではあなたのアプリが 信頼できるデベロッパだけでなく 誰でも署名されたコードを読み 込めてしまうことを意味します この問題に対処するために ライブラリのロード制約を採用しましょう ここではチームまたは信頼できる ライブラリサプライヤーによって 署名されたコードをロード できるようにする制約を示します これを特定のライブラリ向けに さらに制限することも 複数のsigning identifierを使用する ライブラリに適用することも可能です 起動制約と同様に Xcode署名設定で「Library Load Constraint Plist」設定を 適用する際ライブラリ読み込み制約も プロセスにサインインされます 環境制約はどこで利用できる のでしょうか? ライブラリの読み込み制約と launchd plist制約は 任意のmacOSバージョンを 対象とするアプリに含められます macOS Sonoma以降では 強制適用されます 起動制約はmacOS 13.3以降を ターゲットとするアプリに追加でき macOS 13.3以降では 強制適用されます 環境制約で使用できるサポート対象 キーと値のセットは macOSのバージョンによって異なる 場合があることにご注意を 完全な可用性情報については ドキュメントを参照してください アプリ内のプロセス関係launchd plistやライブラリを精査して 環境制約によるアプリの安全性強化が 可能かどうかを確認してください ありがとうございます ♪ ♪
-
-
9:35 - Example constraint
// Example constraint <dict> <key>$or-array</key> <array> <array> <string>$and</string> <dict> <key>team-identifier</key> <string>M2657GZ2M9</string> </dict> </array> <array> <string>$and</string> <dict> <key>signing-identifier</key> <string>com.smith.libraryB</string> <key>team-identifier</key> <string>P9Z4AN7VHQ</string> </dict> </array> <array> <string>$and</string> <dict> <key>signing-identifier</key> <string>com.friday.libraryC</string> <key>team-identifier</key> <string>TA1570ZFMZ</string> </dict> </array> </array> </dict>
-
11:02 - Example parent launch constraint
<dict> <key>team-identifier</key> <string>M2657GZ2M9</string> <key>signing-identifier</key> <string>com.demo.MyDemo</string> </dict>
-
14:06 - Example process launch constraint
<dict> <key>team-identifier</key> <string>M2657GZ2M9</string> <key>signing-identifier</key> <dict> <key>$in</key> <array> <string>com.demo.MyDemo</string> <string>com.demo.DemoMenuBar</string> <string>demohelper</string> </array> </dict> </dict>
-
14:52 - Example launchd plist constraint
// Example launchd plist constraint <dict> <key>Label</key> <string>com.demo.DemoMenuBar.agent</string> <key>BundleProgram</key> <string>Contents/Library/LaunchAgents/DemoMenuBar.app/Contents/MacOS/DemoMenuBar</string> <key>KeepAlive</key> <dict> <key>SuccessfulExit</key> <true/> </dict> <key>RunAtLoad</key> <true/> <key>SpawnConstraint</key> <dict> <key>team-identifier</key> <string>M2657GZ2M9</string> <key>signing-identifier</key> <string>com.demo.DemoMenuBar</string> </dict> </dict>
-
15:29 - Example library load constraint
// Example library load constraint <dict> <key>team-identifier</key> <dict> <key>$in</key> <array> <string>M2657GZ2M9</string> <string>P9Z4AN7VHQ</string> </array> </dict> </dict>
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。