证明 C Runtime 和 Windows API 对安全性的影响

Visual C++ 专栏收录该内容
12 篇文章 0 订阅

 应用程序安全性的一大进步:证明 C Runtime 和 Windows API 对安全性的影响

摘要:本文将讨论使用 C 和 C++ 进行函数调用时的常见错误及其安全隐患,并概括某些函数的正确使用方法。作为一种持续不断的努力,在今后的几个月中,我们将继续展开讨论,为更多的 API 提供安全性信息。

简介
在对 C 和 C++ 代码进行代码检查以寻找安全薄弱环节时,我发现了在调用某些函数时的一些常见问题。尽管某种函数调用可能与安全性无关,但如果使用不当,仍会导致不易发觉的安全隐患。

本文将讨论这些错误及其安全隐患,并将概述一些函数的正确使用方法。

对于在 MSDN 和 Platform SDK 中记载的一些 API 的安全性评价,我们已经展开了讨论(这一讨论仍在继续)。在第一轮的讨论中,我们概述了顶级函数调用,这些调用导致了 Microsoft 和非 Microsoft 产品的安全薄弱环节。

我们首先讨论以下函数,这些函数在安全性方面尤为值得注意:

CopyMemory
CreateProcess、CreateProcessAsUser、CreateProcessWithLogonW
SetSecurityDescriptorDacl
模拟函数
memcpy
sprintf、swprintf
strcat、wcscat、_mbscat
strcpy、wcscpy、_mbscpy
strncat、wcsncat、_mbsncat
WinExec

CopyMemory
安全性评价
第一个参数 Destination 必须足以容纳 count 个字节的 Source 组合大小,否则就可能发生缓冲区溢出。这样,当发生违规访问时,应用程序就可能会遭到拒绝服务攻击,或者更坏,可能会使攻击者将可执行代码注入到您的进程中。如果 Destination 是基于堆栈的缓冲区,则尤为如此。要注意的是,最后一个参数 Length 是要复制到 Destination 的字节数,而不是 Destination 的大小。

以下代码示例演示了安全使用 CopyMemory() 的方法:

void test(char *pbData, unsigned int cbData) {
    char buf[BUFFER_SIZE];
    CopyMemory(buf, pbData, min(cbData,BUFFER_SIZE));
}

CreateProcess、CreateProcessAsUser、CreateProcessWithLogonW
安全性评价
第一个参数 lpApplicationName 可以为 NULL。在这种情况下,可执行程序的名称必须是 lpCommandLine 中第一个用空格分隔的字符串。但是,如果可执行程序的名称或路径名中有空格,则存在一定的风险,因为如果空格处理不当,就可能会运行恶意的可执行程序。以下示例是危险的,因为该进程将试图运行“Program.exe”(如果该程序存在),而不是“foo.exe”。

CreateProcess(NULL, "C:/Program Files/foo", ...)

如果恶意用户要在系统中创建名为“Program.exe”的特洛伊程序,那么任何使用“Program Files”目录不正确地调用 CreateProcess 的程序都将启动特洛伊程序,而不是要调用的应用程序。

注意不要为 lpApplicationName 传递 NULL,以避免函数根据其运行时参数来分析并确定可执行文件路径名。否则,如果 lpApplicationName 为 NULL,则用引号将 lpCommandLine 中的可执行路径引起,如下例所示。

CreateProcess(NULL, "/"C:/Program Files/foo.exe/" -L -S", ...)

SetSecurityDescriptorDacl
安全性评价
最好不要创建具有 NULL DACL 的安全描述符(即:pDacl 为 NULL),因为这样的 DACL 无法为对象提供安全性。实际上,攻击者可在对象上设置一个 Everyone (Deny All Access) ACE,从而拒绝每个人(包括管理员)访问该对象。NULL DACL 没有为对象提供任何免受攻击的保护。

