前幾篇文章中,我們針對 Stack Buffer Overflow 說明了許多不同的攻擊手法與相對應的保護機制。在這幾篇文章中我們都沒有開啟 PIE(可執行區段隨機載入地址)與 Canary(Saved RBP 之前存一檢查值)的保護機制。
我們有提到,要繞過這兩種保護機制常常會搭配 Leak Address 的手法,本篇將介紹一種相對常見、有機會拿來做 Leak Address 的漏洞 - Format Strings。
Format Strings 漏洞(格式化字串漏洞)源於 C/C++ 程式語言中,常見的 printf()、sprintf()、fprintf() 等格式化輸出函數在處理使用者輸入時,沒有正確檢查輸入字串的格式化參數,導致攻擊者可以利用這些函數來進行攻擊。
當開發者使用格式化函數,如 printf("%s", input)
,理想情況下應該要指定格式化參數(如上述的 %s
) 並搭配變數來正確顯示輸出的字串。如果開發者疏忽,直接傳入未經檢查的輸入值(如 printf(input)
),則使用者輸入的字串不但會被直接輸出,還可能包含額外的格式化指令。這樣一來,攻擊者可以利用格式化字串漏洞,讀取甚至修改記憶體內容。
以 printf("Hi, %s", input)
為例,前面的 "Hi, %s"
即為格式化參數,格式化參數包含普通字元與轉換規則,普通字元如 Hi
會直接輸出,轉換規則如 %s
會依據對應的轉換類型,將後續的參數進行轉換並輸出。
以下為幾種轉換類型的說明:
轉換類型 | 說明 |
---|---|
%c | 以字元方式輸出 |
%d | 以十進制整數的方式輸出 |
%x | 以十六進制整數的方式輸出 |
%s | 將參數當作字串處理並輸出 |
%p | 以指標(地址)的方式輸出 |
格式化參數除了最前面要有 % 最後面要有轉換類型標示外,中間還可以加上一些可選部分,其中一個特殊的可選部分為 [parameter],我們直接看個例子:
int a = 10, b = 20, c = 30;
printf("%2$d %3$d %1$d", a, b, c);
// Output: 20 30 10
可以看到 %d
中間夾雜了 2$
、1$
等等的內容即為 [parameter],它以 $ 代表後面的參數,前面的數字代表第幾個參數,2$
即為第二個參數,也就是 b。
接下來我們會詳細說明 Format Strings 是如何運作的,我們先看個例子:
printf("%s%d", "ID", 2);
// Output: ID2
此時這個 printf()
參數如下:
內容 | 儲存位置 | |
---|---|---|
第一個參數 | "%s%d" | RDI 暫存器 |
第二個參數 | "ID" | RSI 暫存器 |
第三個參數 | 2 | RDX 暫存器 |
實際輸出時,當格式化參數(即第一個參數),遇到 % 就會往後抓後面的參數作處理並輸出。所以第一個 %(%s
)將後續第一個參數(即存入 RSI 的第二個參數)其作為字串(s)作處理並輸出。
第二個 %(%d
)將後續第二個參數(即存入 RDX 的第三個參數)作為十進制整數(d)作處理並輸出。
那如果現在的例子變成這樣呢:
printf("%s%d%p", "ID", 2);
在這裡,格式化字串 "%s%d%p" 期待三個參數,但實際上只提供了兩個("ID" 和 2)。這會導致 printf 繼續往下一個參數應該存在的位址找,也就是此時除了會輸出 ID2 以外還會輸出第四個參數的位址(%p),即使我們沒有給他參數。
內容 | 儲存位置 | |
---|---|---|
第一個參數 | "%s%d%p" | RDI 暫存器 |
第二個參數 | "ID" | RSI 暫存器 |
第三個參數 | 2 | RDX 暫存器 |
第四個參數 | RCX 暫存器 |
所以如果程式這樣寫:
printf("%s%d%p%p%p%p%p", "ID", 2);
我們就可以一直往後取,從一開始的 RSI、RDX、RCX、R8、R9 暫存器一直到 Stack 上(x86-64 架構中,用完六個暫存器會存到 Stacl 上)。
但程式沒道理會這樣寫,那們 Format Strings 會在什麼情況下觸發呢?我們看個例子:
char buf[0x100];
fgets(buf, 0x100, stdin);
printf(buf);
這代表什麼呢?這代表我們輸入的內容,會直接作為 printf 的第一個參數,即格式化參數,我們就可以輸入我們需要的格式化參數,例如上述的 "%s%d%p%p%p%p%p"
。藉此可以獲得我們想要的位置的值或位址,以達成資訊洩漏。
實際在利用此漏洞時,通常會搭配整個程式的其他漏洞,藉由精確的控制格式化參數來達成目的,後續的文章中有機會會利用格式化漏洞輔助攻擊。