在程式中,free()
被設計來釋放動態配置的記憶體空間。
Double Free 漏洞就是指 同一個記憶體區塊被 free()
了兩次或以上。
這會破壞 malloc/free
的內部資料結構(例如 fastbin freelist、tcache freelist),進而讓攻擊者能夠控制之後 malloc()
返回的記憶體位置。
常見原因:
NULL
,導致之後還能被 free()
。#include <stdio.h>
#include <stdlib.h>
int main() {
char *a = malloc(0x40);
free(a);
free(a); // 🚨 Double Free
return 0;
}
glibc 版本 | 狀態 | 說明 |
---|---|---|
< 2.26 | 高度可利用 | fastbin 沒有太多檢查,Double Free 幾乎可直接利用 |
>= 2.26 | 增加檢查 | 引入 tcache,針對連續釋放同一 chunk 有檢查,但仍可透過技巧繞過,例如交錯釋放或偽造 fd |
假設有一個 chunk A 被 free 了兩次,它會被插入 fastbin freelist 兩次:
fastbin -> A -> A -> ...
之後 malloc() 會依序取出,導致同一個指標被多次分配。
攻擊者可以:
在 glibc 2.26 之後,引入 tcache:
#include <stdio.h>
#include <stdlib.h>
int main() {
char *a = malloc(0x40);
char *b = malloc(0x40);
free(a);
free(b);
free(a); // 🚨 Double Free
return 0;
}
步驟 | 操作 | freelist 狀態 | 攻擊者效果 |
---|---|---|---|
1 | free(a) | a | chunk a 進入 freelist |
2 | free(b) | b -> a | chunk b 進入 freelist |
3 | free(a) again | a -> b -> a | chunk a 再次進入 freelist |
4 | malloc() -> a | b -> a | 指標 a 分配到 chunk a,可控制內容 |
5 | malloc() -> b | a | 指標 b 分配到 chunk b,可操作 a 內容## |
方法 | 說明 |
---|---|
設指標為 NULL | 每次 free 後將指標設為 NULL,避免重複釋放 |
使用安全記憶體管理 | 如 smart pointer 或 RAII 機制 |
glibc 檢查 | 新版 glibc 會檢查 double free,但仍需注意程式邏輯漏洞 |