错误类型转换范例正确使用范例(二)-上海怡健医学

本文仅供技术学习参考。

指针释放后,必须设置为空指针

如果指针释放处理不当,很容易引发高危漏洞:内存损坏漏洞。

编程中释放指针后,需要将指针设置为NULL,以防止后续对空闲指针的误用,从而导致UAF(Use After Free)等其他内存损坏问题。尤其是存储在结构和类中的原始指针。

无错误指针示例

适当的自由指针范式

指针释放建议解决方案:建议使用字符串、向量、智能指针等代替原有的内存管理机制,可以大大减少此类错误。

指针应用程序必须检查空指针

如果此类问题处理不当,很容易造成低风险的拒绝服务漏洞风险。

以下是检查空指针的示例

注意如何检查指针大小

检查指针大小处理不当,会引发中等风险逻辑漏洞的风险

以下是检查指针大小的示例

安全使用智能指针

如果智能指针使用不当,会导致高危漏洞:内存损坏漏洞

在编程中使用智能指针时,需要防止智能指针和原始指针混用,否则可能导致对象生命周期问题,比如UAF安全风险。

不正确使用智能指针

正确使用智能指针

防止错误的类型转换

处理不当的强制转换可能导致高风险漏洞:内存损坏漏洞

在编程中对指针、对象或变量进行操作时,需要能够正确判断被操作对象的原始类型。如果使用与原始类型不兼容的类型进行访问操作,代码将存在安全风险。

错误类型转换示例

正确使用类型转换范式

无限功能不能直接使用

使用一个没有长度限制的函数,它会引发中风险和高风险漏洞:信息泄露和缓冲区溢出。

不能直接使用无限字符串复制和输入功能,如strcpy、sprintf、wcscpy、mbscpy等功能。这些函数的特点是可以输入一长串字符串而不限制长度。如果环境允许,你应该改用_s安全版本,或者使用n版本的函数(例如:snprintf、vsnprintf)。

在使用sscanf等函数时,在处理字符串输入时应严格限制字符串长度,并保证字符串末尾有\0。如果环境允许已经加载dll找不到输入点,应该使用 _s 安全版本。

使用 n 系列复制功能时,请确保正确计算缓冲区长度。同时,如果不确定在每个编译器下ground是否能保证末尾为0,建议在输入缓冲区中增加1个字节,设置为\0,以保证输出字符串最后必须有一个 \0。

建议使用方案:在C++中,建议将原始指针和动态数组替换为字符串、向量等更高封装层的基础组件,可以有效提高代码的可读性和安全性。

启动进程类调用系统函数的安全实践

如果启动进程类的系统函数调用不当,会导致两个高危漏洞:代码执行漏洞和提权漏洞。

在调用system、WinExec、CreateProcess、ShellExecute等函数启动进程类时,需要严格检查函数的参数。

从用户输入读取组合命令行时,启动时的环境变量,您还需要注意可能存在的命令注入风险。最好检查用户输入的非法数据。

要遵循的示例

尽量不要使用 _alloca 和变长数组

使用 _alloca 和可变长度数组,它可以打开低风险和高风险漏洞:拒绝服务和内存损坏。

_alloca 和可变长度数组使用的内存量在编译时是未知的,尤其是在循环中使用时,并且取决于编译器的实现可能会导致:1.堆栈溢出;2.缺少堆栈内存测试的编译器实现可能会导致分配到堆栈外内存和内存损坏。

对于 C++,变长数组也是一种非标准的扩展,在代码规范中是禁止使用的。

调用printf系列函数,参数必须对应

不处理就调用printf系列函数会导致中危漏洞:信息泄露漏洞

调用printf系列函数,如sprintf、snprintf、vprintf等,必须对应控制符号和参数。

不要使用用户可修改的字符串作为 printf 系列函数的“格式”参数

如果处理不当,可能会导致低风险、中等风险和两个高风险漏洞:拒绝服务、信息泄露、内存损坏和代码执行漏洞。

如果用户可以控制字符串,通过%n、%p等,最坏的情况下,任何恶意代码都可以直接执行。

删除数组时需要使用 delete[]

如果处理不当,将导致低风险、中风险和高风险漏洞:内存泄漏、逻辑漏洞、内存损坏漏洞

delete [] 运算符用于删除数组。delete 运算符用于删除非数组对象。它们分别调用 operator delete[] 和 operator delete。

建议解决方案在C++代码中,使用字符串、向量、智能指针(如std::unique_ptr)等可以消除大部分delete[]的使用场景,代码更干净。

使用开关时必须使用默认值

如果switch在编程中应用不好,会导致两个中等风险的漏洞:逻辑漏洞和内存泄漏。

switch 中应该有 default 来处理各种突发情况。这样可以保证开关接受用户输入,或者以后其他开发者修改功能后,保证开关仍然可以覆盖所有情况,保证逻辑正常工作。

