青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

woaidongmao

文章均收錄自他人博客,但不喜標(biāo)題前加-[轉(zhuǎn)貼],因其丑陋,見諒!~
隨筆 - 1469, 文章 - 0, 評(píng)論 - 661, 引用 - 0
數(shù)據(jù)加載中……

使您的軟件運(yùn)行起來(lái): 防止緩沖區(qū)溢出

http://www.ibm.com/developerworks/cn/security/buffer-defend/index.html#resources

上一篇專欄文章中,描述了高水平的緩沖區(qū)溢出攻擊,以及討論了為什么緩沖區(qū)溢出是如此嚴(yán)重的安全性問(wèn)題。本專欄文章的主題是,通過(guò)防御性編程保護(hù)代碼不受緩沖區(qū)溢出攻擊。我們將論及 C 編程語(yǔ)言中的主要安全性陷阱,顯示應(yīng)該避免特殊構(gòu)造的原因,以及演示推薦的編程實(shí)踐。最后,將討論有助于有效防止緩沖區(qū)溢出的其它技術(shù)。

C 中大多數(shù)緩沖區(qū)溢出問(wèn)題可以直接追溯到標(biāo)準(zhǔn) C 庫(kù)。最有害的罪魁禍?zhǔn)资遣贿M(jìn)行自變量檢查的、有問(wèn)題的字符串操作(strcpy、strcat、sprintf 和 gets)。一般來(lái)講,象“避免使用 strcpy()”和“永遠(yuǎn)不使用 gets()”這樣嚴(yán)格的規(guī)則接近于這個(gè)要求。

今天,編寫的程序仍然利用這些調(diào)用,因?yàn)閺膩?lái)沒(méi)有人教開發(fā)人員避免使用它們。某些人從各處獲得某個(gè)提示,但即使是優(yōu)秀的開發(fā)人員也會(huì)被這弄糟。他們也許在危險(xiǎn)函數(shù)的自變量上使用自己總結(jié)編寫的檢查,或者錯(cuò)誤地推論出使用潛在危險(xiǎn)的函數(shù)在某些特殊情況下是“安全”的。

第一位公共敵人是 gets()。永遠(yuǎn)不要使用 gets()。該函數(shù)從標(biāo)準(zhǔn)輸入讀入用戶輸入的一行文本,它在遇到 EOF 字符或換行字符之前,不會(huì)停止讀入文本。也就是:gets() 根本不執(zhí)行邊界檢查。因此,使用 gets() 總是有可能使任何緩沖區(qū)溢出。作為一個(gè)替代方法,可以使用方法 fgets()。它可以做與 gets() 所做的同樣的事情,但它接受用來(lái)限制讀入字符數(shù)目的大小參數(shù),因此,提供了一種防止緩沖區(qū)溢出的方法。例如,不要使用以下代碼:

void main()
  {
  char buf[1024];
  gets(buf);
  }

而使用以下代碼:

#define BUFSIZE 1024

void main()
  {
  char buf[BUFSIZE];
  fgets(buf, BUFSIZE, stdin);
  }

C 編程中的主要陷阱

C 語(yǔ)言中一些標(biāo)準(zhǔn)函數(shù)很有可能使您陷入困境。但不是所有函數(shù)使用都不好。通常,利用這些函數(shù)之一需要任意輸入傳遞給該函數(shù)。這個(gè)列表包括:

  • strcpy()
  • strcat()
  • sprintf()
  • scanf()
  • sscanf()
  • fscanf()
  • vfscanf()
  • vsprintf
  • vscanf()
  • vsscanf()
  • streadd()
  • strecpy()
  • strtrns()

壞消息是我們推薦,如果有任何可能,避免使用這些函數(shù)。好消息是,在大多數(shù)情況下,都有合理的替代方法。我們將仔細(xì)檢查它們中的每一個(gè),所以可以看到什么構(gòu)成了它們的誤用,以及如何避免它。

strcpy()函數(shù)將源字符串復(fù)制到緩沖區(qū)。沒(méi)有指定要復(fù)制字符的具體數(shù)目。復(fù)制字符的數(shù)目直接取決于源字符串中的數(shù)目。如果源字符串碰巧來(lái)自用戶輸入,且沒(méi)有專門限制其大小,則有可能會(huì)陷入大的麻煩中!

如果知道目的地緩沖區(qū)的大小,則可以添加明確的檢查:

