~主にプログラミング関係この広告は、90日以上更新していないブログに表示しています。はじめにカーネルエクスプロイト入門記事part2です。前回part1では、環境構築とLinuxカーネルのメモリ管理の基礎について、実際のエクスプロイトでのユースケースを通して説明しました。rkx1209.hatenablog.comさて、part2では実際にLinuxカーネルエクスプロイトを書いて行きます。いえ既存の脆弱性を利用するエクスプロイトを記述するのはあまりよろしくないので、今回は学習用に脆弱なドライバを用意し、エクスプロイトを書いていきます。基本的なロジックは実際の脆弱性のそれと同じなので、意義はあるはずです。学習用ドライバとエクスプロイトコードは以下のレポジトリに置いてありますので、各節ごとに逐次参照してください。ももいろテクノロジーといろいろあります。攻撃者はプログラムの意図しないアドレスに値を書き込む(アドレスや値は制限がある場合もあります。)書き込む先はプログラムが制御を移す可能性のある、関数ポインタや、戻りアドレスにする。gadget(後述)のアドレス。これで、攻撃者の用意したコードにプログラムが飛ばされて意図しない動作をさせられるわけです。いった脆弱性をついたエクスプロイト手段というのはユーザープログラムだけでなく、カーネルにも適用できます。LinuxやWindowsもOSとは言え特権モードで動作しているただのプログラムなのでバグもありますし、ユーザー側からシステムコール発行や、外部からのデータ受信などを入力としてそのバグを突く事は可能なわけです。http://thehackernews.com/2016/12/linux-kernel-local-root-exploit.html基本的なエクスプロイトのロジックはユーザー空間もカーネル空間も大差ありません。加えてカーネルは特権モードで動作していて、その最中に攻撃者に制御を奪われて任意コード実行などされると、システム内の最高権限で攻撃コードが走ります。これが凄い威力で、カーネルエクスプロイトの面白さの一つです。俗に言うJailBreakというのも、カーネルレベルで実装されたアクセス制御機構(Jailとかsandboxとかいろいろ呼び方はあります)を、カーネルエクスプロイトによる特権モードでのコード実行で解除する物です。PlayStation4のカーネルエクスプロイトコード中のJailBreakを行う部分は以下のような感じになってます。&prison0;とやると、簡単にjailを無効化できます。これはこの攻撃コードが特権モードで動作しているからです。ユーザー空間でこんなプログラム書いてもViolationで弾かれます。Programming)さて、では実際にカーネルエクスプロイトでよく使われるテクニックの一つとしてまずカーネルROPを紹介します。gadgetと呼ばれるコード断片に次々と飛ばしながら意図した動作を行わせるテクニックです。gadgetを探すツールはrp++を利用します。ももいろテクノロジーこのROPのテクニックは相応の脆弱性があればカーネルに対しても通用します。ここから先登場するコードは全て以下のレポジトリにありますので逐次参照して自分でも動かしてみてください。GitHub今回は以下のような脆弱なドライバを用意します。0を発行すると、引数で指定されたoffsetをopsのアドレスに足した場所をcallしてくれます。1すると、指定された引数で飛ぶ先のアドレスを表示してくれます。こんな感じでユーザーからは使うわけです。0;}なんとも都合の良いドライバですが、Linuxのような複雑なコードに潜む脆弱性を極限まで簡単にモデル化した物だと思っていただければ。実際のカーネルエクスプロイトではこれらに加えて様々な制約が伴うわけですが....ちなみにdmesgを確認すればopsのアドレスも分かります。ffffffffa02e9340さて、ではこの引数で指定されたアドレスに飛んでくれるドライバをどのように利用するか。考えられるのが、どこか別の領域に攻撃者のコード(shellcode)を置いておいて、そこに飛ぶというやつです。どこに置くかですが、カーネルの使用しているメモリ領域は使えません。それをやるにはドライバを書いてkmallocなりでカーネルからメモリを確保する必要があり、その段階でroot権限が必要だからです。ユーザー空間に置いてそこに飛ぶのはどうでしょう。これは俗にret2usrと呼ばれるカーネルエクスプロイトの手法で、うまく行く事もあります。SMEPというプロセッサレベルのセキュリティ機構が有効になっていると、カーネル空間からユーザー空間のコードに直接実行を移すことができなくなります。そこでカーネルROPを使います。gadgetに制御を移していく事でSMEPが回避できるわけですね。カーネル内のgadgetを探してみましょう。gadgets.txtLinuxカーネル本体はvmlinuxと呼ばれるELFファイルで、カーネルをビルドしたディレクトリの直下に生成されています。gadgetが探せます。見つけたgadgetは後から参照できるようgadgets.txtに書き出しておきます。gadgetは集めましたが結局ドライバのコードジャンプを使ってどこに飛べばよいでしょうか?そもそもROPというのは攻撃者があらかじめスタックにgadgetのアドレスを載せておく必要がありましたが、今回はカーネル内のスタックにgadgetのアドレスを載せていく事はできません。Pivotテクニックを使うことでカーネル内のスタックアドレスをその領域にすげかえてやるのが良さそうです。Pivotについては以下参照。*%raxとなっています。opsにoffsetを足したアドレスはraxに入ってるわけです。このアドレスをrax=0xffffffff81000085にしたとしましょう。eax,espを実行するとスタック(rsp)も0x81000085になります。0x81000085の領域にmmapでメモリを確保しておけば、そこがスタックとして扱われるわけです。rspとかで丸ごとスタックアドレスにすれば良いのでは?と思われるかもしれませんが、うまくいきません。0xffff880000000000~となっており、0xffffffff81000085をユーザー空間からmmapする事はできません。よって下位32bitの0x81000085であれば、ユーザー空間内なのでmmap可能なわけです。これがraxでなくeaxを使う理由です。あとはこのmmapした領域にgadgetのアドレスを書き込んで行けばOKです。gadgetはどれを使っても良いわけではありません。いうと、ops+offsetとして指定できるアドレスはカーネルの制約上8byteでアライメントされてる必要があるからです。8byteアライメントされたgadgetのみ表示するスクリプトとしてfind_offset.pyを使ってください。gadgetが記録されてるgadgest.txtを指定すると、8byteアライメントされたgadgetのみを探してoffset値と共に表示してくれます。esp'などして、求めるgadgetのoffset値を表示しましょう。Pivotが完了しました。後はどんなgadgetを実行させていくかですが、カーネル内で現在実行中のプロセスにroot権限を付与するには以下のようなコードを実行する必要があります。gadgetを使ってカーネル内で実行させてユーザー空間に戻ればroot権限が付与されます。ここまで来れば実際のエクスプロイトコードを見てみましょう。Pivotでカーネルのrspをこの値に設定するわけです。gadgetを積んでいっている部分です。図解するとスタックは以下のようになります。図中のアドレスとコードのアドレスが対応していませんが、これは引用元のカーネルのバージョンと違うからです。中身の命令列を見て頂けると幸いです。)このROPは順番に以下のように実行されていきます。%rdiでprepare_kernel_credの実行結果(rax)をrdiに設定。commit_cred)これでcommit_creds(prepare_kernel_cred(0))が実行されます。これでめでたくプロセスにroot権限が付与されました。後はユーザー空間に戻りましょう。ユーザー空間に戻るのはexploit.cの以下が該当します。gadgetの続きを見てみましょう。iretqという命令のgadgetを載せており、その下にさらにshell関数へのアドレス、user_cs,user_rflags...と続きます。このiretq命令こそが、カーネル空間からユーザー空間に戻るための命令です。iretについては詳しくは以下参照。+------------+それぞれのレジスタをこのスタックに積んである値にしてくれます。よってshell関数のアドレスをRIPとして積んでおくと、iret実行直後RIPはshell関数先頭に設定されて制御が移り、/bin/shが起動するわけです。先ほどカーネル空間でcommit_credをしているので、プロセスはroot権限になっておりこれでrootのシェル起動完了です。ちなみにiretq命令は以下のようにしてカーネル内から探してきてください。おわりにさて、今回はカーネルエクスプロイトでよく使うカーネルROPについて説明しました。」を受講する方は上記のROPエクスプロイトを理解して自分の環境で動かしroot権限昇格まで確認しておいてください。gadgetのアドレスが上とかなり違うはずなので、自分でrp++等で調べてアドレスを変更し、うまく動かしてみてください。)月別アーカイブはてなブログをはじめよう!RKX1209さんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。