关闭

C/C++ 代码安全(五)

93人阅读 评论(0) 收藏 举报
规则:

不要使用rand( ) 函数生成伪随机数,这个函数不保证不保证产生随机序列质量,比较好预测。使用random( )  替换。

规则:

正确的设置伪随机数生成器的种子,在random() 之前调用srandom( ) ,以设置伪随机数生成器。

规则:

不要向asctime( ) 函数提供无效数据。

规则:

确保控制永远不会到达非void 函数的结束位置。结尾处无求值语句,为未定义行为。

规则:

如果预定义表示只能以宏的形式实现,不要将其当作对象处理。

规则:

不要在va_list 的值不确定的时候调用va_arg

规则:

不要违反约束。

关于TOCTOU的一个知识点,这个BUG的全称是time of use time of use , 指资源的状态可能在软件检查它的时间以及使用它的时间之间变化的情况。时间流逝导致检查无效,并可能在资源处于无法预料的状态下导致无效的操作。

漏洞与风险
该漏洞的一个典型实例是在打开文件之前,使用系统调用来检查当前进程是否具有打开文件的权限。使用该方式的进程可以在进行检查的时间以及实际打开文件的时间之间被暂停。当进程暂停时,另一个进程可能更改与名称相关联的文件。

通常该情况牵涉到那些支持文件的符号链接的操作系统。例如,使用符号链接操纵密码文件的字符串含义将允许攻击者获得指向任意位置的虚假入口。在某个案例中,在目标用户目录中创建了 .rhosts 文件,从而允许攻击者以该用户的身份进行远程登录。

该漏洞可能允许恶意用户获得对未授权资源的访问权限,并获得进行变更、删除文件以及获得提升的权限。

缓解与预防
避免使用将文件名作为自变量的函数和系统调用,使用那些以文件句柄或文件描述符作自变量的调用。一旦操作系统分配了文件句柄或描述符,它就无法像文件名一样通过符号链接来轻易操纵。

如果您需要在函数中指定文件名

将语句执行的有效 gid 和 uid 设置为当前用户和组的 gid 和 uid
限制资源检查和资源使用之间的时间间隔
在使用调用之后检查资源,确保采取相应的操作
使用环境性锁定机制来保护资源

规则:

不要修改某些函数返回值引用的对象。有些函数返回一个指向对象的指针,在修改该指针时会造成未定义行为。这些函数getenv( ) ,setlocale( ) , localeconv( ),asctime( ) ,strerror( ) .在这种情况下,函数调用结果必须当成const 对待。

示例:

getenv( ) 返回一个指针,指向匹配列表成员相关的字符串。然而作为环境变量程序不能直接修改,如果必须修改应当个创建一个本地拷贝。如果需要修改则使用副本调用setenv( )  函数。

规则:

在可能使某个环境指针无效的操作之后不要依赖该指针。
修改外部环境
#include <stdio.h>
#include <stdlib.h>

extern char ** environ;

int main(void){

   if(setenv("MY_NEW_VAR","new_value",1) != 0){
        /*handle error*/
   }
  
}
规则: 所有退出处理程序必须正常返回。嵌套函数调用退出函数是未定义行为。 由其,_Exit( ) 函数在退出的时候不调用退出处理程序或者信号处理程序。 规则: 不要调用 system( ) . 主要高风险:传递的命令字符串被污染 没有路径名 指定的是可执行的相对路径,且被攻击者有权控制当前目录。 规则: 在调用已知设置error 的库函数之前,将error 设置为0,只在函数返回表示故障之后才检查error . 对于库函数一般有以下规范: @设置error 并返回待外错误 @设置error 并设置带内错误 @不承诺设置error @具有不同标准文档 对于大多数的函数,我们尽可能的优先考虑检查 它的环境下的返回值,其次考虑标准错误检查,但是尽量不要主动设置 error 然后执行测试用例然后来测试是否有错误. 规则: 不要依赖不确定的errno值。 规则: 检测并处理标准库错误。这需要查看C标准库函数。 规则: 清理线程特定存储。例如一键多值的空间一定要选择相关的函数清除空间。 规则: 不要在互斥体被锁定的时候删出他们。互斥体用于保护并发访问的共享数据结构,如果在线程因等待该互斥体被阻塞时,互斥体被删除,临界区将不再受到保护。 规则: 从多个线程访问位域时要避免数据竞争。 考虑这样的一个代码:  
struct flag{
   unsigned int flag1:2;
   unsigned int flag2:2;
};

struct flag test;

int thread1(void *arg){
     flags.flag1 = 1;
     return 0;
}

int thread2(void *arg){
    flags.flag2 = 2;
    return 0;
}     

}
规则: 使用库时比避免竞争条件。有一些C语言标准库函数不保证线程再入。 规则: 以预定义顺序加锁,避免死锁。 规则: 使用条件变量时保持线程安全性和活性。 规则: 不要加入或者断开之前已经加入或者断开的线程。 规则: 不要在一个表达式中两次引用同一个原子变量,例如结合高速缓存和多线程考虑这就是不安全的。    

查看原文:http://zmrlinux.com/2016/08/30/cc-%e4%bb%a3%e7%a0%81%e5%ae%89%e5%85%a8%ef%bc%88%e4%ba%94%ef%bc%89/
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:67582次
    • 积分:3054
    • 等级:
    • 排名:第11370名
    • 原创:244篇
    • 转载:6篇
    • 译文:0篇
    • 评论:13条
    最新评论