模拟函数
安全性评价
如果对模拟函数的调用因任何原因而失败,则不会对客户端进行模拟,客户端请求将在进行调用的进程所在的安全环境中进行。如果进程作为高度特权化的帐户(如 LocalSystem)来运行,或作为管理组的成员来运行,则用户可能可以执行在其他情况下不允许进行的操作。所以,您务必要始终检查调用的返回值,如果该值未报出错误,则不要继续执行客户端请求。以下是一些示例:

RpcImpersonateClient
ImpersonateNamedPipeClient
SetThreatToken
ImpersonateSelf
CoImpersonateClient
ImpersonateDdeClientWindow
ImpersonateSecurityContext
ImpersonateLoggedOnUser

memcpy
安全性评价
第一个参数 dest 必须足以容纳 count 个字节的 src 组合大小,否则就可能发生缓冲区溢出。这样,当发生违规访问时,应用程序就可能会遭到拒绝服务攻击,或者更坏,可能会使攻击者将可执行代码注入到您的进程中。如果 dest 是基于堆栈的缓冲区,则尤为如此。要注意的是,最后一个参数 count 是要复制到 dest 的字节数,而不是 dest 的大小。

以下代码示例演示了安全使用 memcpy() 的方法:

void test(char *pbData, unsigned int cbData) {
    char buf[BUFFER_SIZE];
    memcpy(buf, pbData, min(cbData,BUFFER_SIZE));
}

sprintf、swprintf
安全性评价
第一个参数 buffer 必须足以容纳 format 的格式化版本和末尾的 NULL ('/0') 字符,否则就可能发生缓冲区溢出。这样,当发生违规访问时,应用程序就可能会遭到拒绝服务攻击,或者更坏,可能会使攻击者将可执行代码注入到您的进程中。如果 buffer 是基于堆栈的缓冲区,则尤为如此。

另外,应注意用户或应用程序将 format 提供为变量的危险。下例是危险的,因为攻击者可能会将 szTemplate 设置为“%90s%10s”,这样会创建一个 100 字节的字符串:

void test(char *szTemplate,char *szData1, char *szData2) {
    char buf[BUFFER_SIZE];
    sprintf(buf,szTemplate,szData1,szData2);
}

应考虑使用 _snprintf(英文)或 _snwprintf 来代替。

strcat、wcscat、_mbscat
安全性评价
第一个参数 strDestination 必须足以容纳当前的 strDestination 和 strSource 组合以及一个末尾 '/0',否则就可能发生缓冲区溢出。这样,当发生违规访问时,应用程序就可能会遭到拒绝服务攻击,或者更坏,可能会使攻击者将可执行代码注入到您的进程中。如果 strDestination 是基于堆栈的缓冲区,则尤为如此。应考虑使用 strncat(英文)、wcsncat 或 _mbsncat。

strcpy、wcscpy、_mbscpy
安全性评价
第一个参数 strDestination 必须足以容纳 strSource 和末尾的 '/0',否则就可能发生缓冲区溢出。这样,当发生违规访问时,应用程序就可能会遭到拒绝服务攻击,或者更坏,可能会使攻击者将可执行代码注入到您的进程中。如果 strDestination 是基于堆栈的缓冲区,则尤为如此。应考虑使用 strncpy(英文)、wcsncpy 或 _mbsncpy。

strncat、wcsncat、_mbsncat
安全性评价
第一个参数 strDestination 必须足以容纳当前 strDestination 和 strSource 组合以及一个末尾 NULL ('/0'),否则就可能发生缓冲区溢出。这样,当发生违规访问时,应用程序就可能会遭到拒绝服务攻击,或者更坏,可能会使攻击者将可执行代码注入到您的进程中。如果 strDestination 是基于堆栈的缓冲区,则尤为如此。要注意的是,最后一个参数 count 是要复制到 strDestination 的字节数,而不是 strDestination 的大小。

还要注意,如果缓冲区 strDestination 中有剩余的空间,则 strncat 仅添加末尾 NULL。

以下代码示例演示了安全使用 strncat 的方法:

void test(char *szWords1, char *szWords2) {
     char buf[BUFFER_SIZE];
     
     strncpy(buf,szWords1,sizeof buf - 1);
     buf[BUFFER_SIZE - 1] = '/0';               
     unsigned int cRemaining = (sizeof buf - strlen(buf)) - 1;
     strncat(buf,szWords2,cRemaining);
}