if(strlen(src) >= dst_size) {
  /* Do something appropriate, such as throw an error. */
  }
       else {
  strcpy(dst, src);

完成同樣目的的更容易方式是使用 strncpy() 庫(kù)例程:

strncpy(dst, src, dst_size-1);
  dst[dst_size-1] = '\0'; /* Always do this to be safe! */

如果 src 比 dst 大,則該函數(shù)不會(huì)拋出一個(gè)錯(cuò)誤;當(dāng)達(dá)到最大尺寸時(shí),它只是停止復(fù)制字符。注意上面調(diào)用 strncpy() 中的 -1。如果 src 比 dst 長(zhǎng),則那給我們留有空間,將一個(gè)空字符放在 dst 數(shù)組的末尾。

當(dāng)然,可能使用 strcpy() 不會(huì)帶來(lái)任何潛在的安全性問(wèn)題,正如在以下示例中所見:

strcpy(buf, "Hello!");

即使這個(gè)操作造成 buf 的溢出,但它只是對(duì)幾個(gè)字符這樣而已。由于我們靜態(tài)地知道那些字符是什么,并且很明顯,由于沒(méi)有危害,所以這里無(wú)須擔(dān)心 ― 當(dāng)然,除非可以用其它方式覆蓋字符串“Hello”所在的靜態(tài)存儲(chǔ)器。

確保 strcpy() 不會(huì)溢出的另一種方式是,在需要它時(shí)就分配空間,確保通過(guò)在源字符串上調(diào)用 strlen() 來(lái)分配足夠的空間。例如:

dst = (char *)malloc(strlen(src));
  strcpy(dst, src);

strcat()函數(shù)非常類似于 strcpy(),除了它可以將一個(gè)字符串合并到緩沖區(qū)末尾。它也有一個(gè)類似的、更安全的替代方法 strncat()。如果可能,使用 strncat() 而不要使用 strcat()。

函數(shù) sprintf()vsprintf()是用來(lái)格式化文本和將其存入緩沖區(qū)的通用函數(shù)。它們可以用直接的方式模仿 strcpy() 行為。換句話說(shuō),使用 sprintf() 和 vsprintf() 與使用 strcpy() 一樣,都很容易對(duì)程序造成緩沖區(qū)溢出。例如,考慮以下代碼:

void main(int argc, char **argv)
  {
  char usage[1024];
  sprintf(usage, "USAGE: %s -f flag [arg1]\n", argv[0]);
  }

我們經(jīng)常會(huì)看到類似上面的代碼。它看起來(lái)沒(méi)有什么危害。它創(chuàng)建一個(gè)知道如何調(diào)用該程序字符串。那樣,可以更改二進(jìn)制的名稱,該程序的輸出將自動(dòng)反映這個(gè)更改。 雖然如此, 該代碼有嚴(yán)重的問(wèn)題。文件系統(tǒng)傾向于將任何文件的名稱限制于特定數(shù)目的字符。那么,您應(yīng)該認(rèn)為如果您的緩沖區(qū)足夠大,可以處理可能的最長(zhǎng)名稱,您的程序會(huì)安全,對(duì)嗎?只要將 1024 改為對(duì)我們的操作系統(tǒng)適合的任何數(shù)目,就好了嗎?但是,不是這樣的。通過(guò)編寫我們自己的小程序來(lái)推翻上面所說(shuō)的,可能容易地推翻這個(gè)限制:

void main()
  {
  execl("/path/to/above/program", 
  <<insert really long string here>>, 
  NULL);
  }

函數(shù) execl() 啟動(dòng)第一個(gè)參數(shù)中命名的程序。第二個(gè)參數(shù)作為 argv[0] 傳遞給被調(diào)用的程序。我們可以使那個(gè)字符串要多長(zhǎng)有多長(zhǎng)!

那么如何解決 {v}sprintf() 帶來(lái)得問(wèn)題呢?遺憾的是,沒(méi)有完全可移植的方法。某些體系結(jié)構(gòu)提供了 snprintf() 方法,即允許程序員指定將多少字符從每個(gè)源復(fù)制到緩沖區(qū)中。例如,如果我們的系統(tǒng)上有 snprintf,則可以修正一個(gè)示例成為:

void main(int argc, char **argv)
  {
  char usage[1024];
  char format_string = "USAGE: %s -f flag [arg1]\n";
  snprintf(usage, format_string, argv[0], 
  1024-strlen(format_string) + 1); 
  }

注意,在第四個(gè)變量之前,snprintf() 與 sprintf() 是一樣的。第四個(gè)變量指定了從第三個(gè)變量中應(yīng)被復(fù)制到緩沖區(qū)的字符最大數(shù)目。注意,1024 是錯(cuò)誤的數(shù)目!我們必須確保要復(fù)制到緩沖區(qū)使用的字符串總長(zhǎng)不超過(guò)緩沖區(qū)的大小。所以,必須考慮一個(gè)空字符,加上所有格式字符串中的這些字符,再減去格式說(shuō)明符 %s。該數(shù)字結(jié)果為 1000, 但上面的代碼是更具有可維護(hù)性,因?yàn)槿绻袷阶址既话l(fā)生變化,它不會(huì)出錯(cuò)。

{v}sprintf() 的許多(但不是全部)版本帶有使用這兩個(gè)函數(shù)的更安全的方法。可以指定格式字符串本身每個(gè)自變量的精度。例如,另一種修正上面有問(wèn)題的 sprintf() 的方法是:

void main(int argc, char **argv)
  {
  char usage[1024];
  sprintf(usage, "USAGE: %.1000s -f flag [arg1]\n", argv[0]); 
  }

注意,百分號(hào)后與 s 前的 .1000。該語(yǔ)法表明,從相關(guān)變量(本例中是 argv[0])復(fù)制的字符不超過(guò) 1000 個(gè)。

如果任一解決方案在您的程序必須運(yùn)行的系統(tǒng)上行不通,則最佳的解決方案是將 snprintf() 的工作版本與您的代碼放置在一個(gè)包中。可以找到以 sh 歸檔格式的、自由使用的版本;請(qǐng)參閱 參考資料

