实例介绍
华为C&C++语言安全编程规范 _ V3.1 不含书签,最新3.1版本
规则24;外部输入作为内存操作相关函数的复制长度时,需要校验其合法性 规则2.5:调用格式化函数时,禁 format参数由外部可控 规则26:用格式化函数时,foma中参数的类型与个数必须与实际参教类型一致 3正确使用安全函数 规则3,1:正确设置安全函数中的 destMax参数 想则32:禁止不正确地軍宾义或封装安全函教 规则3.3:禁止用宏重命名安全函数 规则34:禁止自定义安全函数 规则3.5:必须检查安全函数返回值,并讲行正确的处理 4整数 规则4,1:整数之间运算时必须严格检查,确保不会出现溢出、反转、除0 拟则42整表式北较或值为一种更大美型之前必须用这种更太类型对它进行求值 规则43:禁止对有符号整数效进行位操作符运算 规则44:禁止整数与指针间的互相转化 规则45:禁对指针讲行罗辑或位运(&&_L ><<8.A 规则46:循环次教如果受外部数掴制,要校验其合法性 5内存 规则5.1:内存申请前,必须对申请内存大小讲行合法性校验 规则52:内存分配后必须判断是否成功 规则5.3:禁止引用未初始化的内存」 规则54内存释放之后立即赋予新值 规则5.5:禁止使用 realloc(函数 规则56:禁止使用 alloca(函教申请栈上内存 6不安全函数 规则6.1:禁止外部可控教据乍为 system、 popen、 WinExec Shell Execute、 execl, execl, execle, exec heap、 Create Process等进程启动数的参数 想则6,2禁止外部可控教据作为dlρpen/ oadlibrar块加载函教的参数 规则6,3:禁止使用外部数据拼接SQL命令 规则6.4:禁止在信号处理例程中调用非异步安全函数 规则65:禁用 setup/ ongimp 规则66:禁使用内存操作类危险函数 7文件输入角出 规则7,1:创建文件时必须显式指定合适的文件访问权限 规则72:必须对文件路径进行规范化后进行使用 规则73:不要在共享目录中创對临时文件 建议71:在讲行文件操作时避免引起竞争条件 8敏感信息处理 规则8,1:禁用and数产生用于安全用涂的伪随机数 规则8,2:内存中的敏感信息使用完毕后立即清0 规则83:严禁使用 string类存储敏感信息 附ASQL注入相关的特殊字箮 附录B命令注入相关的特殊字符 附录C危险函数及替换的安全函数列表 附录D异步安全的函数列表 参考资料 0前言 目的 本规范旨在加强程人员在编程过程中的安全意识,建立编程人吴的攻击者思维,养成安全编码的习惯,编写出安 全可靠的代码。 适用范围 CC+语言编程人员都应遵循本规范所规定的内容。 攻击者思维 编程过程中应该时刻保持以下的假设 1.程序所处理的所有外部数据都是不可信的攻击数据 2.攻击者时刻试图监听、算改、破坏程序运行环境、外部数据 安全编码基本思想 基于以上的假设,得出安全编码基本思想 1.程序在处理外部数揖时必须经过严格的合法性校验编程人员在处理外部数据过程中必须时刻保持这种思维意 识,不能做出任何外部数据符合预期的假设,外部数据必须经过严格判断后才能使用。编码人员必须在这种 严酷的攻击环境下通过遵守这一原则保证程序的执行过程符合预期结果。 2尽量减少代码的攻击面代码的实现应该尽量简单,避免与外部环境做多余的数据交互,过多的攻击面增加了 被攻击的相率,尽量避免将程序内部的数据处理过程暴露到外部环境。 3.通过防御性的编码策略来弥补澘在的编码人员的篩恕粗心是人类的天性。由于外部环境的不确定性,以及编 码人员的经验、习惯的差异,代码的执行过程很难达到完全符合预期设想的情况。因此在编码过程中必须采 取防御性的策略,尽量缓解由于编码人员疏忽导致的歃陷。这些彗施包括 口变量声明应该赋予初值 口谨慎使用全局变量 口禁用功能复杂、易用错的函数 口禁用易用错的编译器/操作系统的机制 口小心处理资源访问过程 □不要改变操作系统的运行环境(创建临时文件、修改环境变量、创建进程等 口严格的错误处理 口合理使用调试断言( ASSERT) 外部数据定义 口文件(包括程序的配置文件) □注册表 口网络 口环境变量 口命令行 口用户输入(包括命令行、界面) 口用户态数据(对于内核程序) 口迸程间通信(包括管道、消思、共享内存、 socket、RPC等) 口函数参数(对于AP1) 口全局变量(在本函数内,其他线程会修改全局变量) 术语定义 规则:编程时必须遵守的约定。 建议:编程时必须加以考虑的约定。 例外:指规范不适用的某些特殊场景。"规则"的例外应该是极少的。 特别说明:为聚焦于每项规则及建议内容重点表达的内容,示例代码中通常省路了安全函数的返回值检查以及其 他与重点表述内容无关的检查) 1基础要求 11变量 规则1.1.1:指针变量、表示资源描述符的变量、BooL变量声明必须赋予初 值 变量声明赋予初值,可以避免由于编程人员的巯忽导致的变量未初始化引用。 示例: 1. SOCKET S= INVALID SOCKET 2. uns i gned char msg NULL: 3. BOOL success FALSE: 4. int fd = -1: 以下代码,由于变量声明未赋予初值,在最后free的时候出错。 1. char message;//镭误!必须声明为 char message=NULL; 3. if (condition) I mess age=(char *)malloc(len): 5 6.} 8, if(mess age ! =NULL)t 9 free(message) //如果 condition未满足,会造成free未初始化的内存 10. 例外1:对全局变量,静态变量,在编译阶段自动初始化为0或者等于NLL,不用在定义时强制初始化。例如: 1. 05_SEC_BSS TICK_ENTRY__FUNc g_-pfnTickT askEntry: 2. oS_SEC_BSS volatile UINT64 g_ullSTeepT ime; 3. 05_SEC_BSS volatile UINT64 g_ul15leepBegin: 4. 05_SEC_BSs vo lati le UINT64 g_ullsleepEnd 相关指南: CERT. EXP33-C. Do not read uninitialized memory MISRA. C, 2004, Rule 9.1(required): All automatic variables shall have been assigned a value before being sed 规则1.1.2:指向资源句柄或描述符的变量,在资源释放后立即赋予新值 资源释放后,对应的变量应该立即赋予新值,防止后续又被重新引用。如果释放语句刚好在变量作用域的最后 句,可以不进行赋值。 示例: 1. SOCKET S= INVALID SOCKET 2. uns igned char "msg=NULL; 3, int fd =-1: 4 5. closesocket(s); 6. 5= INVALID SOCKET 8. free(msg): 9.msg=( unsigned char)ma11oc(..)://msg变量又被赋子新值 10 11.c1ose〔fd); 12.fd 相关指南: CERT. MEMO1-C. Store a new value in pointers immediately after freed 规则11.3:类的成员变量必须在构造函数中赋予初值 如果类中声明了变量,则必须在构造函数中对变量进行赋值。 示例: 1. class CMsg t 3 public. CMsg: 4 NCMs gO: 5. protected: 6 int size: 7 g 8. 10. CMs g:: CMsgO 11. 1 size=0. 13 msg= NULL 14. 规则11.4:严禁对指针变呈进行 sizeof操作 编码人员往往由于粗心,将指针当做数组进行seof操作,导致实际的执行结果与预期不符。下面的代码, buffer 和path分是针和数组,编码人员想对这2个内存进行操作,但由于编码人员的疏忽,第5行代码,将内存大 小误写成了 sizeof,与预期不符。 1. char *buffer =(char malloc(size) 2. char path [MAX_PATH]= [0]: 3 4. memset(path, 0, sizeof(path)) 5. memset(buffer, 0, sizeof(buffer ) 如果要判断当前的指针类型大小,请使用 sizeof(char*)的方式。 相关指南 CERT. ARRO1-C. Do not apply the sizeof operator to a pointer when taking the size of an array 建议11.1:尽量使用 const 在变量声明勍加 const关键字,表示该变量不可被修改,这样就可以利用编译器迸行类型检查,将代码的权限降到 更低。例如下面是不好的定义: 1. float pi=3. 14159f: 应当这样定义: 1. const float PI =3.14159f 相关指南 CERTDCLO0-C. Const-qualify immutable objects 建议1.1.2:全局变量的访问如果涉及多个线程,需要考虑多线程竟争条件问 应该尽可能减少全局变量的使用,如果多个线程会访问到该全局变量,则访问过程必须加锁。以下代码中,g|ist 是全局变量,对链表进行搜索操作时,在whil循环语句的前后加锁。 1. ItemList #g_list= NULL; 3. ItemList fSearchList(const char #name) 4. cko 6 ItemList # list 8 9 hile (p|= NULL)C 10 if (strcmp(p->name, name)==0)i eak: 11111 p= p->next 4 16 UnL。ckO; 17 18. return p: 19. 性能敏感的代码,请考虑采用原子操作或者无算法。 相关指南 CERT. CON43-C. Do not allow data races in multithreaded code MITRE. CWE-366, Race condition within a thread 建议113:同一个函数内,局部变量所占用的空间不要过大 程序在运行期间,函数内的局部变量保存在栈中,栈的大小是有限的。如果申请过大的静态数組,可能导致出现运 行出错。建议在申请静态数组的时候,大小不超过0x1000。下面的代码,bu申请过大,导致栈空间不够,程序 发生 stackoverflow异常。 1. *define MAX_ BUFF 0x1000000 2. int Food 3. 4 char buff [MAX_BUFF= [Oh 5 6.} 相关指南: CERT. MEMO5-C Avoid large stack allocations 12断言( ASSERT) 断言是一种除错机制,用于验证代码是否符合编码人员的预期。编码人员在开发期间应该对函数的参数、代码中间 执行结果合理地使用断言机制,确保程序的缺陷尽量在试阶段被发现。断言被触发后,说明程序出现了不应该出 现的严重错误,程序会立即提示错误,并终止执行。断言必须用宏进行定义,只在调试版本有效,最终发布版本不 允许出现 assen函数,例如: 1. #include <assert. h> 2. #ifdef Debug 3.#define aSSerT(f) assert(f) 4, else 5. #define ASSERT(f) ((void)o) 6.井 endif 下面的函数 VerifyEr,上层调用者会保证传进来的参数是合法的字符串,不可能出现传递非法参数的情况。因 此,在该函数的开头,加上4个 ASSERT进行校验。 1. BOOL Ver ifyUser(const char *user Name, const char*pas sword) 2. 3 ASSERT (user Name ! NULL); 4 ASSERT(strlen (us er Name)>0) ASSERT(pas sword != NULL) ASSERT(strlen(password)>0) 8. 以下的 switch,由于不可能出现 defau的情况,所以在 default处直接调用 ASSERT: 1. enum I COLOR RED 1 3 COLOR_GREEN, 4 COLOR BLUE 5.}; 6 7. switch (color)[ case CoLOR RED. 10. case CoLOR GREEN 11 12 case COLOR BLUE 13 14 default: I ASSERT(O) 16 17. 以下代码, SendMsg是CMs类的成员函数, socketID是成员变量,在调用 SendMsg的时候必须保证 socketED已经 被初始化,因此在此处用 ASSERT判断 socket的合法性 1. CMs g:: CMs gO 2345 socketID InvaLID socket int CMsg: SendMs g(const char *msg, int Ten) ASSERT(socketID != INVALID_SOCKET) 7891 ret send (socketID, msg, len, 0): 11 在nux内核中定义 ASSERT宏,可以采用如下方式: 1. #ifdef debug 2. #define ASSERT(f) BUG_ON(! (f)) 3.并else 4.#define ASSERT (f ((void) 5. #endif 相关指南: CERT. MSC11-C Incorporate diagnostic tests using assertions 规则1.21:断言必须使用宏定义,禁止直接调用系统提供的 assert0 断言只能在调试版使用,断言被触发后,程序会立即退出,因此严禁在正式发布版本使用断言,请通过编译选项进 行控制。错误用法如 1. int FooCint arr ay, int size) 2. 3 assert(arr ay != NULL); 5. 规则12.2:运行时可能会导致的错误,严禁使用断言 【实例截图】
【核心代码】
标签:
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论