Cisco Japan Blog

脆弱性の詳細:Apple グラフィックス ドライバの不正利用と KASLR のバイパス

1 min read



Cisco Talos で脆弱性の調査を担当する Piotr Bania が最近 Apple Intel HD 3000 グラフィックス ドライバの脆弱性を発見しました。それについては、こちらのブログで紹介しています。 今回の記事では、この調査をさらに深く掘り下げて、この脆弱性と、 任意のコードがローカルで実行される可能性のある KASLR のバイパスとカーネルの不正利用について詳しく取り上げます。これらの手法は、ソフトウェアのサンドボックス技術を回避しようとするマルウェア作成者によって悪用される可能性があります。それは単純にソフトウェア プログラム(ブラウザやアプリケーションのサンドボックス)の中でも、カーネル レベルでも起こり得ます。

調査を進める課程で、Intel HD グラフィックス 3000 GPU を内蔵する Apple OS X コンピュータには、次に示す NULL ポインタを逆参照する脆弱性(バージョン 10.0.0)があることがわかりました。

通常、IOConnectCallMethod 関数でグラフィックス ドライバに基本のペイロードを送信すると、アドレス 0x1aa2f の NULL ポインタ参照により、カーネル パニックが発生します。この場合、RDX レジスタは NULL をポイントします。命令そのものが、利用不可のメモリからデータを読み取ろうとするため、カーネル パニックに陥ります。

この時点で、今回の脆弱性はローカルの DoS 攻撃のように見えますが、0x1aa68 の呼び出し命令が非常にくせ者です。この命令に到達できれば、ローカルでの Dos 攻撃からローカルでのコード実行にエスカレートさせることが可能となります。では、どのようなやり方で実行するのでしょうか。

DoS からローカルでのコード実行へとエスカレートさせるには、NULL ページのデータ(基本的に NULL アドレスで始まるメモリ領域)をマップできるかどうかを、まず確認する必要があります。NULL ページのマッピングは、最新の Microsoft Windows では利用できませんが、OS X システムでは引き続き使用可能です。ただし、いくつかの条件を満たす必要があります。

OS X で NULL ページをマッピングするための条件:

  • バイナリが 32 ビットであること
  • それから、-m32 -Wl,-pagezero_size,0 -O3 でコンパイルすること

これらの条件が揃えば、NULL ページ(基本的に NULL アドレスから始まるメモリ領域)でデータをマッピングできます。アドレス 0x1aa54 の比較で 0x1aa57 の JA ジャンプを強制的にスキップすると、最終的には 0x1aa68 の CALL 命令へとたどり着きます。RDI 値(0x1aa2f を参照)を制御できるため、0x1aa36 の EAX 値も制御できます。この制御は RAX の一部である EAX にもおよぶため、0x11a54 の比較条件をだますことができます。これにより、現在のアドレスが 0x1aa60 となり、基本的に 0x980 で記述されている任意のポインタ、つまり制御対象となるメモリを呼び出すことができます。

これらの制御が実行されると、次にすべきことは何でしょうか。

2013 年以降にリリースされた Intel の CPU では、SMEP(Supervisor Mode Execution Prevention)と呼ばれる機能が備わっているため、これらの条件は悪用できません。SMEP は、CPL = 0 のユーザモードのページ上にあるコードの実行を阻止します。つまり、NULL ページに書き込まれたシェルコードを直接呼び出すことで、カーネルのパニックが発生し、コードの実行が失敗します。ただしこの機能は、私たちが調査した Apple 装置には見られませんでした。

ステージ 1 – カーネル アドレスを取得

SMEP(Supervisor Mode Execution Prevention)と KASLR(カーネル アドレス空間配置のランダム化)は、特に Windows 8 や OS X の Yosemite など、最近の OS や CPU 実装で幅広く採用されています。SMEP/KASLR を実装している場合、ここでカーネルのメモリ アドレスを漏えいするための新たな脆弱性が必要となります。SMEP は私たちがテストしたバージョンの OS X では問題ないため、「過去の時代」にさかのぼってみます。はるか昔、2005 年の暗黒時代にさかのぼると、Windows 上でカーネル アドレスを取得するための手法として、SYSENTER_EIP_MSR Scandown 技術 [2] と呼ばれるものが存在しました。いくつかの変更点はありますが、今回は 64 ビットの OS X システムであるため、同じ考え方が適用できます。この例では、LSTAR(ロング システム ターゲットアドレス レジスター)と、カーネルの 64 ビット ソフトウェア向け RIP SYSCALL エントリが含まれる MSR レジスターのデータを読み取り、さらに下位スキャンして、カーネルの OS X シグニチャを見つけ出します。

つまり、stage0 ペイロードに入り、グラフィック ドライバーにシグニチャを送信した後、NULL ページの最初の 8 バイトに書き込まれたカーネル アドレスを取得する必要があります。


成功しました。カーネルのベース アドレスは、STAGE 2 シェルコードで後ほど使用する API アドレスの計算に欠かせません。これらの API は攻撃者が権限を昇格させるために必要です。

リークされたカーネル アドレスを入手できれば、必要な API アドレス(_current_proc、_proc_ucred、_posix_cred_get)を計算するのは簡単です。無償の MACH-O パーサーがたくさん出回っているので [3]、ステージ 2 に進みましょう。

ステージ 2 – シェルコードの実行

必要な API アドレスはすべて解決済みと想定し、ここからは最終段階となるシェルコードをカーネルに強制実行させます。この最終段階では、プロセスにルート権限を与え、シェルを実行します。このシェルコードは権限を昇格させるために必要な OS X のカーネル API を実行します。

ルート アクセスが可能となった状態での最終出力は次のとおりです。

まとめ

ここでは、DoS 脆弱性からローカルでのコード実行へのエスカレーションを見てきました。カーネル アドレスをマッピングすることで、ベース アドレスに戻り、必要な機能へのオフセットを計算し、KASLR をバイパスし、ルート権限を得られました。KASLR をバイパスし、攻撃をエスカレートさせる方法を理解することは、このような攻撃を軽減させる方法を学ぶ上で不可欠です。Cisco Talos はソフトウェアの脆弱性の調査、検出を行い、責任をもって開示することで、お客様が依存するプラットフォームやソフトウェア、さらにはオンライン コミュニティ全体の安全性の確保に役立っています。情報を開示することで、セキュリティ問題を特定でき、攻撃者による不正利用を防ぐことができます。新しいゼロデイ攻撃の発見は、お客様が利用するソフトウェアの全体的なセキュリティの改善に役立つだけでなく、シスコのセキュリティ開発のライフサイクルにおける手順の直接的な改善も可能にします。

概念実証

ここに示した概念実証エクスプロイトの完全版は、Cisco Talos の脆弱性開発チームのコード リポジトリから入手できます。
https://github.com/talos-vulndev/advisories/tree/master/TALOS-2016-0088/

参考資料

[1] – https://www.blackhat.com/docs/eu-15/materials/eu-15-Todesco-Attacking-The-XNU-Kernal-In-El-Capitain.pdf [英語]
[2] – http://www.uninformed.org/?v=3&a=4&t=txt [英語]
[3] – https://github.com/kpwn/tpwn/blob/master/lsym.m [英語]

本稿は 2016年4月7日に Talos Grouppopup_icon のブログに投稿された「VULNERABILITY DEEP DIVE: EXPLOITING THE APPLE GRAPHICS DRIVER AND BYPASSING KASLRpopup_icon の抄訳です。

コメントを書く