エクスプロイト&脆弱性
脆弱性「CVE-2022-22583」と「CVE-2022-32800」に関する技術的な解説
本ブログでは、弊社側で考案した脆弱性「CVE-2022-22583」の攻撃手段、およびSIPバイパスに繋がる新しい脆弱性「CVE-2022-32800」について、技術的な視点を交えて解説します。
Apple社は2022年1月26日、フレームワーク「PackageKit」においてシステム整合性保護(SIP:System Integrity Protection)が回避(バイパス)される脆弱性「CVE-2022-22583」の修正対応を行いました。Apple社は、本脆弱性の解明に寄与したメンバーとして、Perception Pointの「Ron Hass(@ronhass7)」とトレンドマイクロの「Mickey Jin(@patch1t)」を挙げました。
Perception Pointのブログエントリでは、本脆弱性の包括的な解説や攻撃手段について述べられています。その内容を確認したところ、攻撃手段については、弊社が考案した方式とは異なることが分かりました。また、弊社側で本脆弱性の調査を進めていた際には、新たに別の脆弱性「CVE-2022-32800」も発見されました。
本ブログでは、弊社側で考案した脆弱性「CVE-2022-22583」の攻撃手段、およびSIPバイパスに繋がる新しい脆弱性「CVE-2022-32800」について、技術的な視点を交えて解説します。
本ブログは、SIPの脆弱性に関する発見事項を報告するブログシリーズの第3回目にあたり、今回で最終回となります。SIP自体の解説やデーモンサービスの特別な権限については、先月に公開したブログエントリをご参照ください。弊社では、これまでに15種以上に及ぶSIPバイパスの重大な脆弱性をApple社に開示し、その一部については、セキュリティ会議「Power of Community 2022 Security Conference(POC2022)」の場でも解説を行いました。
脆弱性「CVE-2022-22583」
「CVE-2022-22583」に関するセキュリティ課題
弊社では、プロセス監視によって本脆弱性を発見しました。Apple社の署名付きソフトウェア用インストーラパッケージファイル(PKG)をルートボリュームにインストールした際、高い権限を持つサービス「system_installd」によって下記スクリプトが生成されました。
/tmp/PKInstallSandbox.l57ygT/Scripts/com.apple.pkg.MXFPlugIns.yJpaxP/preinstall
/tmp/PKInstallSandbox.l57ygT/Scripts/com.apple.pkg.MXFPlugIns.yJpaxP/postinstall
サービス「system_installd」には特別な権限「com.apple.rootless.install.heritable」が付与されています。そのため、上記2スクリプトの実行に際しては、SIPの保護機能が回避(バイパス)されます。
両スクリプトがディレクトリ「/tmp/PKInstallSandbox.l57ygT」内に配備されていたことについて、下記の疑問が挙がりました。
- この一時領域内に置かれたスクリプトの内容を変更できるかどうか
- 当該フォルダ「PKInstallSandbox.ランダム文字列」はどのユーザまたはサービスによって作成されたか
- 作成されたフォルダはSIPによって保護されているか
この点について解明することを念頭に、調査を開始しました。
デバッグおよび解析の結果、当該の一時フォルダは以下の関数によって作成されたことが判明しました。
-[PKInstallSandbox prepareForCommitReturningError:]
16行目では、以下の別の関数を呼び出します。その関数は、内部でさらにAPI「mkdtemp」を呼び出すことで、制限なしでフォルダを作成します。
-[PKInstallSandbox _createDirectory:uniquifying:error:]
フォルダ「PKInstallSandbox.XXXXXX」は保護されていなかったため、最初はそこを突く形で攻撃が行える可能性を考えました。しかし、実際には当該フォルダの下層に置かれたスクリプトを直接変更することはできませんでした。その理由は、サブフォルダ「Scripts」へのアクセスは制限されていて、さらに図1の25行目が示すように、そのサブフォルダは制限されたサンドボックスのパスから移動されていたためです。
攻撃者側の視点に立つと、このセキュリティ網を突破して攻撃を行うための手段が少なくとも2つ存在します。
攻撃手段その1:マウント・トリック
第一に、マウントの仕組みを用いる手口が挙げられます。この詳細については、Perception Pointのブログで述べられています。当該ブログによると、攻撃の手順は下記の通りです。
- 仮想イメージファイルを作成し、「/private/tmp」にマウントする。
- Apple社の署名が付与され、かつポストインストールスクリプト(インストール後に実行される)が設定されたパッケージをインストールする。
- インストーラがスクリプト用ディレクトリを展開し終えるまで待機する。その後、当該ディレクトリのパスからランダム文字列の部位を特定する。
- イメージファイルのマウントを解除する。これにより「/private/tmp」の内容が、展開作業を開始する前の状態に戻される。
- スクリプト用ディレクトリを作成(手順3で抽出したランダム文字列を使用)し、実行させたい攻撃用スクリプトを投入する。
なお、Perception Pointのブログには、この攻撃が常に成功するとは限らないこと、そしてタイミングに依存することが述べられています。
攻撃手段その2:シンボリックリンク
トレンドマイクロが考案した攻撃手段では、シンボリックリンクの仕組みを使用します。その実行手順は下記の通りです。
1. 以下のディレクトリの作成を監視する。
/tmp/PKInstallSandbox.XXXXXX
作成された場合、そのディレクトリを以下の別の場所へのシンボリックリンクで置き換え、アクセス制限付きのスクリプトがそこに配備されるようにする。
/tmp/fakebox
2. スクリプトが以下にに配備された後、シンボリックリンクを削除する。
/tmp/fakebox
さらに、元と同じ名前の以下のディレクトリを再作成し、
/tmp/PKInstallSandbox.XXXXXX
そして攻撃用スクリプトを以下の下層ディレクトリに投下する。
/tmp/PKInstallSandbox.XXXXXX/Scripts/pkgid.XXXXXX/
3. 攻撃用スクリプトが実行されるまで待機する。
この攻撃手段の概念実証についてはGitHubにアップロードされています。図3に、概念実証の実演画面を示します。
ディレクトリ「/Library/Apple」はSIPによって保護されています。そのため、通常時はルートユーザであっても、そこにファイルを作成できません。しかし、上記の攻撃プログラムでは、SIPをバイパスできる状態で任意のコマンドを実行し、当該の制限付きディレクトリ内にもファイルを作成することが可能です。
脆弱性「CVE-2022-22583」に関するApple社の修正対応
サービス「installd」と「system_installd」の運用法について、若干ながら混同される傾向にあるようです。しかし、図4の修正コードの内、17行目と18行目を見ると、両サービスが明確に区別されていることが分かります。
修正パッチの動作として、インストールするパッケージにApple社の署名が付与されている場合、自身の制限付きサンドボックスパス内でフォルダ「OpenPath」が使用(図4の24行目)されます。それ以外のパッケージについては以前と同様、ディレクトリ「/tmp」内でランダム文字列のフォルダが使用(図24の30行目)されます。
サンドボックスのインストール
以降、2つ目の脆弱性「CVE-2022-32800」について解説します。まず、本脆弱性に関わる重要な技術要素として、「サンドボックスのインストール」に関する概念をいくつか紹介します。
サンドボックスのリポジトリ
はじめに、以下の関数によって作成、返却される「サンドボックスのリポジトリ」について説明します。
-[PKInstallSandboxManager _sandboxRepositoryForDestination:forSystemSoftware:create:error:]
簡潔に述べると、「サンドボックスのリポジトリ」には下記の4種が存在します。
インストール先がルートボリューム「/」:
Apple社による署名付きPKG:
/Library/Apple/System/Library/InstallerSandboxes/.PKInstallSandboxManager-SystemSoftware
その他のPKG:
/Library/InstallerSandboxes/.PKInstallSandboxManager
インストール先がルートボリューム以外:
Apple社の署名付きPKG:
[インストール先ボリューム]/.PKInstallSandboxManager-SystemSoftware
その他のPKG:
[インストール先ボリューム]/.PKInstallSandboxManager
特記事項として、「サンドボックスのリポジトリ」にアクセス制限がかけられるのは、パッケージにApple社の署名が付与され、そのインストール先がルートボリュームの場合に限られます。
サンドボックスのパス
「サンドボックスのパス」は、インストール時にスクリプトやペイロードを格納するディレクトリであり、「サンドボックスのリポジトリ」内部に配置されます。作成には、以下のメソッドが使用されます。
[PKInstallSandboxManager addSandboxPathForDestination:forSystemSoftware:]_block_invoke
サンドボックスのパスには4種が存在します。下記の通り、そのいずれも汎用一意識別子(UUID:Universally Unique Identifier)とサンドボックスの状態を表す文字列で構成されます。
- UUID.sandbox:初期生成時の状態
- UUID.activeSandbox:稼働状態;使用中
- UUID.trashedSandbox:停止状態;削除される予定
- UUID.orphanedSandbox:孤立状態;ディスク容量が不十分の場合にクリーンアップされる
PKInstallSandbox
「PKInstallSandbox」は、抽象化とカプセル化を意図したObjective-Cのクラス名です。
@interface PKInstallSandbox : NSObject <NSSecureCoding>
{
@public
NSString *_sandboxPath;
PKInstallRequest *_installRequest;
NSString *_scriptsPath;
NSString *_temporaryPath;
NSNumber *_stagedSize;
NSDate *_stageDate;
NSMutableDictionary *_scriptDirsByPackageSpecifier;
NSMutableDictionary *_bomPathsByPackageSpecifier;
NSMutableArray *_cleanupPaths;
NSDictionary *_scriptsAttributes;
NSDictionary *_temporaryAttributes;
NSSet *_previousPackageIdentifiersSharingGroupsWithSandbox;
long long _relevance;
BOOL _safeToReset;
}
+ (BOOL)supportsSecureCoding;
- (id)initWithCoder:(id)arg1;
(id)initWithSandboxPath:(id)arg1 installRequest:(id)arg2 error:(id *)arg3;
@end
クラス「PKInstallSandbox」のインスタンスは、以下のメソッドの呼び出しによって生成されます。生成は、「サンドボックスのパス」と、「インストールのリクエスト情報」に基づいて行われます。
-[PKInstallSandbox initWithSandboxPath:installRequest:error:]
本クラスのインスタンスは直列化(シリアライズ)が可能であり、オブジェクト偽装攻撃を防止するプロトコル「NSSecureCoding」にも準拠しています。サービス「system_installd」には、このインスタンスを直列化して、その内容をサンドボックスのパス上に、「SandboxState」のファイル名で保存する機能があります。この処理には、以下のメソッドが用いられます。
-[PKInstallSandboxManager saveSandboxAsStaged:]
一方、保存したファイル「SandboxState」の内容を非直列化(デジリアライズ)して元のインスタンスに復元する際には、以下のメソッドが用いられます。
-[PKInstallSandboxManager _sandboxAtPath:matchingRequest:forUse:]
上図の57行目を見ると、復元対象のインストール情報が、インストールクライアントから引き渡されたインストール情報に適合するかどうかを厳密にチェックする処理が入っています。攻撃者側の視点では、このチェック処理をいかに突破するかが1つの課題になります。
サービス「system_installd」は、インストール前に、インストールリクエスト情報に従って「PKInstallSandbox」のインスタンスを取得する必要があります。この処理は、以下の関数によって行われます。
-PKInstallSandboxManager sandboxForRequest:created:error:
当該関数のおおまかな処理内容は下記の通りです。
まず、「サンドボックスのリポジトリ」から、「.sandbox」の接尾辞を持つフォルダを全て取得します。次に、各フォルダ内にあるファイル「SandboxState」の内容をもとに、「PKInstallSandbox」のインスタンスを復元します。
インストールリクエスト情報に適合する「PKInstallSandbox」のインスタンスが見つからなかった場合、次は「.activeSandbox」の接尾辞を持つフォルダを全て取得し、そこからも同様にインスタンスの復元を試みます。
適合するインスタンスがなおも見つからない場合は、最後のステップとして、新しい「サンドボックスのパス」を作成し、新規に「PKInstallSandbox」のインスタンスを生成します。
脆弱性「CVE-2022-32800」
脆弱性の詳細
攻撃者は脆弱性「CVE-2022-32800」を突くことで、「SandboxState」のファイルを乗っ取り、SIPをバイパスする権限を取得できるようになります。
ファイル「SandboxState」は、「サンドボックスのリポジトリ」内に位置する「サンドボックスのパス」に格納されています。通常の場合、「サンドボックスのリポジトリ」にアクセスできるのは、Apple社の署名付きパッケージに限定されています。
しかし、インストール先がディスクイメージ(DMG:Disk Image)によるボリュームの場合、「サンドボックスのリポジトリ」に対するアクセス制限はありません。これは、ファイル「SandboxState」についても同様です。この状況ならば、偽の「SandboxState」を事前に準備しておくことで、復元処理中に生成されるインスタンス「PKInstallSandbox」をハイジャックし、その全メンバ変数を改ざんすることが可能です。
脆弱性を利用した攻撃手段
本脆弱性を突いた攻撃手段は、複数存在します。今回調査した例として、図12に示すメンバ変数「_cleanupPaths」を書き換えることで、SIPに保護されている任意のパスを削除する権限が得られました。
インストール作業が完了すると、その結果が成功でも失敗でも、以下の関数が呼び出され、メンバ変数「_cleanupPaths」で指定したフォルダやファイル、サンドボックスのデータが全て削除されます。
-[PKInstallSandboxManager _removeSandbox:]
本攻撃手段の概念実証はGitHubにアップロードされています。実演動画についても、こちらからご視聴いただけます。
脆弱性「CVE-2022-32800」に関するApple社の修正対応
Apple社は本セキュリティ課題をmacOS 12.5で修正対応しました。
修正箇所は、以下の関数に該当します。
-[PKInstallSandboxManager _sandboxAtPath:matchingRequest:forUse:]
38行目を見ると、内部で関数「PKSIPFullyProtectedPath」を呼び出していることが分かります。
Apple社の署名付きパッケージについては、ファイル「SandboxState」の信頼性、およびアクセス制限の有無をチェックする処理が追加されます。
セキュリティ推奨事項
脆弱性を突いた攻撃からシステムを保護するため、ユーザの方は定期的にオペレーティングシステム(OS)をアップデートすることを推奨します。セキュリティパッチを定期的に適用することで、脆弱性を狙う攻撃者による権限昇格などの不正な活動を阻止できる可能性が高まります。今回取り上げた脆弱性のうち、CVE-2022-22583は2022年1月に、CVE-2022-32800は2022年7月に修正パッチがリリースされています。
エンドユーザの方は、「ウイルスバスター™ for Mac」や「Trend Micro Protection Suites」などのセキュリティソリューションを用いることで、上述の脆弱性を狙った攻撃をより効果的に検知、阻止することが可能です。
参考記事:
A-Technical-Analysis-of-CVE-2022-22583-and-CVE-2022-32800
By: Mickey Jin
翻訳:清水 浩平(Core Technology Marketing, Trend Micro™ Research)