
このリポジトリは、MISC Magazine #96に掲載された記事への追加です。
SMEP/SMAPおよびKASLRを有効にした仮想マシン上で、信頼性の高い方法で権限昇格を達成しました。ただし、システムは不安定な状態になり、oopsが発生する可能性が非常に高いことに注意してください。
configs/フォルダには、LinuxカーネルとBusyboxの設定ファイルがあり、それぞれデフォルトとは少し異なります。
binaries/フォルダには、テスト環境を再現するために必要なすべてのビルド済みバイナリが含まれています。例えば、QEMUで使用できる完全なrootfsなどです。
linux-stableは、脆弱なバージョンのLinuxカーネルを指すgitサブモジュールです。git submodule update --recursiveを使用して取得してください(システムに少なくとも1GBの空き容量が必要です...)。busyboxも同様です。
環境は、9Pを介してホストと共有フォルダを持つQEMU x86仮想マシンに基づいています。脆弱なバージョンのカーネル(ff33952e4d23)が、Busyboxの静的リンクビルドとともにコンパイルされています。
私たちの設定は非常にシンプルです。特殊なアーキテクチャやハードウェアをサポートする必要がないからです。make defconfigを実行して生成し、QEMUのネットワークとフォルダ共有をサポートするためにいくつかの機能を有効にしました。
CONFIG_BLK_MQ_VIRTIO=y
CONFIG_MEMORY_BALLOON=y
CONFIG_BALLOON_COMPACTION=y
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
CONFIG_NET_9P_DEBUG=y
CONFIG_VIRTIO_BLK=y
CONFIG_VIRTIO_BLK_SCSI=y
CONFIG_VIRTIO_NET=y
CONFIG_HVC_DRIVER=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM_VIRTIO=y
CONFIG_VIRTIO=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_PCI_LEGACY=y
CONFIG_VIRTIO_BALLOON=y
CONFIG_VIRTIO_INPUT=y
CONFIG_VIRTIO_MMIO=y
CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
CONFIG_9P_FS=y
CONFIG_9P_FS_POSIX_ACL=y
CONFIG_9P_FS_SECURITY=y
最初のPoCの開発を容易にするために、GDBスクリプトとデバッグシンボルも追加されました。
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF4=y
CONFIG_GDB_SCRIPTS=y
このバージョンでは、x86でKASLRがデフォルトで有効になっていることに注意してください。カーネルは再起動ごとに異なるアドレスにマッピングされるため、GDBはシンボルファイルをそれに一致させることができません。その場合、2つのオプションがあります:KASLRなしでテストを実行するか、GDBでシンボルをロードするときにカーネルのベースアドレスをsymbol-fileに渡すことです。
コンパイル後、linux-stable/arch/x86/boot/bzImageにbzImageがあります。
このファイルはbinaries/bzImageにあり、設定ファイルはconfifs/kernel.configにあります。使用するには、linux-stableに.configとしてコピーするだけです。
Busyboxの最新安定版1.28を使用しました。変更する設定はCONFIG_STATICだけで、yに設定します。コンパイルは問題なく行えるはずです。
設定ファイルはconfigs/busybox.configにあり、静的コンパイル済みバイナリはbinaries/busyboxにあります。Linuxと同様に、Busyboxのソースフォルダに.configとしてコピーしてください。
Busyboxは既に/etc/init.d/rcSを実行しようとするinitプロセスを実装しています。通常、これはディストリビューションによって提供されますが(別の名前かもしれません)、ここでは自分たちで行う必要があります!このスクリプトは、いくつかの必須システムフォルダ(proc、sys、dev)とホストと共有するフォルダを作成してマウントし、特権のないシェルにドロップします。
for i in $(seq 1 9); do mknod /dev/tty$i c 4 1; done
mknod -m 0666 /dev/null c 1 3
mknod -m 0660 /dev/ttyS0 c 4 64
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs none /dev
mkdir -p /mnt/share
mount -t 9p -o trans=virtio share /mnt/share/ -oversion=9p2000.L,posixacl,sync
chmod 777 /mnt/share/
export ENV=/etc/profile
setsid cttyhack setuidgid 1000 sh
umount /proc
umount /sys
umount /dev
poweroff -f
/etc/profileファイルは必須ではありませんが、テスト中、特にエクスプロイトが信頼性に欠け、ルート権限を取得するまでに数回の試行を要した場合に役立ちます。
エクスプロイト作成のプロセスはMISC 96で十分に文書化されています。unsafe_put_userを使用してメモリを探索し、ヒープのベースアドレスを見つけます。次に、何千ものclone呼び出しによって、多数のcred構造体をメモリにスプレーします。テスト中、それらのメモリ上の位置はforkを使用した場合よりもはるかに「一定」でした。これは、新しいタスクに対して割り当てられる構造体が少ないためです。
子プロセスを終了すると、誤ったページング要求によりカーネルoopsが発生します。これは正しく処理する必要があります。
このエクスプロイトの信頼性を向上させたい場合やドキュメントを追加したい場合、貢献を歓迎します!また、いくつかの概念について誤りや不正確さがあるかもしれません。何か間違っていると思ったら、遠慮なくIssueを開いてください。
Linuxカーネル
エクスプロイト