PVS-Studio如何帮助检测漏洞?

PVS-Studio是一个静态代码分析器,用于搜索用C,C ++和C#编写的程序中的错误(和漏洞)。 它可以在Windows和Linux下运行,并且可以作为插件集成到Visual Studio IDE中。 此时,分析仪具有450多个诊断规则,每个诊断规则在文档中都有描述。

在发布本文时,我们已经检查了280多个开源项目,发现了11 000多个错误。 有趣的是,这些漏洞的数量确实是漏洞……

您可以在官方网站上下载PVS-Studio,然后自己尝试。

顺便说一下,我们向安全专家提供PVS-Studio许可证。 如果您是安全领域的专家,并且正在搜索漏洞,则可以与我们联系以获得许可证。 有关此优惠的更多详细信息,请参见文章“向安全专家分发PVS-Studio分析仪许可证”。

术语

如果您非常了解术语,并且了解CVE和CWE之间的差异以及它们的相似性,则可以跳过本节。 尽管如此,我还是建议其他人一起来看看,以便将来更容易理解该主题。

CWE(通用弱点枚举)-安全缺陷的组合列表。 针对开发社区和安全从业人员社区,常见弱点枚举(CWE)是软件的体系结构,设计,代码或实现中可能会导致可利用的安全漏洞的常见软件弱点的正式列表或字典。 创建CWE的目的是作为描述软件安全漏洞的通用语言。 作为针对这些弱点的软件安全工具的标准量尺; 并为弱点识别,缓解和预防工作提供通用的基准标准。

CVE(常见漏洞和披露)-程序错误,黑客可以直接使用。

MITRE公司于1999年开始研究软件漏洞的分类,当时,常见漏洞和软件责任(CVE)的清单应运而生。 2005年,在CVE系统进一步开发的框架内,一组作者开始对漏洞,攻击,崩溃和其他类型的安全问题进行预备分类,以定义常见的软件安全缺陷。 但是,尽管在CVE范围内创建的分类是自给自足的,但对于分析人员使用的代码安全性评估方法的定义和分类来说,它似乎过于粗糙。 因此,创建了CWE列表来解决此问题。

PVS-Studio:不同的观点

背景

从历史上看,我们将PVS-Studio定位为搜索错误的工具。 在有关项目分析的文章中,我们始终使用相应的术语:错误,错误和错字。 显然,不同的错误具有不同的严重性级别:可能有些代码片段包含冗余或误导性代码,但是有些错误导致整个系统每隔三天凌晨5点崩溃。 一切都清楚了,这个概念很长一段时间都没有进一步发展-错误只是错误。

但是,随着时间的流逝,事实证明,PVS-Studio检测到的一些错误可能更加严重。 例如,与在stdout输出错误消息相比,使用不正确的printf函数会导致更多的负面后果。 当很明显许多诊断规则不仅可以检测错误而且可以检测弱点(CWE)时,我们决定更详细地研究这个问题,并了解PVS-Studio的诊断规则如何与CWE相关。

PVS-Studio与CWE之间的关系

根据检测PVS-Studio和CWE的警告之间的相关性的结果,我们创建了下表:

以上不是该表的最终变体,但是它使您了解了一些PVS-Studio警告与CWE的关系。 现在很清楚,PVS-Studio不仅可以成功检测到(并且一直可以检测到)程序代码中的错误,而且还可以检测到潜在的漏洞,例如CWE。 关于此主题有几篇文章,它们在本文结尾列出。

CVE基地

潜在漏洞(CWE)尚未成为实际漏洞(CVE)。 在http://cve.mitre.org网站上收集了在开放源代码和专有项目中都发现的实际漏洞。 在这里,您可以找到特定漏洞的描述,其他链接(讨论,漏洞修复公告,提交的链接,修复漏洞等)。(可选)可以以必要的格式下载数据库。 在撰写本文时,漏洞基础的.txt文件约为100MB,超过270万行。 令人印象深刻,是吗?

在对本文进行一些研究时,我发现了很多有趣的资源,它们可能对感兴趣的人有所帮助-http://www.cvedetails.com/。 由于具有以下功能,因此很方便:

  • 通过CWE标识符搜索CVE;
  • 在特定产品中搜索CVE;
  • 查看漏洞外观/修复的统计信息;
  • 以与CVE相关的一种或另一种方式查看各种数据表(例如,对公司的评级,其产品中发现的漏洞数量最多);
  • 还有更多。

使用PVS-Studio可能会发现一些CVE

我写这篇文章是为了证明PVS-Studio分析仪可以保护应用程序免受漏洞(至少是其中一些漏洞)的侵害。