繼續(xù), scanf系列的函數(shù)也設(shè)計(jì)得很差。在這種情況下,目的地緩沖區(qū)會(huì)發(fā)生溢出。考慮以下代碼:

void main(int argc, char **argv)
  {
  char buf[256];
  sscanf(argv[0], "%s", &buf);
  }

如果輸入的字大于 buf 的大小,則有溢出的情況。幸運(yùn)的是,有一種簡(jiǎn)便的方法可以解決這個(gè)問(wèn)題。考慮以下代碼,它沒(méi)有安全性方面的薄弱環(huán)節(jié):

void main(int argc, char **argv)
  {
  char buf[256];
  sscanf(argv[0], "%255s", &buf);
  }

百分號(hào)和 s 之間的 255 指定了實(shí)際存儲(chǔ)在變量 buf 中來(lái)自 argv[0] 的字符不會(huì)超過(guò) 255 個(gè)。其余匹配的字符將不會(huì)被復(fù)制。

接下來(lái),我們討論 streadd()strecpy()。由于,不是每臺(tái)機(jī)器開始就有這些調(diào)用,那些有這些函數(shù)的程序員,在使用它們時(shí),應(yīng)該小心。這些函數(shù)可以將那些含有不可讀字符的字符串轉(zhuǎn)換成可打印的表示。例如,考慮以下程序:

#include <libgen.h>

void main(int argc, char **argv)
  {
  char buf[20];
  streadd(buf, "\t\n", "");
  printf(%s\n", buf);
  }

該程序打印:

\t\n

而不是打印所有空白。如果程序員沒(méi)有預(yù)料到需要多大的輸出緩沖區(qū)來(lái)處理輸入緩沖區(qū)(不發(fā)生緩沖區(qū)溢出),則 streadd() 和 strecpy() 函數(shù)可能有問(wèn)題。如果輸入緩沖區(qū)包含單一字符 ― 假設(shè)是 ASCII 001(control-A)― 則它將打印成四個(gè)字符“\001”。這是字符串增長(zhǎng)的最壞情況。如果沒(méi)有分配足夠的空間,以至于輸出緩沖區(qū)的大小總是輸入緩沖區(qū)大小的四倍,則可能發(fā)生緩沖區(qū)溢出。

另一個(gè)較少使用的函數(shù)是 strtrns(),因?yàn)樵S多機(jī)器上沒(méi)有該函數(shù)。函數(shù) strtrns() 取三個(gè)字符串和結(jié)果字符串應(yīng)該放在其內(nèi)的一個(gè)緩沖區(qū),作為其自變量。第一個(gè)字符串必須復(fù)制到該緩沖區(qū)。一個(gè)字符被從第一個(gè)字符串中復(fù)制到緩沖區(qū),除非那個(gè)字符出現(xiàn)在第二個(gè)字符串中。如果出現(xiàn)的話,那么會(huì)替換掉第三個(gè)字符串中同一索引中的字符。這聽上去有點(diǎn)令人迷惑。讓我們看一下,將所有小寫字符轉(zhuǎn)換成大寫字符的示例:

#include <libgen.h>

void main(int argc, char **argv)
  {
  char lower[] = "abcdefghijklmnopqrstuvwxyz";
  char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  char *buf;
  if(argc < 2) {
  printf("USAGE: %s arg\n", argv[0]);
  exit(0);
  } buf = (char *)malloc(strlen(argv[1]));
  strtrns(argv[1], lower, upper, buf);
  printf("%s\n", buf);
  }

以上代碼實(shí)際上不包含緩沖區(qū)溢出。但如果我們使用了固定大小的靜態(tài)緩沖區(qū),而不是用 malloc() 分配足夠空間來(lái)復(fù)制 argv[1],則可能會(huì)引起緩沖區(qū)溢出情況。





回頁(yè)首


避免內(nèi)部緩沖區(qū)溢出

realpath() 函數(shù)接受可能包含相對(duì)路徑的字符串,并將它轉(zhuǎn)換成指同一文件的字符串,但是通過(guò)絕對(duì)路徑。在做這件事時(shí),它展開了所有符號(hào)鏈接。

該函數(shù)取兩個(gè)自變量,第一個(gè)作為要規(guī)范化的字符串,第二個(gè)作為將存儲(chǔ)結(jié)果的緩沖區(qū)。當(dāng)然,需要確保結(jié)果緩沖區(qū)足夠大,以處理任何大小的路徑。分配的 MAXPATHLEN 緩沖區(qū)應(yīng)該足夠大。然而,使用 realpath() 有另一個(gè)問(wèn)題。如果傳遞給它的、要規(guī)范化的路徑大小大于 MAXPATHLEN,則 realpath() 實(shí)現(xiàn)內(nèi)部的靜態(tài)緩沖區(qū)會(huì)溢出!雖然實(shí)際上沒(méi)有訪問(wèn)溢出的緩沖區(qū),但無(wú)論如何它會(huì)傷害您的。結(jié)果是,應(yīng)該明確不使用 realpath(),除非確保檢查您試圖規(guī)范化的路徑長(zhǎng)度不超過(guò) MAXPATHLEN。

