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

C/C++禁用危險API

Posted on 2008-11-13 11:51 Herbert 閱讀(3489) 評論(1)  編輯 收藏 引用 所屬分類: C++
 轉自:http://bbs.lvy8.cn/ShowPost_PR5339.html


程序員》9月文章

 

申明。文章僅代表個人觀點,與所在公司無任何聯系。

  1. 概述

   在前面的安全編碼實踐的文章里,我們討論了GS編譯選項,數據執行保護DEP功能,以及靜態代碼分析工具Prefast。這里,我們討論在C/C++代碼中禁用危險的API,其主要目的是為了減少代碼中引入安全漏洞的可能性。

  1. 那些是危險的API

    2.1歷史

   在微軟產品的安全漏洞中,有很大一部分是由于不正確的使用C動態庫(C Runtime Library 的函數,特別是有關字符串處理的函數導致的。表一給出了微軟若干由于不當使用C動態庫函數而導致的安全漏洞【1,p242】。 

微軟安全公告 涉及產品 涉及的函數
MS02-039 Microsoft SQL Server 2000 sprint
MS05-010 Microsoft License Server lstrcpy
MS04-011 Microsoft Windows (DCPromo) wvsprintf
MS04-011 Microsoft Windows (MSGina) lstrcpy
MS04-031 Microsoft Windows (NetDDE) wcscat
MS03-045 Microsoft Windows (USER) wcscpy

1:不當使用C動態庫函數而導致的安全漏洞

   不當使用C動態庫函數容易引入安全漏洞,這一點并不奇怪。C動態庫函數的設計大約是30年前的事情了。當時,安全方面的考慮并不是設計上需要太多注意的地方。

    2.2 危險API的列表


 

   有關完整的危險API的禁用列表,大家可以參見http://msdn.microsoft.com/en-us/library/bb288454.aspx. 

   在這里我們列出其中的一部分,以便大家對那些API被禁用有所體會。 

<DIV align=left>
禁用的API 替代的StrSafe函數 替代的Safe CRT函數
有關字符串拷貝的API
strcpy, wcscpy, _tcscpy, _mbscpy, StrCpy, StrCpyA, StrCpyW, lstrcpy, lstrcpyA, lstrcpyW, strcpyA, strcpyW, _tccpy, _mbccpy StringCchCopy, StringCbCopy,

StringCchCopyEx, StringCbCopyEx

strcpy_s
有關字符串合并的API
strcat, wcscat, _tcscat, _mbscat, StrCat, StrCatA, StrCatW, lstrcat, lstrcatA, lstrcatW, StrCatBuffW, StrCatBuff, StrCatBuffA, StrCatChainW, strcatA, strcatW, _tccat, _mbccat StringCchCat, StringCbCat,

StringCchCatEx, StringCbCatEx

strcat_s
有關sprintfAPI
wnsprintf, wnsprintfA, wnsprintfW, sprintfW, sprintfA, wsprintf, wsprintfW, wsprintfA, sprintf, swprintf, _stprintf StringCchPrintf, StringCbPrintf,

StringCchPrintfEx, StringCbPrintfEx

_snprintf_s

_snwprintf_s

</DIV>

2:禁用API的列表(部分)

   其它被禁用的API還有scanf, strtok, gets, itoa等等。 ”n”系列的字符串處理函數,例如strncpy等,也在被禁用之列。

  1. 如何替代被禁用的危險API

   從上面的介紹可以看出絕大多數C動態庫中的字符串處理函數都被禁用。那么,如何在代碼中替代這些危險的API呢?在表2,我們看到有兩種替代方案:

    • StrSafe
    • Safe CRT


 

   后面我們會討論這兩種方案的不同之處。這里我們先說它們的共同點:提供更安全的字符串處理功能。特別在以下幾個方面:

    • 目標緩存區的大小被顯式指明。
    • 動態校驗。
    • 返回代碼。


 

   StringCchCopy舉例。它的定義如下:

HRESULT StringCchCopy(         

    LPTSTR pszDest,

    size_t cchDest,

    LPCTSTR pszSrc

);


 

   cchDest指明目標緩存區pszDest最多能容納字符的數目,其值必須在1STRSAFE_MAX_CCH之間。StringCchCopy總是確保pszDest被拷貝的字符串是以NULL結尾。并且提供以下的返回代碼: S_OKSTRSAFE_E_INVALID_PARAMETER,和STRSAFE_E_INSUFFICIENT_BUFFER。這樣,采用StringCchCopy來替代被禁用的strcpy的話,就可以有效降低由于誤用字符串拷貝而導致緩存溢出的可能。

    3.1使用StrSafe


 

   使用StrSafe非常簡單。在C/C++代碼中加入以下的頭文件即可。

#include "strsafe.h"


 

   StrSafe.h包含在Windows Platform SDK中。用戶可以通過在微軟的網站直接下載。 

   下面給出一個使用StrSafe的代碼示例【2】。

   不安全的代碼:

void UnsafeFunc(LPTSTR szPath,DWORD cchPath) {

   TCHAR szCWD[MAX_PATH];

   GetCurrentDirectory(ARRAYSIZE(szCWD), szCWD);

   strncpy(szPath, szCWD, cchPath);

   strncat(szPath, TEXT("\\"), cchPath);

   strncat(szPath, TEXT("desktop.ini"),cchPath);

}


 

   在以上代碼里存在著幾個問題:首先,沒有錯誤代碼的校驗。更嚴重的是,在strncat中,cchPath是目標緩存區可以存放字符的最大數目,而正確傳遞的參數應該是目標緩存區剩余的字符數目。 

   使用StrSafe后的代碼是

bool SaferFunc(LPTSTR szPath,DWORD cchPath) {

   TCHAR szCWD[MAX_PATH];

   if (GetCurrentDirectory(ARRAYSIZE(szCWD), szCWD)            &&

      SUCCEEDED(StringCchCopy(szPath, cchPath, szCWD))    &&

      SUCCEEDED(StringCchCat(szPath, cchPath, TEXT("\\"))) &&

      SUCCEEDED(StringCchCat(szPath, cchPath, TEXT("desktop.ini")))) {

         return true;

   }

   return false;

}

    3.2使用Safe CRT


 

   SafeCRTVisual Studio 2005起開始支持。當代碼中使用了禁用的危險的CRT函數,Visual Studio 2005編譯時會報告相應警告信息,以提醒開發人員考慮將其替代為Safe CRT中更為安全的函數。 

   下面給出一個使用Safe CRT的代碼示例【3】。 

   不安全的代碼:

void UnsafeFunc (const wchar_t * src)

{

    // Original

    wchar_t dest[20];

    wcscpy(dest, src);           // 編譯警告

    wcscat(dest, L"...");        // 編譯警告

}


 

   以上這段代碼里存在著明顯緩存溢出的問題。 

   使用Safe CRT后的代碼是

errno_t SaferFunc(const wchar_t * src)

{

    wchar_t dest[20];

   

    errno_t err = wcscpy_s(dest, _countof(dest), src);

    if (!err)

        return err;

    return wcscat_s(dest, _countof(dest), L"...");

}

    3.3 StrSafe Safe CRT的對比

   我們看到,StrSafeSafe CRT存在功能重疊的地方。那么什么時候使用StrSafe,什么時候使用SafeCRT呢?

   下面的表格【1p246】里列出了兩者之間的差異。采用何種方式應該根據具體情況而定。有時候也許只能采取其中一種方式:例如如果你的開發系統是Visual Studio 2003的話,就只能使用StrSafe?;蛘吣愕拇a中有許多itoa的話,就考慮使用Safe CRT,因為StrSafe中沒有提供簡單的替代方式。有時候也許兩者都可以。這種情況下,我個人是更喜歡采用StrSafe這種方式,因為它不依賴具體的動態庫支持。如果是編寫Win32上的程序的話,StrSafeHRESULT的返回代碼,也和Win32 API的代碼類似,這樣代碼的整體風格可能會更加一致。

<DIV align=left>
  StrSafe Safe CRT
發布方式 Web Microsoft Visual Studio 2005
頭文件 一個 (StrSafe.h) 多個 (不同的 C runtime 頭文件)
是否提供鏈接庫的版本
是否提供內嵌(Inline)版本
是否是業界標準 正在評估過程
Kernel Mode支持
返回類型 HRESULT (user mode)

NTSTATUS (kernel mode)

隨函數變化,errno_t
是否需要修改代碼
主要針對 緩存溢出 緩存溢出,和其它安全方面的考慮
</DIV>

3:StrSafe和Safe CRT對比

  1. 爭論

    在開發過程中,代碼中全面禁用危險的API的編碼實踐,存在著一定的爭議性。其中最具有代表性的觀點可以參見Danny KalevVisual C++ 8.0 Hijacks the C++ Standard一文【4】。爭論主要集中在以下幾點。

    4.1對于程序性能的影響

    StrSafe舉例,由于增加了更多的動態校驗,其速度較C動態庫的函數相比,是有所下降的。在【2】一文中,給出了對StrSafe速度方面的測試數據如下: 

    測試例子:1千萬次字符串合并調用。結果:

    C動態庫:7.3

    StrSafe8.3 

    我們看到,如果開發的系統不是完全以字符串處理為工作核心的話,使用StrSafe對系統性能的影響是可以控制的。

    4.2開發人員可以決定在合適的地方使用危險API


 

    首先,同意如果代碼中正確使用危險API的話,也是可以避免安全漏洞的引入。但是,在具體的開發實踐中,存在著以下問題:

    • 開發人員的素質和培訓
    • 有時候即使執行嚴格的代碼復查,仍然可能由于使用危險的API引入安全漏洞。


 

    第二點尤其關鍵。大家看到這里可能會有疑問,使用危險的API有這么容易出問題嗎?即便代碼復查(code review)也沒能看出來?【5中給出了一個微軟安全漏洞的具體實例。 

    微軟 05-047 Plug-n-Play RPC:即插即用中的漏洞,允許遠程執行代碼和特權提升。經過身份驗證的攻擊者可以通過創建特制的網絡消息并將該消息發送到受影響的系統來嘗試利用此漏洞。導致這個嚴重的安全漏洞的代碼如下:

#define MAX_CM_PATH                       360

GetInstanceList(

IN LPCWSTR pszDevice, IN OUT LPWSTR *pBuffer, IN OUT PULONG pulLength)

{

      WCHAR       RegStr[MAX_CM_PATH], szInstance[MAX_DEVICE_ID_LEN];

...

      // Validate that passed in pszDevice is an actual registry entry

      // If lookup for the key fails, reject call and cleanup.

      // ghEnumKey points to HKLM\System\CurrentControlSet\Enum

      if (RegOpenKeyEx(ghEnumKey, pszDevice, 0,

        KEY_ENUMERATE_SUB_KEYS, &hKey) != ERROR_SUCCESS) {

 Status = CR_REGISTRY_ERROR;

      goto Clean0;

}

...

      ulLen = MAX_DEVICE_ID_LEN;  // size in chars

...

      // Query szInstance from registry

      RegStatus = RegEnumKeyEx(hKey, ulIndex, szInstance, &ulLen, ...);

      if (RegStatus == ERROR_SUCCESS) {

      // Build lookup string given a valid registry root key and valid instance ID

      wsprintf(RegStr, TEXT("%s\\%s"), pszDevice, szInstance);}


 

    復查這段代碼時,我們看到,雖然使用了危險的APIwsprintf,但應該是不會發生緩存溢出的問題。這是因為根據MSDN,

 

 

    

1:注冊表字符數目的限制

    于是:

    • pszDevice 應該少于255 characters
    • pszDevice 是一個 有效的 key HKLM\System\CurrentControlSet\Enum
    • szInstance 是一個有效的subkeypszDevice
    • RegStr is 360 characters
    • 攻擊者并不能控制注冊表內容


 

    但實際上,wspringf還是導致了緩存溢出的安全漏洞。到底是怎么回事?我們來看一下攻擊代碼:

errno_t SaferFunc(const wchar_t * src)

int main()

{

      PWCHAR pszFilter = (PWCHAR)malloc(sizeof(WCHAR)*1000);

      PWCHAR Buffer = (PWCHAR)malloc(86);

      wsprintf(pszFilter,L"ISAPNP\\ReadDataPort\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\0");

      CM_Get_Device_ID_List((PCWSTR)pszFilter,Buffer,86,1);

      return 0;

}


 

    攻擊代碼之所以有效,是因為:

    • pszFilter(除去末位的0) 作為pszDevice 傳遞給GetInstanceList
    • RegOpenKeyEx 接收了這個長字符串,忽略那些“\”,返回 ERROR_SUCCESS。


 

    通過這個例子我們看出,在開發復雜的系統中,即便是有經驗的開發人員,加上嚴格的代碼復查過程,還是有可能由于使用危險的API而導致安全漏洞的引入。這也是微軟在Windows Vista的開發過程中全面禁用危險API的原因。

    4.3程序可移植性的影響

   這一點的考慮是非常值得重視的。不管是StrSafe,還是Safe CRT,都不是工業界標準。因此,如果開發的系統需要移植到其它平臺的話,采用Safe CRT是肯定不合適的。StrSafeInline方式,因為不依賴特定庫,對可移植性的影響相對較小。

  1. 總結

   C/C++程序中禁用危險的API,可以有效降低在代碼中引入安全漏洞的可能。在考慮了性能和可移植性的因素下,強烈建議在開發過程中,使用StrSafe或Safe CRT中對應的安全函數來替代被禁用的危險的API調用。

  1. 參考文獻

Feedback

# re: C/C++禁用危險API  回復  更多評論   

2011-03-21 20:22 by yautou
寫的很好,不介意小弟轉載博客吧,值得收藏,!
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲女同同性videoxma| 亚洲人成绝费网站色www| 国产精品乱码人人做人人爱| 欧美二区在线| 欧美高清视频一区| 欧美精品一区二区三区蜜臀| 欧美福利视频在线观看| 欧美全黄视频| 国产精品尤物福利片在线观看| 国产欧美精品日韩区二区麻豆天美| 国产美女精品| 亚洲国产精品va在线看黑人| 日韩视频免费| 亚洲欧美日韩综合aⅴ视频| 久久精品国产77777蜜臀| 欧美jizz19性欧美| 亚洲人成在线观看一区二区| 亚洲在线观看免费视频| 久久久久久久久久码影片| 欧美精品videossex性护士| 欧美三级黄美女| 狠狠干综合网| 亚洲一区日韩| 欧美黄色片免费观看| 亚洲丝袜av一区| 亚洲丶国产丶欧美一区二区三区 | 亚洲成人在线网| 在线亚洲免费| 欧美freesex8一10精品| 亚洲一区久久久| 欧美国产精品劲爆| 国产综合色精品一区二区三区| 99在线热播精品免费99热| 久久免费高清| 亚洲欧美精品一区| 欧美日韩黄色大片| 亚洲激情在线激情| 久久欧美中文字幕| 亚洲一区国产| 国产精品久久久久一区二区三区共 | 性视频1819p久久| 欧美激情第六页| 樱桃成人精品视频在线播放| 亚洲宅男天堂在线观看无病毒| 亚洲一区在线播放| 亚洲欧美日产图| 欧美精品在线极品| 亚洲福利一区| 久久免费黄色| 欧美亚洲日本一区| 国产精品一区二区你懂的| 一区二区三区免费观看| 亚洲国产天堂网精品网站| 久久久精品一区| 国产一区二区中文字幕免费看| 午夜精品免费在线| 亚洲视频综合| 国产精品亚洲一区| 亚洲欧美日韩人成在线播放| 一区二区三区蜜桃网| 欧美日韩国产色视频| 一本一本久久a久久精品综合妖精| 欧美激情精品久久久久久免费印度 | 久久黄金**| 亚洲欧美日韩中文播放| 国产精品中文字幕欧美| 久久国产精品久久久久久久久久| 亚洲免费在线视频| 国产伦精品一区二区三区在线观看| 亚洲欧美日韩一区| 欧美一区二区私人影院日本| 国产自产在线视频一区| 免费视频一区| 欧美精品国产一区| 亚洲欧美日韩一区二区| 久久成人免费网| 最近看过的日韩成人| 亚洲精品中文字幕在线| 国产精品日韩精品欧美精品| 久久久亚洲高清| 美日韩免费视频| 亚洲一二三级电影| 欧美一区二区视频网站| 亚洲人成亚洲人成在线观看| 一本色道久久加勒比精品| 国产日韩欧美在线| 欧美激情1区| 国产精品男gay被猛男狂揉视频| 欧美专区在线观看一区| 毛片一区二区| 午夜精品免费视频| 免费成人性网站| 先锋影音久久| 欧美黄色视屏| 久久久久在线观看| 欧美日韩在线精品| 蜜桃视频一区| 国产精品一区二区三区免费观看| 老司机精品久久| 欧美视频在线观看免费网址| 久久综合国产精品| 国产精品久久国产三级国电话系列| 久久久久国产一区二区三区四区| 欧美激情精品久久久久| 91久久精品久久国产性色也91| 久久一区二区三区国产精品| 99精品欧美一区| 久久久久久久性| 亚洲免费在线看| 欧美黄色小视频| 欧美高清在线播放| 国产欧美精品一区二区色综合| 亚洲肉体裸体xxxx137| 狠狠色狠狠色综合日日五| 一区二区久久| 一本色道久久综合亚洲二区三区| 久久影院午夜片一区| 欧美一区亚洲| 国产精品99免费看| 亚洲精品在线视频| 亚洲经典自拍| 久久亚洲一区二区| 久久人人97超碰人人澡爱香蕉| 欧美日韩一区二区三区免费| 亚洲国产欧美一区二区三区久久| 黄色成人在线网址| 欧美一区国产一区| 欧美专区在线| 国内成+人亚洲| 欧美在线视频不卡| 久久精品国产免费| 国产人成精品一区二区三| 亚洲自拍偷拍视频| 先锋影音一区二区三区| 国产精品日韩专区| 亚洲免费在线看| 久久精品一区四区| 韩日在线一区| 久久综合九色综合久99| 欧美高潮视频| 亚洲美女毛片| 欧美日韩另类在线| 一区二区三区欧美| 午夜精品久久久久| 国产日韩欧美在线看| 久久gogo国模裸体人体| 免费人成网站在线观看欧美高清| 亚洲大片精品永久免费| 欧美成人日韩| 一区二区日韩伦理片| 欧美亚洲午夜视频在线观看| 国产性天天综合网| 久久综合伊人77777| 亚洲精品日韩综合观看成人91| 亚洲天堂网站在线观看视频| 国产精品伦子伦免费视频| 欧美一级夜夜爽| 欧美国产一区二区三区激情无套| 亚洲麻豆视频| 国产美女精品一区二区三区| 久久久久一区二区| 亚洲人成网站在线播| 久久成人免费网| 亚洲国产精品热久久| 欧美日韩精品欧美日韩精品 | 欧美区日韩区| 亚洲专区国产精品| 欧美高清在线一区| 亚洲欧美日本日韩| 一区久久精品| 国产精品白丝av嫩草影院| 亚洲网友自拍| 欧美激情第二页| 午夜精品久久久久久久99热浪潮| 久久一区二区三区四区| 一区二区三区.www| 好看不卡的中文字幕| 欧美日韩第一区日日骚| 亚洲免费伊人电影在线观看av| 欧美成人亚洲成人| 香蕉久久一区二区不卡无毒影院| 亚洲福利一区| 国产一区二区三区在线免费观看| 欧美国产日韩一区二区| 欧美综合激情网| 99国产精品99久久久久久| 美女在线一区二区| 香蕉久久夜色精品国产| 一区二区三区欧美激情| 在线日韩中文字幕| 国产日韩精品久久| 国产精品99免费看 | 欧美1区2区| 欧美一区二区三区在线观看视频 | 午夜国产精品视频免费体验区| 亚洲国产成人不卡| 猫咪成人在线观看| 久久久久久久91| 欧美亚洲免费电影| 午夜精品一区二区在线观看|