爲什麼這段代碼是不安全的?爲什麼這個代碼是可被利用的?
#include <stdio.h>
int main(int argc, char *argv[])
{
printf(argv[1]);
printf("\n");
return 0;
}
爲什麼這段代碼是不安全的?爲什麼這個代碼是可被利用的?
#include <stdio.h>
int main(int argc, char *argv[])
{
printf(argv[1]);
printf("\n");
return 0;
}
printf
將處理它的第一個參數,尋找的東西像%d
和%s
。
基於這些值,它將從堆棧中獲取更多數據並將其打印出來。
所以,如果有人叫你的程序:
a.out "%d %d %d %d %d %d %d %d %d %d %d %d"
他們可以查看您的計算機的調用堆棧的一部分。
如果他們對格式說明符有更多的創造性,他們可能會轉儲一些重要的東西,比如信用卡號碼或密碼。
考慮一下的printf
控制的第一個參數(提示:printf
不只是讀它的輸入參數)。
看看什麼是一個格式化字符串漏洞:
由於海報問一個例子是什麼呢%n
:
的方式printf
格式字符串可以變化內存是使用%n
選項;通過「明智地」使用格式寬度說明符可以獲得要寫入的特定值。作爲一個測試:
#include <stdio.h>
int main(int argc, char **argv)
{
int *q = (int *)argv[0];
printf("%1$300000d%5$n",
123, // %1 - 1st param (formatted as '300000d')
0, // %2 - 2nd param (unused)
0, // %3 - 3rd param (unused)
0, // %4 - 4th param (unused)
argv[0]); // %5 - 5th param (written to via 'n')
printf("\nNow *q == %d\n", *q);
return 0;
}
如果你運行這個,看看輸出的最後一行,它會打印Now *q == 300000
(在Linux上測試)。
我使用printf()
這裏的,而未知位置格式的語法(%
<POS> $
<FMT>),以顯示如何能夠跳過參數選擇修改哪一個,而無需使用任何的「無趣」的。
我會讓讀者進行實驗來找出printf()
作爲printf(argv[1])
這樣的調用的「參數」。答案取決於您的系統的calling conventions(或相關,ABI),並且對於32/64位Windows/Linux/MacOSX等不同。
爲什麼我們應該爲您做作業? – 2012-04-09 21:12:42
http://en.wikipedia.org/wiki/Uncontrolled_format_string – 2012-04-09 21:13:04