其它廣泛可用的調(diào)用也有類似的問(wèn)題。經(jīng)常使用的 syslog() 調(diào)用也有類似的問(wèn)題,直到不久前,才注意到這個(gè)問(wèn)題并修正了它。大多數(shù)機(jī)器上已經(jīng)糾正了這個(gè)問(wèn)題,但您不應(yīng)該依賴正確的行為。最好總是假定代碼正運(yùn)行在可能最不友好的環(huán)境中,只是萬(wàn)一在哪天它真的這樣。getopt() 系列調(diào)用的各種實(shí)現(xiàn),以及 getpass() 函數(shù),都可能產(chǎn)生內(nèi)部靜態(tài)緩沖區(qū)溢出問(wèn)題。如果您不得不使用這些函數(shù),最佳解決方案是設(shè)置傳遞給這些函數(shù)的輸入長(zhǎng)度的閾值。

自己模擬 gets() 的安全性問(wèn)題以及所有問(wèn)題是非常容易的。 例如,下面這段代碼:

char buf[1024];
  int i = 0;
  char ch;
  while((ch = getchar()) != '\n')
  {
  if(ch == -1) break;
  buf[i++] = ch;
  }

哎呀!可以用來(lái)讀入字符的任何函數(shù)都存在這個(gè)問(wèn)題,包括 getchar()、fgetc()、getc() 和 read()。

緩沖區(qū)溢出問(wèn)題的準(zhǔn)則是:總是確保做邊界檢查。

C 和 C++ 不能夠自動(dòng)地做邊界檢查,這實(shí)在不好,但確實(shí)有很好的原因,來(lái)解釋不這樣做的理由。邊界檢查的代價(jià)是效率。一般來(lái)講,C 在大多數(shù)情況下注重效率。然而,獲得效率的代價(jià)是,C 程序員必須十分警覺(jué),并且有極強(qiáng)的安全意識(shí),才能防止他們的程序出現(xiàn)問(wèn)題,而且即使這些,使代碼不出問(wèn)題也不容易。

在現(xiàn)在,變量檢查不會(huì)嚴(yán)重影響程序的效率。大多數(shù)應(yīng)用程序不會(huì)注意到這點(diǎn)差異。所以,應(yīng)該總是進(jìn)行邊界檢查。在將數(shù)據(jù)復(fù)制到您自己的緩沖區(qū)之前,檢查數(shù)據(jù)長(zhǎng)度。同樣,檢查以確保不要將過(guò)大的數(shù)據(jù)傳遞給另一個(gè)庫(kù),因?yàn)槟膊荒芟嘈牌渌说拇a!(回憶一下前面所討論的內(nèi)部緩沖區(qū)溢出。)





回頁(yè)首


其它危險(xiǎn)是什么?

遺憾的是,即使是系統(tǒng)調(diào)用的“安全”版本 ― 譬如,相對(duì)于 strcpy() 的 strncpy() ― 也不完全安全。也有可能把事情搞糟。即使“安全”的調(diào)用有時(shí)會(huì)留下未終止的字符串,或者會(huì)發(fā)生微妙的相差一位錯(cuò)誤。當(dāng)然,如果您偶然使用比源緩沖區(qū)小的結(jié)果緩沖區(qū),則您可能發(fā)現(xiàn)自己處于非常困難的境地。

與我們目前所討論的相比,往往很難犯這些錯(cuò)誤,但您應(yīng)該仍然意識(shí)到它們。當(dāng)使用這類調(diào)用時(shí),要仔細(xì)考慮。如果不仔細(xì)留意緩沖區(qū)大小,包括 bcopy()、fgets()、memcpy()、snprintf()、strccpy()、strcadd()、strncpy() 和 vsnprintf(),許多函數(shù)會(huì)行為失常。

另一個(gè)要避免的系統(tǒng)調(diào)用是 getenv()。使用 getenv() 的最大問(wèn)題是您從來(lái)不能假定特殊環(huán)境變量是任何特定長(zhǎng)度的。我們將在后續(xù)的專欄文章中討論環(huán)境變量帶來(lái)的種種問(wèn)題。

到目前為止,我們已經(jīng)給出了一大堆常見 C 函數(shù),這些函數(shù)容易引起緩沖區(qū)溢出問(wèn)題。當(dāng)然,還有許多函數(shù)有相同的問(wèn)題。特別是,注意第三方 COTS 軟件。不要設(shè)想關(guān)于其他人軟件行為的任何事情。還要意識(shí)到我們沒(méi)有仔細(xì)檢查每個(gè)平臺(tái)上的每個(gè)常見庫(kù)(我們不想做那一工作),并且還可能存在其它有問(wèn)題的調(diào)用。

即使我們檢查了每個(gè)常見庫(kù)的各個(gè)地方,如果我們?cè)噲D聲稱已經(jīng)列出了將在任何時(shí)候遇到的所有問(wèn)題,則您應(yīng)該持非常非常懷疑的態(tài)度。我們只是想給您起一個(gè)頭。其余全靠您了。





回頁(yè)首


靜態(tài)和動(dòng)態(tài)測(cè)試工具