不要在调试版本或错误消息中提供太多信息。

提供过多的信息,从而产生中等风险的信息泄露漏洞。

用户不应捕获包含过多信息的调试消息。调试信息可能会泄露一些值,例如内存数据、内存地址等,这可以帮助攻击者在对程序进行初始控制后更容易地攻击程序。

无法返回堆栈上变量的地址并使用未初始化的堆栈变量

这种情况可能导致高风险的内存损坏漏洞。

函数不能返回栈上变量的地址,函数返回后其内容无效,可以使用堆类传递简单类型变量。

确保在堆栈上声明的变量在使用之前已初始化。声明变量时最好直接初始化变量值。

建议的解决方案:强烈建议返回字符串、向量等类型,这样会使代码更简单、更安全。

错误的范式

正确使用示例

函数的每个分支都应该有一个返回值

如果函数中的分支处理不当,会导致两个中危漏洞:信息泄露和逻辑漏洞。

函数的每个分支都应该有一个返回值,否则如果函数转到一个没有返回值的分支,结果是未知的。

错误使用示例

正确使用示例

变量应确保多线程中的线程安全

如果线程中的变量处理不当,会导致两个中危漏洞:信息泄露和逻辑漏洞。

当一个变量可能被多个线程使用时,应该使用原子操作或锁定操作。

建议的解决方案:

对于 C 代码,推荐在 C11 之后使用 atomic 标准库。

对于 C++ 代码,在 C++11 之后已经加载dll找不到输入点,推荐使用 std::atomic。

错误使用示例

正确使用示例

敏感信息不得以明文形式存储在程序中。

存储明文信息,引发高危漏洞风险:敏感信息泄露漏洞。

用户的敏感信息要经过加密算法处理,传输时加密,存储时加密,存储时加密。程序运行内存中的用户敏感信息应完全擦除。

使用 rand 类函数应该正确初始化

rand函数在编程中没有正确初始化,会导致逻辑漏洞的高危漏洞。

在编程中,类 rand 函数的随机性不高。并且在使用前需要使用 srand 进行初始化。未初始化的随机数可能会导致一些可预测的事情。

操作文件时避免路径遍历问题

在编程中,如果文件路径处理不当,会导致高风险的逻辑漏洞。

在进行文件操作时,需要判断传入的文件名是否合法。如果文件名中包含../等特殊字符,会导致路径遍历,导致任意文件的读写。

避免导致劫持的相对路径

如果在编程中对相对路径处理不当,就会导致出现逻辑漏洞的风险。

在编程中,使用相对路径可能会带来一些安全隐患,比如DLL、EXE劫持等问题。

DLL劫持编码安全建议:

在调用LoadLibrary、LoadLibraryEx、CreateProcess、ShellExecute等函数进行模块加载时,指定模块的完整(全)路径,禁止使用相对路径,以免从其他目录加载DLL。调用 SetDllDirectory(TEXT(“”)); 在应用程序的开头从 DLL 的搜索列表中删除当前目录。结合SetDefaultDllDirectories、AddDllDirectory、RemoveDllDirectory等API,可以有效避免DLL劫持问题。

文件权限控制

在编程中,文件权限处理不当,会导致中等风险的逻辑漏洞风险。

创建文件时,需要根据文件的敏感级别设置不同的访问权限,防止敏感数据被其他恶意程序读取或写入。

防止整数溢出

在编程中,当数据操作处理不当时,可能会导致一个高危漏洞:内存损坏。

计算时需要考虑整数溢出的可能性,尤其是在进行内存操作时,需要验证分配、复制等的合法性,防止因整数溢出导致漏洞。

错误使用示例

正确使用示例

防止一对一漏洞

在计算和操作数据时,可能会导致一个高危漏洞:内存损坏

在进行计算或运算时,使用不正确的最大值或最小值以致该值比正确值大 1 或小 1 可能会导致安全风险。

解决方案:建议使用字符串和向量等组件,而不是原始的指针和数组操作。

在操作期间检查除以零异常

在编程中,数据操作不检查除以零,这可能导致低风险漏洞:拒绝服务漏洞。

在进行除法运算时,需要判断被除数是否为零,以防止程序达不到预期或崩溃。

防止数字类型的错误转换

数值类型在编程中处理不当,可能导致中等风险的逻辑漏洞和高风险的内存损坏漏洞。

在涉及有符号数和无符号数的运算中,需要注意类型强制,这可能会导致逻辑错误。建议指定参与计算的数字类型或统一类型参与计算。

下图为参考示例

比较数据大小时添加最小或最大校验和

编程中的数据处理不好,会导致高危内存损坏漏洞

编程中比较数据大小时,需要合理检查数据的区间范围。建议根据数值类型判断最大值和最小值,防止出现意外错误。

‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

‍‍‍‍‍‍‍‍‍‍‍

如何编写更安全的代码?

— EOF —

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论