我们从未调查过PVS-Studio检测到的某个缺陷是否可以被利用为漏洞。 这非常复杂,我们从未设定过这样的任务。 因此,我将采取其他措施:如果PVS-Studio定期检查了代码,我将采取一些已经发现并描述的漏洞,并证明可以避免这些漏洞。

注意。 本文中描述的漏洞未在综合示例中找到,但在真实的源文件中发现了(来自旧项目修订版)。

照明门

我们要谈论的第一个漏洞是在illumos-gate项目的源代码中检测到的。 illumos-gate是一个开源项目(可从GitHub的存储库中获得),它构成了操作系统的核心,其根源于BSD中的Unix。

该漏洞的名称为CVE-2014–9491。

CVE-2014–9491的描述 :illumos中的devzvol_readdir函数不会检查strchr调用的返回值,这使远程攻击者可以通过未指定的向量导致拒绝服务( NULL指针取消引用和恐慌)。

问题代码在函数devzvol_readdir中

static int devzvol_readdir (....) 
{
....
char *ptr;
....
ptr = strchr(ptr + 1, '/') + 1;
rw_exit(&sdvp->sdev_contents);
sdev_iter_datasets(dvp, ZFS_IOC_DATASET_LIST_NEXT, ptr);
....
}

函数strchr返回一个指向第一个符号出现的指针,作为第二个参数传递。 但是,如果在源字符串中找不到符号,则该函数可以返回空指针。 但是这个事实被遗忘了,或者没有考虑在内。 结果,返回值仅被加1,结果被写入ptr变量,然后按“原样”处理指针。 如果获得的指针为空,则将其加1,我们将获得一个无效的指针,针对NULL进行验证并不意味着其有效性。 在某些情况下,此代码可能会导致内核崩溃。

PVS-Studio使用诊断规则V769检测到此漏洞,说strchr函数返回的指针可以为空,并且同时受到损坏(由于加1):

V769’strchr(ptr + 1,’/’)+ 1’表达式中的’strchr(ptr + 1,’/’)’指针可以为nullptr。 在这种情况下,结果值将毫无意义,因此不应使用。

网络音频系统

网络音频系统(NAS)-网络透明的客户端-服务器音频传输系统,其源代码可在SourceForge上获得。 NAS可在Unix和Microsoft Windows上运行。

在此项目中检测到的漏洞的代号为CVE-2013-4258。

CVE-2013-4258的描述 :网络音频系统(NAS)1.9.3的server / os / aulog.c中osLogMsg函数中的格式字符串漏洞允许远程攻击者拒绝服务(崩溃)并可能执行任意代码通过与syslog相关的未指定向量中的格式字符串说明符。

代码如下:

 .... 