我們將在以后的專欄文章中更加詳細(xì)地介紹一些脆弱性檢測(cè)的工具,但現(xiàn)在值得一提的是兩種已被證明能有效幫助找到和去除緩沖區(qū)溢出問(wèn)題的掃描工具。 這兩個(gè)主要類別的分析工具是靜態(tài)工具(考慮代碼但永不運(yùn)行)和動(dòng)態(tài)工具(執(zhí)行代碼以確定行為)。

可以使用一些靜態(tài)工具來(lái)查找潛在的緩沖區(qū)溢出問(wèn)題。很糟糕的是,沒(méi)有一個(gè)工具對(duì)一般公眾是可用的!許多工具做得一點(diǎn)也不比自動(dòng)化 grep 命令多,可以運(yùn)行它以找到源代碼中每個(gè)有問(wèn)題函數(shù)的實(shí)例。由于存在更好的技術(shù),這仍然是高效的方式將幾萬(wàn)行或幾十萬(wàn)行的大程序縮減到只有數(shù)百個(gè)“潛在的問(wèn)題”。(在以后的專欄文章中,將演示一個(gè)基于這種方法的、草草了事的掃描工具,并告訴您有關(guān)如何構(gòu)建它的想法。)

較好的靜態(tài)工具利用以某些方式表示的數(shù)據(jù)流信息來(lái)斷定哪個(gè)變量會(huì)影響到其它哪個(gè)變量。用這種方法,可以丟棄來(lái)自基于 grep 的分析的某些“假肯定”。David Wagner 在他的工作中已經(jīng)實(shí)現(xiàn)了這樣的方法(在“Learning the basics of buffer overflows”中描述;請(qǐng)參閱 參考資料),在 Reliable Software Technologies 的研究人員也已實(shí)現(xiàn)。當(dāng)前,數(shù)據(jù)流相關(guān)方法的問(wèn)題是它當(dāng)前引入了假否定(即,它沒(méi)有標(biāo)志可能是真正問(wèn)題的某些調(diào)用)。

第二類方法涉及動(dòng)態(tài)分析的使用。動(dòng)態(tài)工具通常把注意力放在代碼運(yùn)行時(shí)的情況,查找潛在的問(wèn)題。一種已在實(shí)驗(yàn)室使用的方法是故障注入。這個(gè)想法是以這樣一種方式來(lái)檢測(cè)程序:對(duì)它進(jìn)行實(shí)驗(yàn),運(yùn)行“假設(shè)”游戲,看它會(huì)發(fā)生什么。有一種故障注入工具 ― FIST(請(qǐng)參閱 參考資料)已被用來(lái)查找可能的緩沖區(qū)溢出脆弱性。

最終,動(dòng)態(tài)和靜態(tài)方法的某些組合將會(huì)給您的投資帶來(lái)回報(bào)。但在確定最佳組合方面,仍然有許多工作要做。





回頁(yè)首


Java 和堆棧保護(hù)可以提供幫助

如上一篇專欄文章中所提到的(請(qǐng)參閱 參考資料),堆棧搗毀是最惡劣的一種緩沖區(qū)溢出攻擊,特別是,當(dāng)在特權(quán)模式下?lián)v毀了堆棧。這種問(wèn)題的優(yōu)秀解決方案是非可執(zhí)行堆棧。 通常,利用代碼是在程序堆棧上編寫,并在那里執(zhí)行的。(我們將在下一篇專欄文章中解釋這是如何做到的。)獲取許多操作系統(tǒng)(包括 Linux 和 Solaris)的非可執(zhí)行堆棧補(bǔ)丁是可能的。(某些操作系統(tǒng)甚至不需要這樣的補(bǔ)丁;它們本身就帶有。)

非可執(zhí)行堆棧涉及到一些性能問(wèn)題。(沒(méi)有免費(fèi)的午餐。)此外,在既有堆棧溢出又有堆溢出的程序中,它們易出問(wèn)題。可以利用堆棧溢出使程序跳轉(zhuǎn)至利用代碼,該代碼被放置在堆上。 沒(méi)有實(shí)際執(zhí)行堆棧中的代碼,只有堆中的代碼。這些基本問(wèn)題非常重要,我們將在下一篇專欄文章中專門刊載。

當(dāng)然,另一種選項(xiàng)是使用類型安全的語(yǔ)言,譬如 Java。較溫和的措施是獲取對(duì) C 程序中進(jìn)行數(shù)組邊界檢查的編譯器。對(duì)于 gcc 存在這樣的工具。這種技術(shù)可以防止所有緩沖區(qū)溢出,堆和堆棧。不利的一面是,對(duì)于那些大量使用指針、速度是至關(guān)重要的程序,這種技術(shù)可能會(huì)影響性能。但是在大多數(shù)情況下,該技術(shù)運(yùn)行得非常好。

Stackguard 工具實(shí)現(xiàn)了比一般性邊界檢查更為有效的技術(shù)。它將一些數(shù)據(jù)放在已分配數(shù)據(jù)堆棧的末尾,并且以后會(huì)在緩沖區(qū)溢出可能發(fā)生前,查看這些數(shù)據(jù)是否仍然在那里。這種模式被稱之為“金絲雀”。(威爾士的礦工將 金絲雀放在礦井內(nèi)來(lái)顯示危險(xiǎn)的狀況。當(dāng)空氣開始變得有毒時(shí),金絲雀會(huì)昏倒,使礦工有足夠時(shí)間注意到并逃離。)

