
Linux ELF x32/x64 向け ASLR/DEP/NX バイパスエクスプロイト(スタックスプレー使用)
Linux ELF x32/x64 ASLR DEP/NX バイパスエクスプロイト(スタックスプレー使用)

特性:
依存関係:
制限事項:
ヒープスプレー攻撃をご存知でしょうか?ヒープスプレー攻撃をご存知でしょうか?スタックスプレーも同様ですが、ほとんどの場合、特にx86-64のASLRでは実用的ではないと考えられていました。
私の研究はその逆を証明します。
32ビットの場合、理論的には2^32 (4,294,967,296)のアドレスが存在しますが、カーネルは仮想化メモリ内での実行に対して約半分のビット (2^(32/2) = 65,536) しか制御できません。つまり、スタック内で50,000文字以上を制御できれば、カーネルのリダイレクションと再変換のおかげで、アドレスに関係なくほぼ確実にシェルコードを指すことができます。私のテストによると、呼び出された関数が他の変数を作成しない場合、100文字や10文字でも十分であり、ROPスタイルの攻撃が可能になります。
これはシェル変数を使用して実現できます。シェル変数には特定の長さの制限はありませんが、実用的な制限は約10万文字で、それを超えるとTTYが飽和します。
したがって、任意のシェルコードでエクスプロイトを成功させるには、シェルコードの後にNOPスレッドを配置してシェル変数に格納し、ランダムなアドレスでバイナリをエクスプロイトするだけです。なお、NOPスレッドは必須ではなく、エクスプロイトを汎用化するためのものです。
64ビットシステムでは状況が異なりますが、私の発見によればそれほど大きな違いはありません。
もちろん、2^64のすべての可能性をカバーする必要はありません。実際、カーネルは48ビットしか許可しておらず、さらにその一部は予測可能で静的なため、約2^(4x8+5) (137,438,953,472) の可能性が残ります。
シェル変数のサイズ制限について述べましたが、個数にも制限があり、それは約10のようです。これにより、100万文字のシェルコードを格納でき、数千分の一程度の可能性だけが残り、迅速かつ自動的にテストできます。ただし、今回はブルートフォースとNOPスレッドを使用して処理を高速化する必要があります。
とはいえ、32ビットと64ビットの両方のASLRは、数分と数行のシェルで簡単にバイパスできます...
一方、DEP/NXはx32では、return-to-libc テクニックを使用し、異なるOSの統計的研究、特にASLRの制限と実装と組み合わせることでバイパスできます。これにより、2つの理由でエクスプロイトが成功する可能性があります。 第一は、ASLRの選択がそれほどランダムではなく、いくつかの定数とエントロピーの低さがあることです(libCアドレスを推測しやすく、各OSに独自の定数があります)。 第二は、libCのシェル引数を環境にスプレーすることです(簡単に見つけてlibCに渡せます)。
結論として、32ビットのDEP/NXはASLRによって弱体化されます。
より詳細な説明はHakin9-12-14の号にあります。
もし人生で一度でもバッファオーバーフローをエクスプロイトしたことがあれば、このセクションは飛ばして構いませんが、念のため:
apt install gcc libc6-dev-i386 || kill -9 $$
chmod u+x ASLRay.sh
sudo gcc -z execstack test.c -o test
sudo gcc -m32 -z execstack test.c -o test32
sudo chmod +s test test32
source ASLRay.sh test32 1024
source ASLRay.sh test 1024
source ASLRay.sh test 1024 \x31\x80...your_shellcode_here
sudo gcc -m32 test.c -o test32x
sudo chmod +s test test32
source ASLRay.sh test32x 1024
NOPスレッドがDebian x32で不要であることを証明するには:
!!! 警告 !!! これは /etc/passwd を変更し、/etc/shadow のパーミッションを変更します。VMでの実行を推奨します。
chmod u+x PoC.sh
source PoC.sh
grep ALI /etc/passwd
それでも動作しない場合は、先頭にいくつかのNOP (\x90) を追加してください。
Debian x32では環境変数さえも不要であることを証明するには:
chmod u+x PoC2.sh
source PoC2.sh
これにより、シェルコードを変数に格納し、レジスタにランダムなアドレスを与えてASLRが有効なシェルを取得できます。これは、関数が1つの変数のみを持ち、それが書き換えられる特定のコンテキストであり、その結果スタックがシェルコードだけでEIPにポップされるためです。これはROP攻撃に似ています。
Arch/Ubuntuでは、スタック破壊保護を無効にする必要があり、ブルートフォースにはかなりの時間がかかる可能性があります(実行遅延、おそらくbrk(NULL/0)システムコールまたは/およびカナリアによる):
sudo gcc -z execstack -fno-stack-protector test.c -o test
sudo gcc -m32 -z execstack -fno-stack-protector test.c -o test32
sudo gcc -m32 -fno-stack-protector test.c -o test32x
Debian 10では、この問題は部分的に修正されました。特にAppArmorによるものです。
常に単一の保護ではなく、複数の保護に依存すべきです。
新しいシステムセキュリティメカニズムが必要です。
「私たちの立っている場所から見ると、雨はランダムに見える。別の場所に立てば、そこに秩序を見ることができるだろう。」 トニー・ヒラーマン、コヨーテは待つ