您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > 华为C&C++语言安全编程规范-V3.1
华为C&C++语言安全编程规范HuaweiC&C++SecureCodingStandardV3.1华为技术有限公司版权所有侵权必究目录0前言 目的 适用范围 攻击者思维 安全编码基本思想 外部数据定义 术语定义1基础要求 1.1变量 规则1.1.1:指针变量、表示资源描述符的变量、BOOL变量声明必须赋予初值 规则1.1.2:指向资源句柄或描述符的变量,在资源释放后立即赋予新值 规则1.1.3:类的成员变量必须在构造函数中赋予初值 规则1.1.4:严禁对指针变量进行sizeof操作 建议1.1.1:尽量使用const 建议1.1.2:全局变量的访问如果涉及多个线程,必须加锁 建议1.1.3:同一个函数内,局部变量所占用的空间不要过大 1.2断言(ASSERT) 规则1.2.1:断言必须使用宏定义,禁止直接调用assert函数 规则1.2.2:运行时可能会导致的错误,严禁使用断言 规则1.2.3:严禁在断言内改变运行环境 建议1.2.1:不要将多条语句放在同一个断言中 1.3函数 规则1.3.1:数组作为函数参数时,必须同时将其长度作为函数的参数 规则1.3.2:严禁对公共接口API函数的参数进行ASSERT操作 规则1.3.3:不对内容进行修改的指针型参数,定义为const 建议1.3.1:谨慎使用不可重入函数 建议1.3.2:字符串或指针作为函数参数时,请检查参数是否为NULL 建议1.3.3:在函数的开始处对参数进行ASSERT操作(API除外) 1.4循环 规则1.4.1:循环必须有退出条件 1.5异常机制 规则1.5.1:禁用C++异常机制 1.6类 规则1.6.1:如果有构造函数,则必须有析构函数 规则1.6.2:构造函数内不能做任何有可能失败的操作 规则1.6.3:严禁在构造函数中创建线程 规则1.6.4:严禁出现deletethis操作 规则1.6.5:如果类的公共接口中返回类的私有数据地址,则必须加const类型 建议1.6.1:尽量避免定义public成员 1.7安全退出 规则1.7.1:禁用atexit函数 规则1.7.2:严禁调用kill、TerminateProcess函数终止其他进程 规则1.7.3:禁用pthread_exit、ExitThread函数 建议1.7.1:禁用exit、ExitProcess函数(main函数除外) 建议1.7.2:禁用abort函数2字符串/数组操作 规则2.1:确保有足够的存储空间 规则2.2:对字符串进行存储操作,确保字符串有’\0’结束符 规则2.3:外部数据作为数组索引时必须确保在数组大小范围内 规则2.4:外部输入作为内存操作相关函数的复制长度时,需要校验其合法性 规则2.5:调用格式化函数时,禁止format参数由外部可控 规则2.6:调用格式化函数时,format中参数的类型与个数必须与实际参数类型一致3正确使用安全函数 规则3.1:正确设置安全函数中的destMax参数 规则3.2:禁止不正确地重定义或封装安全函数 规则3.3:禁止用宏重命名安全函数 规则3.4:禁止自定义安全函数 规则3.5:必须检查安全函数返回值,并进行正确的处理4整数 规则4.1:整数之间运算时必须严格检查,确保不会出现溢出、反转、除0 规则4.2:整型表达式比较或赋值为一种更大类型之前必须用这种更大类型对它进行求值 规则4.3:禁止对有符号整数进行位操作符运算 规则4.4:禁止整数与指针间的互相转化 规则4.5:禁止对指针进行逻辑或位运算(&&、||、!、~、、、&、^、|) 规则4.6:循环次数如果受外部数据控制,需要校验其合法性5内存 规则5.1:内存申请前,必须对申请内存大小进行合法性校验 规则5.2:内存分配后必须判断是否成功 规则5.3:禁止引用未初始化的内存 规则5.4:内存释放之后立即赋予新值 规则5.5:禁止使用realloc()函数 规则5.6:禁止使用alloca()函数申请栈上内存6不安全函数 规则6.1:禁止外部可控数据作为system、popen、WinExec、ShellExecute、execl,execlp,execle,execv,execvp、CreateProcess等进程启动函数的参数 规则6.2:禁止外部可控数据作为dlopen/LoadLibrary等模块加载函数的参数 规则6.3:禁止使用外部数据拼接SQL命令 规则6.4:禁止在信号处理例程中调用非异步安全函数 规则6.5:禁用setjmp/longjmp 规则6.6:禁止使用内存操作类危险函数7文件输入/输出 规则7.1:创建文件时必须显式指定合适的文件访问权限 规则7.2:必须对文件路径进行规范化后进行使用 规则7.3:不要在共享目录中创建临时文件 建议7.1:在进行文件操作时避免引起竞争条件8敏感信息处理 规则8.1:禁用rand函数产生用于安全用途的伪随机数 规则8.2:内存中的敏感信息使用完毕后立即清0 规则8.3:严禁使用string类存储敏感信息附录ASQL注入相关的特殊字符附录B命令注入相关的特殊字符附录C危险函数及替换的安全函数列表附录D异步安全的函数列表参考资料0前言目的本规范旨在加强编程人员在编程过程中的安全意识,建立编程人员的攻击者思维,养成安全编码的习惯,编写出安全可靠的代码。适用范围C/C++语言编程人员都应遵循本规范所规定的内容。攻击者思维编程过程中应该时刻保持以下的假设:1.程序所处理的所有外部数据都是不可信的攻击数据2.攻击者时刻试图监听、篡改、破坏程序运行环境、外部数据安全编码基本思想基于以上的假设,得出安全编码基本思想:1.程序在处理外部数据时必须经过严格的合法性校验编程人员在处理外部数据过程中必须时刻保持这种思维意识,不能做出任何外部数据符合预期的假设,外部数据必须经过严格判断后才能使用。编码人员必须在这种严酷的攻击环境下通过遵守这一原则保证程序的执行过程符合预期结果。2.尽量减少代码的攻击面代码的实现应该尽量简单,避免与外部环境做多余的数据交互,过多的攻击面增加了被攻击的概率,尽量避免将程序内部的数据处理过程暴露到外部环境。3.通过防御性的编码策略来弥补潜在的编码人员的疏忽粗心是人类的天性。由于外部环境的不确定性,以及编码人员的经验、习惯的差异,代码的执行过程很难达到完全符合预期设想的情况。因此在编码过程中必须采取防御性的策略,尽量缓解由于编码人员疏忽导致的缺陷。这些措施包括:变量声明应该赋予初值谨慎使用全局变量禁用功能复杂、易用错的函数禁用易用错的编译器/操作系统的机制小心处理资源访问过程不要改变操作系统的运行环境(创建临时文件、修改环境变量、创建进程等)严格的错误处理合理使用调试断言(ASSERT)外部数据定义文件(包括程序的配置文件)注册表网络环境变量命令行用户输入(包括命令行、界面)用户态数据(对于内核程序)进程间通信(包括管道、消息、共享内存、socket、RPC等)函数参数(对于API)全局变量(在本函数内,其他线程会修改全局变量)术语定义规则:编程时必须遵守的约定。建议:编程时必须加以考虑的约定。例外:指规范不适用的某些特殊场景。规则的例外应该是极少的。(特别说明:为聚焦于每项规则及建议内容重点表达的内容,示例代码中通常省略了安全函数的返回值检查以及其他与重点表述内容无关的检查)1基础要求1.1变量规则1.1.1:指针变量、表示资源描述符的变量、BOOL变量声明必须赋予初值变量声明赋予初值,可以避免由于编程人员的疏忽导致的变量未初始化引用。示例:以下代码,由于变量声明未赋予初值,在昀后free的时候出错。例外1:对全局变量,静态变量,在编译阶段自动初始化为0或者等于NULL,不用在定义时强制初始化。例如:相关指南:CERT.EXP33-C.DonotreaduninitializedmemoryMISRA.C.2004.Rule9.1(required):Allautomaticvariablesshallhavebeenassignedavaluebeforebeingused.规则1.1.2:指向资源句柄或描述符的变量,在资源释放后立即赋予新值资源释放后,对应的变量应该立即赋予新值,防止后续又被重新引用。如果释放语句刚好在变量作用域的昀后一句,可以不进行赋值。示例:1.SOCKETs=INVALID_SOCKET; 2.unsignedchar*msg=NULL; 3.BOOLsuccess=FALSE; 4.intfd=-1;1.char*message; //错误!必须声明为char*message=NULL; 2.... 3.if(condition){ 4. message=(char*)malloc(len); 5. ... 6.} 7.... 8.if(message!=NULL){ 9. free(message); //如果condition未满足,会造成free未初始化的内存。 10.} 1.OS_SEC_BSSTICK_ENTRY_FUNC g_pfnTickTaskEntry; 2.OS_SEC_BSSvolatileUINT64 g_ullSleepTime; 3.OS_SEC_BSSvolatileUINT64 g_ullSleepBegin; 4.OS_SEC_BSSvolatileUINT64 g_ullSleepEnd; 1.SOCKETs=INVALID_SOCKET; 2.unsignedchar*msg=NULL; 3.intfd=-1; 4.... 5.closesocket(s); 相关指南:CERT.MEM01-C.Storeanewvalueinpointersimmediatelyafterfree()规则1.1.3:类的成员变量必须在构造函数中赋予初值如果类中声明了变量,则必须在构造函数中对变量进行赋值。示例:规则1.1.4:严禁对指针变量进行sizeof操作编码人员往往由于粗心,将指针当做数组进行sizeof操作,导致实际的执行结果与预期不符。下面的代码,buffer和path分别是指针和数组,编码人员想对这2个内存进行清0操作,但由于编码人员的疏忽,第5行代码,将内存大小误写成了sizeof,与预期不符。如果要判断当前的指针类型大小,请使用sizeof(char*)的方式。相关指南:CERT.ARR01-C.Donotapplythesizeofoperatortoapointerwhentakingthesizeofanarray6.s=INVALID_SOCKET; 7.... 8.free(msg); 9.msg=(unsignedchar*)malloc(...); //msg变量又被赋予新值10.... 11.close(fd); 12.fd=-1; 13.... 1.classCMsg{2.public:3. CMsg();4. ~CMsg();5.protected:6. intsize;7. unsignedchar*msg;8.};9.10.CMsg::CMsg()11.{
本文标题:华为C&C++语言安全编程规范-V3.1
链接地址:https://www.777doc.com/doc-6601290 .html