Stackguard 方法不如一般性邊界檢查安全,但仍然相當(dāng)有用。Stackguard 的主要缺點(diǎn)是,與一般性邊界檢查相比,它不能防止堆溢出攻擊。一般來(lái)講,最好用這樣一個(gè)工具來(lái)保護(hù)整個(gè)操作系統(tǒng),否則,由程序調(diào)用的不受保護(hù)庫(kù)(譬如,標(biāo)準(zhǔn)庫(kù))可以仍然為基于堆棧的利用代碼攻擊打開了大門。

類似于 Stackguard 的工具是內(nèi)存完整性檢查軟件包,譬如,Rational 的 Purify。這類工具甚至可以保護(hù)程序防止堆溢出,但由于性能開銷,這些工具一般不在產(chǎn)品代碼中使用。





回頁(yè)首


結(jié)束語(yǔ)

在本專欄的上兩篇文章中,我們已經(jīng)介紹了緩沖區(qū)溢出,并指導(dǎo)您如何編寫代碼來(lái)避免這些問(wèn)題。我們還討論了可幫助使您的程序安全遠(yuǎn)離可怕的緩沖區(qū)溢出的幾個(gè)工具。表 1 總結(jié)了一些編程構(gòu)造,我們建議您小心使用或避免一起使用它們。如果有任何認(rèn)為我們應(yīng)該將其它函數(shù)加入該列表,請(qǐng)則通知我們,我們將更新該列表。

函數(shù) 嚴(yán)重性 解決方案
gets 最危險(xiǎn) 使用 fgets(buf, size, stdin)。這幾乎總是一個(gè)大問(wèn)題!
strcpy 很危險(xiǎn) 改為使用 strncpy。
strcat 很危險(xiǎn) 改為使用 strncat。
sprintf 很危險(xiǎn) 改為使用 snprintf,或者使用精度說(shuō)明符。
scanf 很危險(xiǎn) 使用精度說(shuō)明符,或自己進(jìn)行解析。
sscanf 很危險(xiǎn) 使用精度說(shuō)明符,或自己進(jìn)行解析。
fscanf 很危險(xiǎn) 使用精度說(shuō)明符,或自己進(jìn)行解析。
vfscanf 很危險(xiǎn) 使用精度說(shuō)明符,或自己進(jìn)行解析。
vsprintf 很危險(xiǎn) 改為使用 vsnprintf,或者使用精度說(shuō)明符。
vscanf 很危險(xiǎn) 使用精度說(shuō)明符,或自己進(jìn)行解析。
vsscanf 很危險(xiǎn) 使用精度說(shuō)明符,或自己進(jìn)行解析。
streadd 很危險(xiǎn) 確保分配的目的地參數(shù)大小是源參數(shù)大小的四倍。
strecpy 很危險(xiǎn) 確保分配的目的地參數(shù)大小是源參數(shù)大小的四倍。
strtrns 危險(xiǎn) 手工檢查來(lái)查看目的地大小是否至少與源字符串相等。
realpath 很危險(xiǎn)(或稍小,取決于實(shí)現(xiàn)) 分配緩沖區(qū)大小為 MAXPATHLEN。同樣,手工檢查參數(shù)以確保輸入?yún)?shù)不超過(guò) MAXPATHLEN。
syslog 很危險(xiǎn)(或稍小,取決于實(shí)現(xiàn)) 在將字符串輸入傳遞給該函數(shù)之前,將所有字符串輸入截成合理的大小。
getopt 很危險(xiǎn)(或稍小,取決于實(shí)現(xiàn)) 在將字符串輸入傳遞給該函數(shù)之前,將所有字符串輸入截成合理的大小。
getopt_long 很危險(xiǎn)(或稍小,取決于實(shí)現(xiàn)) 在將字符串輸入傳遞給該函數(shù)之前,將所有字符串輸入截成合理的大小。
getpass 很危險(xiǎn)(或稍小,取決于實(shí)現(xiàn)) 在將字符串輸入傳遞給該函數(shù)之前,將所有字符串輸入截成合理的大小。
getchar 中等危險(xiǎn) 如果在循環(huán)中使用該函數(shù),確保檢查緩沖區(qū)邊界。
fgetc 中等危險(xiǎn) 如果在循環(huán)中使用該函數(shù),確保檢查緩沖區(qū)邊界。
getc 中等危險(xiǎn) 如果在循環(huán)中使用該函數(shù),確保檢查緩沖區(qū)邊界。
read 中等危險(xiǎn) 如果在循環(huán)中使用該函數(shù),確保檢查緩沖區(qū)邊界。
bcopy 低危險(xiǎn) 確保緩沖區(qū)大小與它所說(shuō)的一樣大。
fgets 低危險(xiǎn) 確保緩沖區(qū)大小與它所說(shuō)的一樣大。
memcpy 低危險(xiǎn) 確保緩沖區(qū)大小與它所說(shuō)的一樣大。
snprintf 低危險(xiǎn) 確保緩沖區(qū)大小與它所說(shuō)的一樣大。
strccpy 低危險(xiǎn) 確保緩沖區(qū)大小與它所說(shuō)的一樣大。
strcadd 低危險(xiǎn) 確保緩沖區(qū)大小與它所說(shuō)的一樣大。
strncpy 低危險(xiǎn) 確保緩沖區(qū)大小與它所說(shuō)的一樣大。
vsnprintf 低危險(xiǎn) 確保緩沖區(qū)大小與它所說(shuō)的一樣大。