WinExec
安全性评价
可执行名称被视为 lpCmdLine 中的第一个用空格分隔的字符串。 但是,如果可执行程序的名称或路径名中有空格,则存在一定的风险,因为如果空格处理不当,就可能会运行恶意的可执行程序。以下示例是危险的,因为该进程将试图运行“Program.exe”(如果该程序存在),而不是“foo.exe”。

WinExec("C:/Program Files/foo", ...)
如果恶意用户要在系统中创建名为“Program.exe”的特洛伊程序,那么任何使用“Program Files”目录不正确地调用 WinExec 的程序都将启动特洛伊程序,而不是要调用的应用程序。

就安全性而言,我们强烈建议您使用 CreateProcess 而不是 WinExec。但是,如果您由于遗留问题而必须使用 WinExec,则务必要将应用程序名用引号引起来,如下例所示:

WinExec("/"C:/Program Files/foo.exe/" -L -S", ...)

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
<p> <span style="font-size:14px;color:#337FE5;">【为什么学爬虫?】</span> </p> <p> <span style="font-size:14px;">       1、爬虫入手容易,但是深入较难,如何写出高效率爬虫,如何写出灵活性高可扩展爬虫都是一项技术活。另外在爬虫过程中,经常容易遇到被反爬虫,比如字体反爬、IP识别、验证码等,如何层层攻克难点拿到想要数据,这门课程,你都能学到!</span> </p> <p> <span style="font-size:14px;">       2、如果是作为一个其他行业开发者,比如app开发,web开发,学习爬虫能让你加强技术认知,能够开发出更加安全软件网站</span> </p> <p> <br /> </p> <span style="font-size:14px;color:#337FE5;">【课程设计】</span> <p class="ql-long-10663260"> <span> </span> </p> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> 一个完整爬虫程序,无论大小,总体来说可以分成三个步骤,分别是: </p> <ol> <li class="" style="font-size:11pt;color:#494949;"> 网络请求:模拟浏览器行为从网上抓取数据。 </li> <li class="" style="font-size:11pt;color:#494949;"> 数据解析:将请求下来数据进行过滤,提取我们想要数据。 </li> <li class="" style="font-size:11pt;color:#494949;"> 数据存储:将提取到数据存储到硬盘或者内存中。比如用mysql数据库或者redis等。 </li> </ol> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> 那么本课程也是按照这几个步骤循序渐进进行讲解,带领学生完整掌握每个步骤技术。另外,因为爬虫多样性,在爬取过程中可能会发生被反爬、效率低下等。因此我们又增加了两个章节用来提高爬虫程序灵活性,分别是: </p> <ol> <li class="" style="font-size:11pt;color:#494949;"> 爬虫进阶:包括IP代理,多线程爬虫,图形验证码识别、JS加密解密、动态网页爬虫、字体反爬识别等。 </li> <li class="" style="font-size:11pt;color:#494949;"> Scrapy分布式爬虫:Scrapy框架、Scrapy-redis组件、分布式爬虫等。 </li> </ol> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> 通过爬虫进阶知识点我们能应付大量反爬网站,而Scrapy框架作为一个专业爬虫框架,使用他可以快速提高我们编写爬虫程序效率速度。另外如果一台机器不能满足你需求,我们可以用分布式爬虫让多台机器帮助你快速爬取数据。 </p> <p style="font-size:11pt;color:#494949;">   </p> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> 从基础爬虫到商业化应用爬虫,本套课程满足您所有需求! </p> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> <br /> </p> <p> <br /> </p> <p> <span style="font-size:14px;background-color:#FFFFFF;color:#337FE5;">【课程服务】</span> </p> <p> <span style="font-size:14px;">专属付费社群+定期答疑</span> </p> <p> <br /> </p> <p class="ql-long-24357476"> <span style="font-size:16px;"><br /> </span> </p> <p> <br /> </p> <p class="ql-long-24357476"> <span style="font-size:16px;"></span> </p>
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值