iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 17
1
Security

CTF 的三十道陰影系列 第 17

Day17: [Pwn] Educational Heap Exploitation - part 2

  • 分享至 

  • xImage
  •  

前言

接續昨天的 Educational Heap Exploitation,今天介紹的技巧在 glibc 2.29 中都已經被修復,不過其實大部分的 Linux distribution 都還沒使用 2.29,因此在撰寫 real world 的 exploit 時依然是很實用的技巧

Educational Heap Exploitation - part 2

1. unsafe_unlink.c

  • 上一篇有提到早期的 heap 題會考 dlmalloc 的 unlink 造成任意位置寫入的用法,但在 ptmalloc 在 unlink 時加入了 circular check,已經無法使用
  • ptmalloc unlink 的條件變成非常嚴苛,需要以下條件:
    1. 需要已知一個指向 heap 的變數 p,一般會需要 p 的位置,通常是在 bss 段
      • 因此在 PIE enable 的程式幾乎無法利用,如果能 leak 了有其他更簡單的利用方式......
    2. p 需要存在 UAF,並且能修改 fd 和 bk
    3. 操作完 p 的值會變成 &p-0x18,接著要能繼續對 p 寫兩次值,第一次改掉 p 指向的 address,第二次就造成任意位置寫入
    4. 接下來不能有任何 small bin 和 unsorted bin 的操作,否則程式通常會 abort
  • 詳細原理請參考:https://www.slideshare.net/AngelBoy1/heap-exploitation-51891400
  • 範例 code 存在 UAF 的漏洞,如果前一塊記憶體上的 chunk 有 bof 的問題也可以利用此方式,但前一個 chunk 不能是 freed 否則會一起被 merge
  • 文件上寫可利用版本是 < 2.26,但避開觸發 tcache 之後應該還是能使用

2. poison_null_byte.c

  • heap exploit 最典型的利用,在其他類型的 buffer 發生 null byte off-by-one 通常只能造成 crash,在 heap 上卻可以透過巧妙的排 heap 讓 chunk overlap 達到 RIP control
  • 跟 overlapping_chunks.c 和 overlapping_chunks_2.c 達成類似的效果
  • 最早看到相關的技術分析是由 Project Zero 揭露的 Ghost 漏洞所使用
  • 詳細原理請參考:https://www.slideshare.net/AngelBoy1/advanced-heap-exploitaion
  • 範例 code 的漏洞是真實用 null byte off-by-one 進行利用
    • a[real_a_size] = 0; // <--- THIS IS THE "EXPLOITED BUG"
  • 文件上寫可利用版本是 < 2.26,但避開觸發 tcache 之後,到 2.28 之前還是能使用
  • 2.29 增加 prev_size 要和上一塊 chunk size 大小相同的檢查,向後一塊做 unlink 造成 shrink chunk 已經不能用了

3. overlapping_chunks.c

  • 與昨天的 overlapping_chunks_2.c 做法類似,但這次是加大 freed chunk 的 size 來達成 overlap
  • 前一塊 chunk 不能是 freed 否則會觸發 unlink 造成 abort
  • 範例 code 存在 UAF 的漏洞,如果前一塊記憶體上的 chunk 有 bof 的問題也可以利用此方式
  • 文件上寫可利用版本是 < 2.26,但避開觸發 tcache 之後應該還是能使用

4. unsorted_bin_attack.c

  • 改寫 unsorted bin 的 bk,下次 malloc 之後會在 bk + 8 的位置寫上 unsorted bin 的 address
  • 無法控制寫入的內容,一般來說無法直接控制 RIP
  • 比較常見的用法是講 global_max_fast 的值改掉,這樣後面所有 chunk 都會以 fastbin 的方式進行處理
  • 2.29 後因為加入 unsorted bin 的 circular check 而無法使用
  • 範例 code 存在 UAF 的漏洞,如果前一塊記憶體上的 chunk 有 bof 的問題也可以利用此方式

5. unsorted_bin_into_stack.c

  • 與 unsorted bin attack 的原理一樣,但需要將 bk 指到偽造的 chunk
  • 跟 fastbin_dup_into_stack.c 效果一樣,通常會用到的情境是想讓 heap bof 變成 stack bof 進行 ROP