在我們急匆匆講述這些基礎(chǔ)知識(shí)時(shí),到現(xiàn)在為止,已經(jīng)遺漏了一些緩沖區(qū)溢出很酷的細(xì)節(jié)。在下幾篇專欄文章中,我們將深入這臺(tái)“引擎”的工作,并給它加點(diǎn)黃油。我們將詳細(xì)地了解緩沖區(qū)溢出的工作原理,甚至還會(huì)演示一些利用代碼。



參考資料



作者簡(jiǎn)介

Gary McGraw是 Reliable Software Technologies 負(fù)責(zé)企業(yè)技術(shù)的副總裁,該公司位于美國(guó)弗吉尼亞州杜勒斯(Dulles)。他從事咨詢服務(wù)和研究工作,幫助決定技術(shù)研究和開發(fā)方向。McGraw 在 Reliable Software Technologies 從一個(gè)研究科學(xué)家做起,從事軟件工程和計(jì)算機(jī)安全性方面的研究。他擁有印第安那大學(xué)認(rèn)知科學(xué)和計(jì)算機(jī)科學(xué)雙博士學(xué)位,弗吉尼亞大學(xué)的哲學(xué)學(xué)士學(xué)位。他為技術(shù)刊物撰寫了 40 余篇經(jīng)同行審查的文章,擔(dān)任過(guò)主要的電子貿(mào)易供應(yīng)商(包括 Visa 和 Federal Reserve)的顧問(wèn)職務(wù),并在空軍研究實(shí)驗(yàn)室、DARPA、國(guó)家科學(xué)基金會(huì)以及 NIST 的高級(jí)技術(shù)項(xiàng)目贊助下?lián)纹涫紫{(diào)研員。

McGraw 是移動(dòng)代碼安全性方面著名的權(quán)威人士,并且與普林斯頓的教授 Ed Felten 合作撰寫了“Java Security: Hostile Applets, Holes, & Antidotes”(Wiley, 1996)以及“Securing Java: Getting down to business with mobile code”(Wiley, 1999)。McGraw 和 RST 創(chuàng)始人之一、首席科學(xué)家 Dr. Jeffrey Voas 一起編寫了“Software Fault Injection: Inoculating Programs Against Errors”(Wiley, 1998)。McGraw 定期為一些受歡迎的商業(yè)出版物撰稿,而且其文章經(jīng)常在全國(guó)出版的文章中所引用。


John Viega是一名高級(jí)副研究員,Software Security Group 的共同創(chuàng)始人,并擔(dān)任 Reliable Software Technologies 的高級(jí)顧問(wèn)。他是 DARPA 贊助的開發(fā)標(biāo)準(zhǔn)編程語(yǔ)言安全性擴(kuò)展的首席調(diào)研員。John 已撰寫了 30 余篇涉及軟件安全性和測(cè)試領(lǐng)域的技術(shù)性文章。他負(fù)責(zé)在主要網(wǎng)絡(luò)和電子商業(yè)產(chǎn)品中查找一些眾所周知的安全性弱點(diǎn),包括最近在 Netscape 安全性中的缺陷。他還是開放源碼軟件社區(qū)的重要成員,編寫過(guò) Mailman、GNU Mailing List Manager 以及最近發(fā)布的 ITS4(一種在 C 和 C++ 代碼中查找安全性弱點(diǎn)的工具)。Viega 擁有弗吉尼亞大學(xué)計(jì)算機(jī)科學(xué)碩士學(xué)位。

posted on 2008-05-10 20:56 肥仔 閱讀(921) 評(píng)論(0)  編輯 收藏 引用 所屬分類: C++ 基礎(chǔ)

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美精品一区在线| 欧美不卡视频一区发布| 国产资源精品在线观看| 国产麻豆91精品| 国产日产亚洲精品| 国产视频在线观看一区二区| 国产亚洲福利社区一区| 狠狠入ady亚洲精品经典电影| 国产一区美女| 亚洲精品之草原avav久久| 亚洲一本视频| 久久综合一区| 99国产精品视频免费观看一公开| 亚洲欧美日韩精品在线| 蜜臀av性久久久久蜜臀aⅴ四虎| 欧美精品一卡二卡| 国产一区二区三区四区五区美女| 亚洲欧洲精品天堂一级| 亚洲欧美色婷婷| 欧美激情亚洲自拍| 亚洲欧美日韩区| 欧美精品一区在线观看| 国精品一区二区| 亚洲小视频在线| 亚洲大片在线| 亚洲视频在线观看一区| 久久综合给合久久狠狠色| 国产精品日韩欧美| 亚洲欧洲日产国产网站| 小嫩嫩精品导航| 亚洲精品久久久久久久久久久久久| 亚洲自拍偷拍麻豆| 欧美日韩精品一区二区在线播放 | 国产嫩草一区二区三区在线观看| 黄色成人小视频| 亚洲欧美日韩一区在线观看| 欧美v日韩v国产v| 欧美一区二区三区在| 欧美日韩在线播放三区| 亚洲精品在线免费| 欧美成人一区二区三区| 久久精品亚洲精品| 国产无一区二区| 亚洲一二区在线| 99re66热这里只有精品3直播| 美女网站久久| 伊人狠狠色丁香综合尤物| 久久国产日韩欧美| 欧美日韩成人一区二区三区| 伊人久久大香线蕉综合热线| 午夜精品在线| 亚洲视频在线播放| 欧美私人网站| 亚洲一区二区高清| 亚洲人成在线免费观看| 裸体一区二区三区| 亚洲激情视频| 亚洲激情中文1区| 欧美freesex8一10精品| 最新国产成人av网站网址麻豆| 欧美1区免费| 美女网站在线免费欧美精品| 亚洲成色www久久网站| 欧美大尺度在线| 欧美高清视频一区二区| av成人激情| 一本不卡影院| 国产精品久久久久秋霞鲁丝 | 久久在线精品| 欧美在线观看一区二区| 国外成人在线| 欧美大片一区二区三区| 你懂的视频欧美| 一二三区精品| 亚洲摸下面视频| 黄色精品一区二区| 亚洲二区在线观看| 国产精品www994| 久久久久成人精品免费播放动漫| 久久精品一区蜜桃臀影院| 影音先锋中文字幕一区二区| 欧美电影打屁股sp| 欧美日韩在线播放三区| 欧美在线观看视频在线| 久久尤物视频| 亚洲永久在线观看| 久久久国产精品一区| 亚洲三级视频在线观看| 亚洲图片欧洲图片av| 红桃视频成人| 一区二区三区精品久久久| 国产日韩欧美在线视频观看| 免费观看成人| 国产精品美女久久久久久2018| 久久久久九九九| 欧美日韩精品二区| 久久在线免费| 国产精品免费看| 亚洲第一黄色| 国产一区二区久久| 一区二区冒白浆视频| 在线免费观看成人网| 99精品福利视频| 亚洲国产成人午夜在线一区| 亚洲午夜一级| 亚洲韩国日本中文字幕| 久久一区免费| 午夜在线一区二区| 欧美国产一区视频在线观看| 欧美一级二级三级蜜桃| 欧美精品一区二区三区在线播放| 久久精品五月| 国产精品啊啊啊| 亚洲茄子视频| 亚洲精品视频在线看| 久久网站热最新地址| 久久九九免费| 国产精品亚洲一区| 一区二区冒白浆视频| 日韩天堂在线观看| 另类春色校园亚洲| 免费人成网站在线观看欧美高清| 国产一区二区三区精品欧美日韩一区二区三区 | 亚洲午夜视频在线| 一区二区三欧美| 欧美黄色aaaa| 欧美大片专区| 亚洲国产经典视频| 久久嫩草精品久久久久| 久久久噜噜噜久久中文字免| 国产精品久久久久一区二区| 99在线精品视频| 一区二区三区国产在线观看| 欧美国产三区| 亚洲九九精品| 在线亚洲精品福利网址导航| 欧美精品一区二区三区一线天视频| 亚洲电影观看| 一本色道久久综合亚洲91| 欧美人与性动交cc0o| 夜夜嗨av一区二区三区网站四季av| 亚洲社区在线观看| 国产精品免费看久久久香蕉| 亚洲一区二区精品在线| 久久国产精品99久久久久久老狼| 国产女精品视频网站免费| 欧美一区观看| 欧美电影在线观看| 亚洲美女免费视频| 国产精品成人免费| 欧美夜福利tv在线| 蜜桃av一区二区| 99国产精品国产精品久久 | 国产精品国产成人国产三级| 中国女人久久久| 久久久久免费观看| 亚洲黄网站在线观看| 欧美日韩亚洲激情| 性做久久久久久久久| 欧美成人精品高清在线播放| 日韩午夜电影av| 国产精品白丝av嫩草影院| 亚洲欧美日韩专区| 欧美激情视频给我| 亚洲资源av| 亚洲高清视频的网址| 蜜桃久久精品乱码一区二区| 一本色道久久| 免费在线日韩av| 亚洲伊人观看| 欧美日韩国产丝袜另类| 欧美亚洲免费在线| 在线观看日韩av电影| 欧美日韩精品免费观看视频| 性色av一区二区三区在线观看| 欧美高清视频在线| 亚洲一区二区视频| 亚洲国产日韩欧美一区二区三区| 欧美日韩在线视频首页| 久久精品女人| 亚洲一区二区三区在线| 亚洲国产成人久久综合| 久久精品亚洲热| 中文国产一区| 亚洲黄色在线| 在线观看中文字幕不卡| 国产精品综合网站| 欧美三级电影一区| 欧美成年人视频| 久久久久久久综合色一本| 亚洲一区二区欧美日韩| 亚洲美女免费视频| 亚洲二区视频| 欧美国产91| 欧美xx视频| 欧美freesex交免费视频| 久久免费国产| 久久久久国产精品麻豆ai换脸| 午夜精品视频| 亚洲综合另类|