if (NasConfig.DoDaemon) { /* daemons use syslog */
openlog("nas", LOG_PID, LOG_DAEMON);
syslog(LOG_DEBUG, buf);
closelog();
} else {
errfd = stderr;
....

在此片段中, 系统日志功能使用不正确。 函数声明如下:

 void syslog ( int priority, const char *format, ...); 

第二个参数应该是格式字符串,而其他所有参数都是该字符串所需的数据。 此处缺少格式字符串,目标消息直接作为参数(变量buf )传递。 这是造成漏洞的原因,该漏洞可能导致执行任意代码。

如果我们相信SecurityFocus数据库中的记录,则该漏洞会在Debian和Gentoo中显示出来。

那PVS-Studio呢? PVS-Studio使用诊断规则V618检测到此错误并发出警告:

V618以这种方式调用’syslog’函数很危险,因为正在传递的行可能包含格式规范。 安全代码示例:printf(“%s”,str);

分析器中内置的功能注释机制有助于检测此类错误; 对于C和C ++,带注释的函数的数量大于6500,对于C#,带注释的函数的数量大于900。

这是纠正此漏洞的正确调用此函数的方法:

 syslog(LOG_DEBUG, "%s", buf); 

它使用格式字符串“%s” ,这使syslog函数的调用安全。

Ytnef(Yerase的TNEF流阅读器)

Ytnef —在GitHub上可用的开源程序。 例如,它旨在对在Outlook中创建的TNEF流进行解码。

在过去的几个月中,这里检测到了许多漏洞。 让我们考虑一下此列表中给出的CVE之一-CVE-2017-6298。

CVE-2017–6298的描述 :在1.9.1之前的ytnef中发现了一个问题。 这与描述为“ 1之9。未检查空指针Deref / calloc返回值”的补丁有关。

所有可能包含空指针取消引用的固定片段都大致相同:

 vl->data = calloc(vl->size, sizeof (WORD)); 
temp_word = SwapWord((BYTE*)d, sizeof (WORD));
memcpy(vl->data, &temp_word, vl->size);

在所有这些情况下,漏洞都是由错误使用calloc函数引起的。 万一程序无法分配所请求的内存块,此函数可以返回空指针。 但是结果指针没有经过NULL测试,因为calloc总是会返回非null指针,所以使用了该指针。 这有点不合理。

PVS-Studio如何检测漏洞? 很容易:分析器具有许多诊断规则,这些规则使用空指针来检测工作。

特别是,上述漏洞将通过V575诊断来检测。 警告如下所示:

V575潜在的空指针被传递到“ memcpy”函数中。 检查第一个参数。

分析器检测到由于对calloc函数的调用而导致的可能为空的指针被传递给了memcpy函数,而没有针对NULL进行验证。

这就是PVS-Studio检测到此漏洞的方式。 如果在编写代码时定期使用分析器,则可以避免此问题进入版本控制系统。

的MySQL

MySQL是一个开放源代码的关系数据库管理系统。 通常,MySQL用作本地或远程客户端访问的服务器。 但是,该分发工具包包括一个内部服务器库,允许将MySQL构建为独立程序。

让我们考虑一下在此项目中检测到的漏洞之一-CVE-2012–2122。

CVE-2012–2122的描述 :Oracle MySQL 5.1.x(5.1.63之前),5.5.x(5.5.24之前)和5.6.x(5.6.6之前)以及MariaDB 5.1.x(5.1之前)中的sql / password.c。 62、5.2.12之前的5.2.x,5.3.6之前的5.3.x和5.5.23之前的5.5.x,在具有某些memcmp功能实现的特定环境中运行时,允许远程攻击者通过重复使用进行身份验证来绕过身份验证相同的错误密码,由于返回值检查不正确,最终导致令牌比较成功。

这是具有漏洞的代码:

 typedef char my_bool; 
my_bool
check_scramble ( const char *scramble_arg, const char *message,
const uint8 *hash_stage2)
{
....
return memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE);
}

memcmp函数的返回值类型为int ,而check_scramble的返回值类型为my_bool,但实际上是char。 结果,存在从intchar的隐式转换在此期间有效位丢失。 结果是,在256种情况中,有1种情况下,只要知道用户名就可以用任何密码登录。 考虑到300次连接尝试不到一秒钟的事实,这种保护与没有保护一样好。 您可以通过以下页面上的链接找到有关此漏洞的更多详细信息:CVE-2012–2122。

PVS-Studio在诊断规则V642的帮助下检测到此问题。 警告如下:

V642将’memcmp’函数结果保存在’char’类型变量中是不合适的。 有效位可能会丢失,从而破坏程序的逻辑。 密码

如您所见,使用PVS-Studio可以检测到此漏洞。

的iOS

iOS –由Apple开发和制造的用于智能手机,平板电脑和便携式播放器的移动操作系统。

让我们考虑一下此操作系统中检测到的漏洞之一; CVE-2014–1266。 幸运的是,我们可以看到问题所在的代码片段已经公开可用。

CVE-2014–1266漏洞的描述: 6.1.6之前的Apple iOS 6.x和7.0.6之前的7.x的数据安全组件中的安全传输功能中的libsecurity_ssl / lib / sslKeyExchange.c中的libsecurity_ssl / lib / sslKeyExchange.c中的SSLVerifySignedServerKeyExchange函数, 6.0.2之前的Apple TV 6.x和10.9.2之前的Apple OS X 10.9.x不会检查TLS服务器密钥交换消息中的签名,该消息允许中间人攻击者通过( 1)在签名步骤中使用任意私钥,或者(2)省略签名步骤。

导致漏洞的代码片段如下:

 static OSStatus 
SSLVerifySignedServerKeyExchange (SSLContext *ctx,
bool isRsa,
SSLBuffer signedParams,
uint8_t *signature,
UInt16 signatureLen)
{
OSStatus err;
....
 if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0) 
goto fail;
if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
goto fail;
goto fail;
if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0)
goto fail;
....
 fail: 
SSLFreeBuffer(&signedHashes);
SSLFreeBuffer(&hashCtx);
return err;
}

问题出在两个彼此靠近的goto运算符中。 第一个引用if语句,而第二个不引用。 因此,无论先前条件的值如何,控制流程都将跳转到“ fail ”标签。 由于有了第二个goto运算符,所以err值将成功。 这使得中间人攻击者可以欺骗SSL服务器。