6. large_bin_attack.c

  • 有兩個利用前提:
    • 需要可以修改 largebin 上的 data
    • unsorted bin 要跟在 largebin 的後面
  • 與 unsorted bin attack 達成的效果類似,通常也要後續的 heap 利用才能達成 RIP control
  • 文件上寫可利用版本是 < 2.26,但避開觸發 tcache 之後應該還是能使用

0x10: PlaidCTF CTF 2015 Pwn 550 PlaidDB

解釋一下這篇現在才補的原因,當時想試試看在最新版的 glibc 2.29 有沒有辦法利用,在排除 tcache 的限制,在做 unlink 的時候怎麼樣都失敗 QQ 後來在做 Balsn CTF PlainNote 才發現 2.29 有對 unlink 做 harden ... QQ


這題 PlaidDB 應該是 heap 題正式進入血尿時代的開端...XD 概念是源自於 Project Zero 的技術文章 The poisoned NUL byte, 2014 edition (之前就有揭漏 off-by-one 的利用,但這邊講解得最清楚)

這題長得不像標準選單題的樣子,但其實差不多,只是變成透過 command 去操作功能,但逆向時痛苦的是在做儲存時不單純只是分配 heap,背後有用一個類似 RB tree 的 data structure 去儲存 chunk,因此這題要逆完程式的功能才有辦法開始排 heap

這題是實作了一個 database 的 service,每一筆資料表示一個 row,row 的結構大致如下:

struct row {
	char *key
	int size
	char *content
	row *left
	row *right
	row *parent
	bool is_leaf
}

database 支援的 command 如下:

  • GET
    • allocate 一段放 key 的 heap buffer,用 key 去向 database query 內容,結束會 free 掉 heap buffer 不會保存
  • PUT
    • 會先 allocate 大小為 0x38 的 row,再 allocate 8 byte 作為 key 的 buffer,最後根據輸入的 size 大小分配 content 的內容
    • 輸入 key 時如果超過 8 byte 就會用 realloc 重新分配兩倍的空間
  • DUMP
    • 列出目前所有的 key
  • DEL
    • GET 類似,allocate 一段放 key 的 heap buffer,如果 match 到就會把對應的 row 給 free 掉
    • 但如果沒有 match 到,前面 allocate 出來的 key buffer 會保存,可以用這個 bug (?) 來協助排 heap

這題的漏洞是在實作 input function 的地方存在 off-by-one 的問題,如果輸入的 key 長度剛好 match 目前 buffer size,就不會觸發 realloc,但是會在結尾補 \0,所有需要輸入 key 的地方都可以觸發

利用方式就是 2. poison_null_byte.c 提到的方式,在這就不再贅述,在 overlap chunk 之後,把 key 的 chunk 和 row 的 chunk 都落入可修改的範圍,就可以利用 DUMP 來 leak libc address

這題沒有 edit 的功能好用,因此 overlap 之後還是不好修改 chunk data,會需要利用 RB tree 做 node 搬移的功能,首先要把 row 偽造成以下的結構:

row->key = '/bin/sh'
row->size = 7
row->content = NULL
row->left = libc.sym['__free_hook']
row->right = libc.sym['__free_hook'] - 0x30
row->parent = libc.sym['__free_hook']
row->is_leaf = libc.sym['system']

這樣在觸發 DEL 的時候,__free_hook 就會被寫上 system,下一次再 free 就可以執行 system("/bin/sh") 拿到 shell

必須說這題是很有 DEF CON CTF 風格的一題,整個程式被包裝成很 real world,除了排 heap 以外需要了解整個 PlaidDB 如何運作,這種題目跟現在常見的選單題是各有優劣,但這題會有大量時間需要 reverse 程式,如果是剛學習 heap exploit 的新手就不太適合做這題


上一篇
Day16: [Pwn] Educational Heap Exploitation
下一篇
Day18: [Pwn] Educational Heap Exploitation - part 3
系列文
CTF 的三十道陰影31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言