作者 | 爱吃小鱼干
小编 | 吃不饱
01嵌入式软件应用程序所面临的日益增多的网络威胁
嵌入式软件应用面临着越来越多的安全问题,在任何现代软件开发环境中,考虑安全性都是非常重要的。即使经过最好的审查和测试的软件也可能存在BUG,而这些BUG可以让恶意用户进入系统并造成巨大的物理和财务损失。
其攻击范围涵盖很多领域:从机场的调度系统到医疗设备都可能受到攻击,特别值得关注的是日益增加的自动驾驶汽车或连接汽车、列车和飞机等计算机控制系统。任何与外界通信的系统都面临着风险,例如汽车可能被盗,更糟糕的情况是车辆的控制权被夺取。
Q
那么,BUG是如何进入系统的呢?
C和C++语言存在未定义的行为和不确定的行为,这可能会导致问题,尤其是对于没有经验的开发人员来说,他们可能不知道代码实际上并没有执行他们预期的操作。此类错误可能会导致开发者错误地认为一切都很正常,因为以前使用过该代码,所以不需要重新验证。但实际上并非如此。代码的优化可能看起来是一件好事,占用更少的空间,但代码优化可能会删除优化器认为不必要但却对安全至关重要的检查,例如除以零和不可达代码检测。外部库可能包含BUG,但是采用的代码可能没有经过验证。因此,在使用外部库时,重要的是检查公开BUG的已知数据库,例如CV。而任何使用动态内存的地方都可能导致问题,特别是像内存泄漏之类的问题。
更多的安全漏洞是由于假设输入数据格式正确且无需验证,导致出现数据缓冲区溢出和使用未分配动态内存(即所谓的“use after free”)等问题。尽管人们普遍认识到这些安全问题可能会出现,但它们并没有得到足够的关注和解决。原因可能有很多,但最主要的原因是之前没有真正推动改变,增加新功能比花费时间检查安全问题更为重要。可以通过教育开发人员贯穿软件开发生命周期考虑安全、改进流程和工具来提高检测安全漏洞的信心,以及针对安全的测试,来改善这种情况。
02CERT C和C++如何检测软件安全问题
如今可能有实施软件安全的愿望,那么如何实现呢?我们将看看嵌入式系统中使用的语言,以及如何使用C和C++来检测这些语言引起的安全问题。历史上,嵌入式系统是用汇编语言编写的,但现在情况已经改变,大多数关键系统都是用C或C++编写的。C++正在变得越来越受欢迎,但当前C仍是首选语言。然而,这两种语言都存在安全问题。
White Source知识库显示,在过去十年中发现的开源代码安全漏洞中,47%是C,6%是C++。这可能会导致人们认为C本质上比其他语言更容易受到攻击,但事实并非如此。因为C语言编写的代码数量比任何其他语言都多,并且时间跨度较长,因此发现漏洞的机会更多。而在过去五年中发现了大量漏洞是好事情。高危漏洞的高比例(36%)在C++中被发现,然后是C(26%)。但需要注意的是,随着C++变得越来越流行,也会有更多的机会在两种语言中发现漏洞,因此需要适当评估这些数据。
在计算机安全中,最常见的漏洞是缓冲区溢出和输入验证。缓冲区溢出是一个非常严重的问题,可能会导致严重的后果。C和C++特别容易受到溢出攻击的影响,因为它们将字符串定义为未终止的字符数组,没有隐式进行边界检查,即使开发人员认为已经进行了检查,标准库函数对字符串也不执行任何边界检查。在某些函数(如向量、点、A-T)中,C++进行了一些改进,并通过默认进行了边界检查。漏洞代码允许恶意用户覆盖内存中的其他值,例如CPU必须执行的指令,从而更改代码的行为。
Q
关于缓冲区溢出
那就不得不提到两个常见的函数:strcpy和gets。这两个函数都存在潜在的安全风险。如果输入字符串超过目标数组的预定义长度,则strcpy函数会导致缓冲区溢出;而gets函数则永远不能被安全地使用,因为gets函数没有边界检查,当输入的字符串长度大于目标数组的长度时,将发生缓冲区溢出,可能会导致程序运行异常或被入侵者利用。
此外,未受限制的格式化输出字符串也可能会导致安全漏洞。这种漏洞是由于应用程序将输入字符串的数据作为命令进行评估。如果恶意用户可以完全或部分地控制格式化字符串的内容,则可能会导致应用程序崩溃、堆栈内容泄露、任意内存写入等后果。此外,攻击者还可以执行任意代码并以易受攻击进程的权限运行,从而破坏系统的安全和稳定性。
即使是最有经验的程序员也可能犯错。研究表明,他们通常只能以约50% 的效率发现自己的错误。那么如何确保安全问题,例如缓冲区溢出的情况不会出现在最终产品中呢?编译器可能会看到显而易见的起点,但它可能仅实现语言标准的子集,语言标准的解释可能因编译器而异,这可能导致未来的移植或语义错误。最好的方法是根据编码标准对代码进行检查,例如CERT C或CERT C++。正如我们所看到的,C和C++都具有未定义和未指定的行为,应该避免使用。而编码标准正提供了一种做到这一点的方法。
编码标准是一组规则,通常由一个团队根据多年的经验制定,可以让开发人员对其代码更有信心。通过使用编码标准遵循一组规则,降低引入错误的可能性,使代码更易于维护。任何安全系统的起点都是使用防御性实现威廉希尔官方网站 ,使软件即使在面临不利情况时也能继续运行。公认的编码标准意味着其已经考虑了常见的使用情况,因为C和C++都具有可能导致关键或未指定行为的特性。编码标准因此定义了一个语言子集,以防止使用会导致此类行为的构造方式。此外,编码标准将实现强类型,它确保对语言数据类型有所了解,从而防止某些类别的编程错误。
CERT部门协助开发的编码标准专注于安全,它们被认为是一个全面的程序安全标准,并在多个行业中使用。该标准由一个在线社区开发,有单独的标准适用于C、C++和Java。然而,由于C和C++之间存在重叠,许多CERT C规则已经包括在内。只需添加一些额外的规则,便可关注C++语言中没有完全覆盖的部分。如何通过限制使用某些库函数来创建一个安全的C语言子集,以提高代码的安全性?这可以通过引入一些规则来实现,比如INTC和A-R等,这些规则旨在防止常见的安全问题,例如缓冲区溢出和输入验证等。ARR30-C:不要形成或使用超出边界的指针或数组。如果使用越界指针或数组,就可能会导致程序错误和安全漏洞。因此,在编写程序时,应该确保所有指针和数组的访问都在其有效范围内。如果需要进行指针或数组的操作,应该先检查其有效范围,再进行后续的处理。这样可以避免因为越界访问而导致的程序错误和安全漏洞。例如,如果使用指针访问数组元素时,应该先检查指针是否指向数组的有效范围内,再进行访问操作。如果指针越界,就可能会导致程序崩溃或者被攻击者利用。因此,ARR30-C规则的实践可以提高程序的安全性和稳定性。ARR38-C:保证库函数不会形成无效指针。它要求在使用库函数时,必须保证传递给函数的指针参数是有效的,即指向已分配的内存区域或NULL指针。如果传递给函数的指针参数是无效的,那么就可能会出现程序错误和安全漏洞。
因此,在使用库函数时,应该先检查传递给函数的指针参数是否有效,再进行后续的处理。这样可以避免因为传递无效指针而导致的程序错误和安全漏洞。例如,如果使用strcpy()函数将一个字符串复制到另一个字符串中,那么应该先检查目标字符串的指针是否有效,再进行复制操作。如果目标字符串的指针无效,那么就可能会导致程序崩溃或者被攻击者利用。因此,ARR38-C规则的实践可以提高程序的安全性和稳定性。
EXP39-C: 不要通过不兼容类型的指针访问变量。如果使用不兼容类型的指针访问变量,就可能会导致程序错误和安全漏洞。因此,在访问变量时,应该使用与变量类型兼容的指针。如果需要使用不兼容类型的指针,可以通过类型转换来实现。但是,在进行类型转换时,需要确保转换后的指针仍然指向有效的内存区域,否则就可能会出现程序错误和安全漏洞。因此,EXP39-C规则的实践可以提高程序的安全性和稳定性。
FIO37-C: 在使用fgets()或fgetws()函数读取输入时,不要假定函数返回的字符串非空。因为这两个函数在读取输入时可能会遇到文件结束符或读取错误等情况,导致返回的字符串为空。如果程序在使用fgets()或fgetws()函数时假定返回的字符串非空,那么就可能会出现程序错误和安全漏洞。因此,在使用fgets()或fgetws()函数时,应该先检查返回的字符串是否为空,再进行后续的处理。这样可以避免因为假定字符串非空而导致的程序错误和安全漏洞。
STR31-C: 确保字符串存储空间足够容纳字符数据和空字符终止符。这条规则的目的是防止缓冲区溢出和其他安全漏洞,从而提高代码的安全性和可靠性。具体实现方法包括使用安全的字符串函数、检查字符串长度和缓冲区大小、避免使用不安全的字符串拼接等。在编写代码时,应该遵循这条规则,并结合实际情况选择相应的实现方法,以确保代码的安全性和可靠性。STR32-C: 不要将非零终止字符序列传递给期望字符串的库函数。旨在防止将非空字符终止的字符序列传递给期望字符串的库函数。这条规则的目的是防止缓冲区溢出和其他安全漏洞,从而提高代码的安全性和可靠性。具体实现方法包括使用安全的字符串函数、检查字符串长度和缓冲区大小、避免使用不安全的字符串拼接等。在编写代码时,应该遵循这条规则,并结合实际情况选择相应的实现方法,以确保代码的安全性和可靠性。
03静态代码分析工具如何有效地实现安全编码标准?
如何实施编码标准以确保代码的正确性和合规性呢?CERT C标准规定了确定性、不确定性和合规性的要求,并强制要求代码不得违反任何规则。同时,建议遵循推荐操作以便更容易符合规则。为了检查代码是否违反规则,该标准建议使用静态代码分析工具。
在软件开发生命周期中,手动和自动代码审查都有其适用的场景,例如自动化工具无法知道代码的实际意图。然而,手动代码审查的结果会受到审核人员专业知识的影响。静态代码分析可以检查很少被控制的代码片段,这些代码片段通常无法通过其他方法测试。这可以找出异常处理程序或日志系统中的缺陷。与手动代码审查相比,其速度更快,而且不占用开发人员的时间,使他们能够更专注于开发。开发者广泛认为手动审核和自动静态代码分析的结合是最有效的方式,因为这是识别漏洞和弱点的最佳方式,CERT C 和CERT C++ 都应该使用静态代码分析工具,最好是行业标准的工具,如Helix QAC,其对CERT编码规范的覆盖度达到100%。这款Perforce的静态代码分析工具可以验证代码符合编码指南,并提供这种符合性的证据,以满足网络安全要求。Helix QAC 具有完整的第三方 C 和 C++ 语言库的覆盖,这使得开发人员更容易验证软件是否免受常见代码安全漏洞的影响。
04总结
总之,实施编码标准是确保代码质量的重要步骤,它可以帮助开发人员避免常见的错误和漏洞,从而提高软件的可靠性和安全性。同时,使用静态分析工具进行全面的代码审查可以进一步加强代码的正确性和符合性。
-
软件
+关注
关注
69文章
4938浏览量
87446 -
信息安全
+关注
关注
5文章
656浏览量
38899
发布评论请先 登录
相关推荐
评论