PVS-Studio使用两个诊断规则(V640和V779)检测到此问题。 这些是警告:

  • V640代码的操作逻辑与其格式不符。 该语句向右缩进,但始终会执行。 大括号可能丢失。
  • V779检测到无法访问的代码。 可能存在错误

因此,分析仪会警告一些似乎令人怀疑的事情。

  • 程序的逻辑与代码格式不符:从对齐方式来看,我们得到的印象是,两个goto语句都引用了if语句,但事实并非如此。 第一个goto确实处于状况中,但是第二个-并非如此。
  • 无法访问的代码:由于第二个goto在没有条件的情况下运行,因此后续代码将无法执行。

事实证明,PVS-Studio在这里也成功地完成了工作。

有效使用静态分析

正如我前面提到的,本文的目的是表明PVS-Studio分析仪可以成功检测到漏洞。 为实现此目标而选择的方法是证明分析仪发现了一些众所周知的漏洞。 该材料对于确认可以使用静态分析来搜索漏洞这一事实是必不可少的。

现在,我想谈谈更有效地做到这一点的方法。 理想情况下,应该在漏洞转化为漏洞之前(即,当有人找到并了解如何利用它们时)将其检测出来; 发现越早越好。 通过以适当的方式使用静态分析,可以在编码阶段检测到漏洞。 下面是如何实现此目的的说明。

注意。 在本节中,我将使用“错误”一词来保持一致性。 但是,正如我们已经看到的,简单的漏洞可能是潜在的漏洞,然后是实际的漏洞。 请不要忘记这一点。

通常,越早发现并修复错误,修复该错误的成本越低。 该图提供了Capers Jones所著《应用软件度量》中的数据。

正如您在图表上看到的那样,当修复成本最小时,大约85%的错误是在编码阶段产生的。 随着错误继续存在于代码中,其修复成本不断提高。 如果在编码阶段仅花费25美元解决错误,那么在软件发布后,这一数字将增加至数万美元。 更不用说发布后发现的漏洞成本。

它得出一个简单的结论-越早发现并纠正错误,越好。 静态分析的目的是尽早发现代码中的错误。 静态分析不是其他验证工具的替代品,而是对它们的补充。

如何从静态分析仪中获得最大的收益? 第一条规则-必须定期检查代码。 理想情况下,应在将错误提交给版本控制系统之前,将其固定在编码阶段。

但是,在开发人员的机器上进行连续检查可能非常不便。 除此之外,对代码的分析可能会很长,因此您无法在修复后重新检查代码。 PVS-Studio实施了特殊的增量分析模式,该模式仅允许分析自上次构建以来已修改/编辑的代码。 此外,此功能允许在构建后自动运行分析,这意味着开发人员无需考虑手动启动分析。 分析完成后,如果在修改的文件中检测到错误,将通知程序员。

但是即使以这种方式使用分析器,也有可能出现错误进入版本控制系统。 这就是为什么拥有“第二级保护”很重要的原因-在构建服务器上使用静态分析器。 例如,将代码分析集成到夜间构建过程中。 这样一来,便可以在晚上进行项目检查,而在早晨则可以收集有关版本控制系统中错误的信息。 这里重要的是立即修复以这种方式检测到的错误-最好在第二天。 否则,随着时间的流逝,没有人会注意新的错误,并且这种检查几乎没有用处。

如果不是从头开始开发项目,则将静态分析实施到开发过程中似乎并非易事。 文章“在大型项目中集成静态分析的快速方法是什么?”对如何正确开始使用静态分析进行了清晰的解释。

结论

我希望我能够证明这一点:

  • 甚至一个看似简单的错误也可能是一个严重的漏洞;
  • PVS-Studio不仅可以成功地检测代码中的错误,还可以成功地处理CWE和CVE。

而且,如果一个简单的漏洞的成本随着时间的推移而增加,那么漏洞的成本可能会非常巨大。 同时,借助静态分析,许多漏洞甚至可以在进入版本控制系统之前得到修复。 更不用说在有人找到它们并开始利用它们之前。

最后,我想建议在您的项目上尝试使用PVS-Studio -如果您发现可以节省项目到CVE基础的东西该怎么办?

附加链接

  • 向安全专家发放PVS-Studio分析仪许可证;
  • PVS-Studio:搜索软件弱点。
  • 如何在一个晚上找到FreeBSD代码中的56个潜在漏洞。
  • PVS-Studio团队愿意致力于改善Tizen项目(公开信)。
  • “在大型项目中集成静态分析的快速方法是什么?”