• <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>
            Dict.CN 在線詞典, 英語(yǔ)學(xué)習(xí), 在線翻譯

            學(xué)海苦作舟,書山勤為徑

            留下點(diǎn)回憶

            常用鏈接

            統(tǒng)計(jì)

            積分與排名

            Denoise

            English study

            Web技術(shù)

            數(shù)據(jù)壓縮

            一些連接

            最新評(píng)論

            Strlcpy和strlcat-一致的、安全的字符串復(fù)制和串接

            ?

            概要:

            時(shí)下緩沖區(qū)溢出攻擊已經(jīng)增加,越來(lái)越多的程序員使用帶有 size 或長(zhǎng)度邊界的字符串函數(shù),例如: strncpy strncat 。這的確是一個(gè)趨勢(shì),但標(biāo)準(zhǔn)的 C 字符串函數(shù)并不是真正為這些任務(wù)而設(shè)計(jì)的。本文描述一個(gè)專門設(shè)計(jì)用于安全字符串復(fù)制的可選的、直覺(jué)的和一致的 API

            strncpy strncat 作為 strcpy strcat 安全版本有幾個(gè)問(wèn)題。兩個(gè)函數(shù)都是以不同的和非直覺(jué)的方法來(lái)處理 NULL 結(jié)尾的和長(zhǎng)度參數(shù),即使有經(jīng)驗(yàn)的程序員都有時(shí)迷惑;而檢查什么時(shí)候發(fā)生截?cái)嘁彩遣蝗菀椎摹W詈螅?/span> strncpy 0 來(lái)填充目標(biāo)字符串剩余的部分,這是以損失性能為代價(jià)的。所有這些迷惑都是由長(zhǎng)度參數(shù)引起的,空結(jié)束的要求也非常重要。當(dāng)我們?cè)u(píng)估 OpenBSD 源樹的潛在安全漏洞的時(shí)候,我們發(fā)現(xiàn)大量濫用 strncpy strncat 。當(dāng)然,并不是所有的都導(dǎo)致暴露的安全漏洞,上面的這些使說(shuō)明了一點(diǎn):使用 strncpy strncat 作為安全字符串操作容易被誤解。推薦使用的函數(shù)是 strlcpy strlcat ,通過(guò)為安全字符串設(shè)計(jì)的 API 來(lái)程序這些問(wèn)題(見圖 1 的函數(shù)原型)。兩個(gè)函數(shù)都保證 NUL 結(jié)尾,長(zhǎng)度參數(shù)是以字節(jié)記數(shù)的,并且提供了檢查截?cái)嗟姆椒ǎ瑑蓚€(gè)函數(shù)都不是在目標(biāo)字符串中填充 0

            ?

            介紹

            ?

            1996 年中,作者和其他 OpenBSD 項(xiàng)目的成員一起承擔(dān)了對(duì) OpenBSD 源樹的評(píng)估,為了找出安全問(wèn)題;以緩沖區(qū)溢出作為開始。緩沖區(qū)溢出最近在一些論壇(例如 BugTraq )大量關(guān)注,并且正被廣泛地開拓。我們發(fā)現(xiàn)大量的緩沖區(qū)溢出是由于較大的使用 sprintf strcpy strcat 進(jìn)行的字符串復(fù)制;在循環(huán)中操作字符串而沒(méi)有明確地檢查循環(huán)變量的長(zhǎng)度也是一個(gè)問(wèn)題。另外,我們也發(fā)現(xiàn)許多程序員使用 strncpy strncat 來(lái)進(jìn)程安全字符串操作但失敗的場(chǎng)景。

            因此,在評(píng)估代碼的時(shí)候,我們發(fā)現(xiàn)不僅僅檢查 strcpy strcat 的不安全使用,同樣也要檢查 strncpy strncat 的不正確使用。檢查正確使用并不總是明顯地,特別在靜態(tài)變量和緩沖區(qū)或 calloc 分配的緩沖區(qū),這些都容易被忽視。我們得到結(jié)論,一個(gè)安全的 strncpy strncat 是必要的,首先可以減輕程序員的工作;另外也可以是代碼評(píng)估更容易。

            ?

            size_t strlcpy(char *dst, const char *src, size_t size);
            size_t strlcat(char *dst, const char *src, size_t size);

            Figure 1: ANSI C prototypes for strlcpy() and strlcat()

            通常誤解

            最通常的誤解是 strncpy 空結(jié)尾的目標(biāo)字符串。然而,只有源符串的長(zhǎng)度小于 size 參數(shù)才是正確的。當(dāng)用戶輸入的任意長(zhǎng)度字符串時(shí)候,可能有問(wèn)題。這種情況下最安全方法是傳遞一個(gè)小于目標(biāo)字符串的 size strncpy ,并且手動(dòng)添加一個(gè)結(jié)束符號(hào)。這種方法下你可以總是保證目標(biāo)字符穿是 NUL 結(jié)束的。嚴(yán)格地說(shuō),如果是一個(gè)靜態(tài)的字符串或一個(gè) calloc 分配的字符串不必要手動(dòng)添加一個(gè)結(jié)束符號(hào);主要由于這些字符串在分配的時(shí)候是填充 0 的。然而這些特性時(shí)候比較迷惑的。

            另外一個(gè)暗示的假定就是從 strcpy strcat 代碼轉(zhuǎn)換到 strncpy strncat 導(dǎo)致的性能下降是可以接受的。對(duì)于 strncat 來(lái)說(shuō)是正確的,但同樣對(duì)于 strncpy 來(lái)說(shuō)并不正確,由于 strncpy 將剩余的目標(biāo)字節(jié)填充 0 ,這在字符串比較大的時(shí)候可能導(dǎo)致可觀的性能損失。確切的損失由 CPU 架構(gòu)和實(shí)現(xiàn)的而決定。

            最常見的錯(cuò)誤是使用 strncat 和一個(gè)不正確的 size 參數(shù)。然而 strncat 保證目標(biāo)字符串是 NULL 結(jié)尾的,你不需要在 size 參數(shù)中為 NUL 計(jì)算機(jī)空間。最重要的,這不是目標(biāo)字符串自身的大小,而是可用空間的數(shù)量。因此這個(gè)值總是要計(jì)算,并且作為一個(gè)可靠的常量,它常常也不能正確計(jì)算。

            為什么 strlcpy strlcat 能夠安全

            ?

            這兩個(gè)函數(shù)提供了一個(gè)一致的、沒(méi)有二義性的 API 來(lái)幫助程序員寫比較防彈代碼。首先也是最重要的,兩個(gè)函數(shù)都能夠保證所有的目標(biāo)字符串是 NUL 結(jié)尾的,給定的 size 0 ;其次,兩個(gè)函數(shù)都將目標(biāo)字符串的整個(gè) size 作為一個(gè) size 參數(shù)。在大多數(shù)情況下,這個(gè)值比較容易在編譯期間使用 sizeof 操作符號(hào)來(lái)計(jì)算;最后,不管是 strlcpy 還是 strlcat 都不 0 填充他們的目標(biāo)字符串(而是強(qiáng)迫 NUL 到字符串的結(jié)尾)。

            Strlcpy strlcat 函數(shù)返回最終創(chuàng)建的字符串長(zhǎng)度。對(duì)于 strlcpy 來(lái)說(shuō)是源的長(zhǎng)度,對(duì)于 strlcat 來(lái)說(shuō)意味著目標(biāo)的長(zhǎng)度加源的長(zhǎng)度。為了檢查截?cái)啵绦騿T需要驗(yàn)證返回值是否小于 size 參數(shù)。因此,如果發(fā)生截?cái)啵梢园l(fā)現(xiàn)已經(jīng)存儲(chǔ)了多少個(gè)字節(jié),并且程序員可以重新分配空間來(lái)重新復(fù)制字符串。返回值和 snprintf BSD 上的實(shí)現(xiàn)有相同的含義。如果沒(méi)有截?cái)喟l(fā)生,程序員現(xiàn)在有返回值長(zhǎng)度的字符串;這是有用的,因?yàn)橥ǔG闆r用 strncpy strncat 來(lái)構(gòu)造字符串并且使用 strlen 來(lái)取得字符串的長(zhǎng)度。使用 strlcpy strlcat strlen 就不需要了。

            例子 1a 是潛在緩沖區(qū)溢出的例子( HOME 環(huán)境變量由用戶來(lái)控制可以是任意長(zhǎng)度)。

            strcpy(path, homedir);
            strcat(path, "/");
            strcat(path, ".foorc");
            len = strlen(path);

            Example 1a: Code fragment using strcpy() and strcat()

            例子 1b 轉(zhuǎn)換到 strncpy strncat 的同樣代碼片段(注意,我必須自己添加字符串結(jié)束符號(hào))。

            strncpy(path, homedir,
            sizeof(path) - 1);
            path[sizeof(path) - 1] = '\?0';
            strncat(path, "/",
            sizeof(path) - strlen(path) - 1);
            strncat(path, ".foorc",
            sizeof(path) - strlen(path) - 1);
            len = strlen(path);

            Example 1b: Converted to strncpy() and strncat()

            例子 1c 是到 strlcpy/strlcat 的變化,其有例子 1a 一樣簡(jiǎn)單的好處,但卻沒(méi)有利用 API 的返回值:

            strlcpy(path, homedir, sizeof(path));
            strlcat(path, "/", sizeof(path));
            strlcat(path, ".foorc", sizeof(path));
            len = strlen(path);

            Example 1c: Trivial conversion to strlcpy()/strlcat()

            由于例子 1c 如此容易閱讀和理解,添加其他的檢查也是非常簡(jiǎn)單,在例子 1d 中,我們檢查返回值來(lái)確保對(duì)于源字符串來(lái)說(shuō)有足夠的空間。如果沒(méi)有,我們返回一個(gè)錯(cuò)誤。這里稍微復(fù)雜一點(diǎn),但它仍然很好,同時(shí)也避免了調(diào)用 strlen

            len = strlcpy(path, homedir,sizeof(path);
            if (len >= sizeof(path))
            return (ENAMETOOLONG);
            len = strlcat(path, "/",sizeof(path);
            if (len >= sizeof(path))
            return (ENAMETOOLONG);
            len = strlcat(path, ".foorc",sizeof(path));
            if (len >= sizeof(path))
            return (ENAMETOOLONG);

            Example 1d: Now with a check for truncation

            ?

            設(shè)計(jì)決策

            許多思想加入判斷 strlcpy strlcat 應(yīng)該是什么語(yǔ)義。最初的想法是使 strlcpy strlcat strncpy strncat 相同,并且始終是 NUL 結(jié)束的目標(biāo)字符串。然而,當(dāng)我們回過(guò)來(lái)看常用(和誤用) strncat 說(shuō)服我們 strlcat size 參數(shù)應(yīng)該是字符串的所有大小而不僅僅是未分配的字符的數(shù)量。返回值開始作為復(fù)制字符串的數(shù)量,由于有復(fù)制和串聯(lián)的副作用。我們很快決定返回值應(yīng)該與 sprintf 一樣,這樣程序可以比較彈性的處理截?cái)嗪突謴?fù)。

            性能

            當(dāng)目標(biāo)字符串的長(zhǎng)度比源字符串明顯大很多的時(shí)候,程序員正在避免使用 strncpy ,主要由于其降低性能。例如, Apache 組用內(nèi)部函數(shù)來(lái)代替 strncpy 并且注意到性能提升。同樣, ncurses 包最近刪除了 strncpy ,結(jié)果比 tic 實(shí)現(xiàn)提高了四倍。我們的希望是,將來(lái)更多的程序員使用 strlcpy 而不是自定義的接口。

            為了對(duì)性能的降低有一個(gè)感覺(jué),我們比較 strncpy strlcpy ,并且復(fù)制字符串 ’’ ;也就是復(fù)制 1000 次到 1024 字節(jié)的緩沖區(qū)中。這對(duì) strncpy 有點(diǎn)不公平,由于使用了大的緩沖區(qū)和小的字符串,并且大緩沖區(qū)的時(shí)候, strncpy 不得不填充多余的緩沖為 NUL 字符。實(shí)際上,通常使用的緩沖區(qū)都比用戶輸入的大,例如,路徑名稱緩沖區(qū)是 MAXPATHLEN 長(zhǎng)( 1024 ),但多數(shù)文件都比較短。表 1 中的平均運(yùn)行時(shí)間在 HP9000/425t 25Mhz68040 CPU 運(yùn)行 OPENBSD2.5 DEC AXPPCI166 166Mhz Alpha CPU 運(yùn)行 OpenBSD 。所有的 case 都是相同 C 版本函數(shù),時(shí)間由時(shí)間工具產(chǎn)生:

            ?cpu architecture?

            ?function?

            ?time (sec)?

            m68k

            strcpy

            0.137

            m68k

            strncpy

            0.464

            m68k

            strlcpy

            0.14

            alpha

            strcpy

            0.018

            alpha

            strncpy

            0.10

            alpha

            strlcpy

            0.02

            1 :性能時(shí)間表

            如我們?cè)诒?/span> 1 中看到的一樣, strncpy 的時(shí)間是最壞的。可能的原因不僅是 NUL 填充,也可能因?yàn)?/span> CPU 數(shù)據(jù)緩沖區(qū)被長(zhǎng)流 0flush 的原因。

            ?

            什么時(shí)候不要 strlcpy strlcat

            然而, strlcpy strlcat 處理固定大小的緩沖區(qū)很好,但他們不能在所有情況下代理 strncpy strncat 。有時(shí)候操作緩沖區(qū)并不是真正的 C 字符串(例如,結(jié)構(gòu)體 utmp 中的字符串)時(shí)候就是必要的。然而,我們爭(zhēng)論的這樣假冒字符串不應(yīng)該用在新的編碼中,由于他們可能被誤用,并且據(jù)我們的經(jīng)驗(yàn),這也是 BUG 的根源。另外, strlcpy strlcat 函數(shù)并不是 C 里面修正字符串處理的嘗試,他們?cè)O(shè)計(jì)為來(lái)適應(yīng)正常的 C 字符串框架。如果你需要字符串函數(shù)支持動(dòng)態(tài)分配的、任意大小的緩沖區(qū),你可能需要檢查 asstring 包,在 MIB 軟件中。

            誰(shuí)使用 strlcpy strlcat

            Strlcpy strlcat 函數(shù)首先出現(xiàn)在 OpenBSD2.4 。這些函數(shù)最近被將來(lái)的 Solaris 版本中批準(zhǔn)。第三方包也開始收集這些 API 。例如, rsync 包現(xiàn)在使用 strlcpy 并且提供它自己的版本如果 OS 不支持的話。其他的操作系統(tǒng)和應(yīng)用程序?qū)?lái)使用 strlcpy strlcat 是我們的希望,并且它將某個(gè)時(shí)候接受標(biāo)準(zhǔn)。

            下一步是什么?

            Strlcpy strlcat 的源碼可以免費(fèi)獲得,并且 BSD 風(fēng)格的 license OpenBSD 操作系統(tǒng)的一部分。你可以通過(guò)匿名 ftp ftp.openbsd.org 下載代碼和相關(guān)的手冊(cè);目錄為 /pub/OpenBSD/src/lib/libc/string strlcpy strlcat 的源碼在 strlcpy.c strlcat.c 中。也可以找到相應(yīng)的文檔。

            作者: Todd C. Miller

            http://www.courtesan.com/todd/papers/strlcpy.html

            posted on 2006-10-05 18:43 笨笨 閱讀(4191) 評(píng)論(0)  編輯 收藏 引用 所屬分類: Security

            亚洲精品tv久久久久久久久久| 亚洲精品无码久久久久AV麻豆| 久久精品无码专区免费东京热 | www.久久99| 久久青青色综合| 久久精品无码一区二区三区免费| 久久久91精品国产一区二区三区 | 久久国产午夜精品一区二区三区| 久久婷婷五月综合色奶水99啪| 久久无码中文字幕东京热| 亚洲?V乱码久久精品蜜桃| 一本大道加勒比久久综合| 久久久久夜夜夜精品国产| 999久久久免费国产精品播放| 99久久国产主播综合精品| 免费观看成人久久网免费观看| 香蕉久久一区二区不卡无毒影院| 久久久精品一区二区三区| 久久免费视频网站| 久久婷婷人人澡人人| 久久人人爽人人爽人人av东京热| 亚洲欧美伊人久久综合一区二区| 无码人妻少妇久久中文字幕| 久久综合九色综合久99| 亚洲嫩草影院久久精品| 久久久久久亚洲精品无码| 99蜜桃臀久久久欧美精品网站| 久久国产精品99久久久久久老狼| 国产精品狼人久久久久影院 | 一本色道久久88—综合亚洲精品| AV无码久久久久不卡蜜桃| 国产精品久久久久久搜索| 久久久久久无码国产精品中文字幕| 人妻少妇久久中文字幕| 成人午夜精品久久久久久久小说| 国内精品综合久久久40p| 色综合久久久久无码专区| 久久久久久噜噜精品免费直播 | 久久久久久久99精品免费观看| 国产三级精品久久| 久久综合九色综合网站|