diff --git "a/openKylin-C&C++\350\257\255\350\250\200\345\256\211\345\205\250\347\274\226\347\250\213\350\247\204\350\214\203.md" "b/openKylin-C&C++\350\257\255\350\250\200\345\256\211\345\205\250\347\274\226\347\250\213\350\247\204\350\214\203.md" new file mode 100644 index 0000000000000000000000000000000000000000..0cd8d8a61bd2e1d68b2d2eb0e01eb7b6a913fab0 --- /dev/null +++ "b/openKylin-C&C++\350\257\255\350\250\200\345\256\211\345\205\250\347\274\226\347\250\213\350\247\204\350\214\203.md" @@ -0,0 +1,998 @@ +C&C++安全编程规范 + + -------------------------------- -------------------------------------- + 审核人: 编写日期: + + 批准人: 审核日期: + -------------------------------- -------------------------------------- + +麒麟软件有限公司 + +版本说明 + + ------------ -------- -------------------------------- ------------ -------------- + 日期 版本号 发布说明 编写人 审核人 + + 2022.05.07 v1.0 编写初稿 苏鑫 + + 2022.05.20 v2.0 添加命令注入、路径操作相关规则 苏鑫 + + 2022.06.15 v3.0 添加EXP01、MSC01、PRE01规则 苏鑫 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ------------ -------- -------------------------------- ------------ -------------- + +# 目录 {#目录 .TOC-标题1} + +[0. 前言 [3](#前言)](\l) + +[目的 [3](#目的)](\l) + +[适用范围 [4](#适用范围)](\l) + +[1. 基本要求 [4](#基本要求)](\l) + +[1.1. 未使用的代码 [4](#未使用的代码)](\l) + +[规则1.1.1 项目不应包含执行不到的代码 [4](#_Toc842753089)](\l) + +[1.2. 初始化 [4](#初始化)](\l) + +[规则1.2.1 具有自动存储期限的对象的值在设置之前不得读取 +[4](#_Toc1756175168)](\l) + +[2. 预处理 [5](#预处理)](\l) + +[规则2.1 不要使用弃用或过时的函数替换安全函数 +[5](#规则2.1-不要使用弃用或过时的函数替换安全函数)](\l) + +[3. 表达式 [6](#表达式)](\l) + +[规则3.1 不要读取未初始化的内存 +[6](#规则3.1-不要读取未初始化的内存)](\l) + +[4. 内存 [7](#内存)](\l) + +[规则4.1 在不再需要时释放动态分配的内存 +[7](#规则4.1-在不再需要时释放动态分配的内存)](\l) + +[5. 输入输出 [8](#输入输出)](\l) + +[规则5.1 规范化源自受污染源的路径名称 +[8](#规则5.1-规范化源自受污染源的路径名称)](\l) + +[6. 环境 [10](#环境)](\l) + +[规则6.1 不调用system()或等价的函数 +[10](#规则6.1-不调用system或等价的函数)](\l) + +[7. 杂项 [12](#杂项)](\l) + +[规则7.1 不要使用已弃用或过时的函数 +[12](#规则7.1-不要使用已弃用或过时的函数)](\l) + +[8. 代码规范工具 [15](#代码规范工具)](\l) + +[8.1. 待定 [15](#待定)](\l) + +# 前言 + +## 目的 {#目的 .list-paragraph} + +> 本规范作为安全编程规范指南,引导编程人员建立安全编程思维,强化安全编程意识,养成良好的编程习惯,从而交付高质量,高可靠的代码 + +## 适用范围 {#适用范围 .list-paragraph} + +本规范适用但不限于C/C++语言编程人员及审核人员,本规范通过实践,不断迭代和完善。 + +1. # 基本要求 + + 1. ## 未使用的代码 + + []{#_Toc842753089 .anchor}规则1.1.1 项目不应包含执行不到的代码 + +执行不到的代码不会被执行,存在执行不到的代码可能表示程序逻辑中存在错误。执行不到的代码会浪费资源。 + +1) 风险评估 + +等级 :L2 + +分析 :不可判断 + +2) 相关指南 + + ----------------------------------- ----------------------------------- + MISRA.Rule 2.1 A project shall not contain + unreachable code + + ----------------------------------- ----------------------------------- + +1. ## 初始化 + + []{#_Toc1756175168 .anchor}规则1.2.1 + 具有自动存储期限的对象的值在设置之前不得读取 + +拥有静态存储周期的对象若不进行显式初始化,会自动初始化为零。拥有静态存储周期的对象不会自动初始化,因此可能是不确定的值。 + +1) 不合规代码 + + 例1: + ++-----------------------------------------------------------------------+ +| void f(bool_t b, uint16_t \*p){ | +| | +| if(b){ | +| | +| \*p = 3U; | +| | +| } | +| | +| } | +| | +| void g(void){ | +| | +| uint16_t u; | +| | +| f(false, &u); | +| | +| if(u == 3U){ | +| | +| /\* 不合规,因为u未被赋值 \*/ | +| | +| } | +| | +| } | ++-----------------------------------------------------------------------+ + +2) 风险评估 + +等级 :L1 + +分析 :不可判断 + +3) 相关指南 + + ----------------------------------- ----------------------------------- + MISRA.Rule 9.1 The value of an object with + automatic storage duration shall + not be read before it has been set + + ----------------------------------- ----------------------------------- + +# 预处理 + +## 规则2.1 不要使用弃用或过时的函数替换安全函数 {#规则2.1-不要使用弃用或过时的函数替换安全函数 .list-paragraph} + +宏经常用于将一个标识符全局替换为另一个标识符以修复现有代码。将函数名称替换为已弃用或过时函数的函数名称会非常危险。弃用的函数由《C语言标准》定义。过时的函数由该规范的MSC01-C定义。 + +此规则与规则MSC24-C本质上相同的,不同之处是不安全函数出现的位置。 + +1) 不合规代码 + +对于不支持vsnprintf()的系统,如下面的不合规代码创建了一个C头文件,将vsnprintf()函数定义为vsprintf()函数: + ++-----------------------------------------------------------------------+ +| #define vsnprintf(buf, size, fmt, list) \\ | +| | +| vsprintf(buf, fmt, list) | ++-----------------------------------------------------------------------+ + +vsprintf()函数不检查边界。参数size被丢弃,当使用不受信任的数据时,可能导致缓冲区溢出。 + +2) 合规代码 + +解决方案是包含缺失函数的实现。假设由于未定义\_\_USE_ISOC11导致找不到vsnprintf()函数的定义,合规代码如下: + ++-----------------------------------------------------------------------+ +| #include \ | +| | +| #ifndef \_\_USE_ISOC11 | +| | +| #include \"my_stdio.h\" | +| | +| #endif | ++-----------------------------------------------------------------------+ + +3) 风险评估 + +已弃用和过时的函数通常与软件漏洞相关联。 + +等级 :L1 + +4) 相关指南 + + ----------------------------------- ----------------------------------- + MITRE CWE CWE-684,未能提供指定的功能 + + CERT.PRE09-C Do not replace secure functions + with deprecated or obsolescent + functions + ----------------------------------- ----------------------------------- + +# 表达式 + +## 规则3.1 不要读取未初始化的内存 {#规则3.1-不要读取未初始化的内存 .list-paragraph} + +如果在初始化之前读取局部自动变量,则它们可能为非预期值。例如,当本地自动变量存储在程序堆栈中时,它们的值默认为当前存储在堆栈内存中的任意值。 + +1) 不合规代码 + +不合规代码中,is_negative()函数返回number是否为负数。但是,程序员忽略了number等于0的情况。因为局部变量sign未初始化,所以\<操作在读取sign时表现出非预期的行为。 + ++-----------------------------------------------------------------------+ +| int is_negative(int number) { | +| | +| int sign; | +| | +| if (number \> 0) { | +| | +| sign= 1; | +| | +| } else if (number \< 0) { | +| | +| sign= -1; | +| | +| } | +| | +| return sign \< 0; | +| | +| } | ++-----------------------------------------------------------------------+ + +2) 合规代码 + +通过考虑number等于0的可能性来修复该问题。 + ++-----------------------------------------------------------------------+ +| int is_negative(int number) { | +| | +| int sign; | +| | +| if (number \>= 0) { | +| | +| \*sign_flag = 1; | +| | +| } else { | +| | +| \*sign_flag = -1; | +| | +| } | +| | +| return sign \< 0; | +| | +| } | ++-----------------------------------------------------------------------+ + +3) 风险评估 + +读取未初始化的变量可能会导致非预期的程序行为。在某些情况下,这些安全漏洞可能允许执行任意代码。 + +等级:L1 + +4) 相关指南 + ++-----------------------------------+-----------------------------------+ +| MITRE CWE | CWE-456,未初始化变量 | +| | | +| | CWE-457,使用未初始化变量 | ++-----------------------------------+-----------------------------------+ +| CERT.EXP33-C | Do not read uninitialized memory | ++-----------------------------------+-----------------------------------+ + +# 内存 + +## 规则4.1 在不再需要时释放动态分配的内存 {#规则4.1-在不再需要时释放动态分配的内存 .list-paragraph} + +最后一个存储标准内存分配函数返回值的指针,在生命周期结束之前,必须由匹配的释放函数,如free、delete等,进行释放。 + +1) 不合规代码 + +由malloc()分配的对象,在指向该对象的最后一个指针text_buffer的生命周期结束之前没有被释放: + ++-----------------------------------------------------------------------+ +| enum { BUFFER_SIZE = 32 }; | +| | +| int f(void) { | +| | +| char \*text_buffer = (char \*)malloc(BUFFER_SIZE); | +| | +| return 0; | +| | +| } | ++-----------------------------------------------------------------------+ + +2) 合规代码 + +调用free()释放指针: + ++-----------------------------------------------------------------------+ +| enum { BUFFER_SIZE = 32 }; | +| | +| int f(void) { | +| | +| char \*text_buffer = (char \*)malloc(BUFFER_SIZE); | +| | +| free(text_buffer); | +| | +| return 0; | +| | +| } | ++-----------------------------------------------------------------------+ + +3) 风险评估 + +未能释放内存可能会导致系统内存资源耗尽,从而导致拒绝服务攻击。 + +等级:L2 + +4) 相关指南 + ++-----------------------------------+-----------------------------------+ +| MITRE CWE | CWE-401,删除最后一个引 | +| | 用之前不当的内存释放(内存泄漏) | ++-----------------------------------+-----------------------------------+ +| CERT.MEM31-C | Free dynamically allocated memory | +| | when no longer needed | ++-----------------------------------+-----------------------------------+ +| MISRA.Rule 22.1 | All resources obtained | +| | dynamically by means of Standard | +| | Library | +| | | +| | functions shall be explicitly | +| | released | ++-----------------------------------+-----------------------------------+ + +# 输入输出 + +## 规则5.1 规范化源自受污染源的路径名称 {#规则5.1-规范化源自受污染源的路径名称 .list-paragraph} + +为了简化文件名验证,建议将名称转换为其规范形式。由于规范形式在操作系统和文件系统之间各有不同,因此最好使用操作系统特定的机制进行规范化。例如,这是一个在Linux系统上确保路径名为用户主目录中文件的函数: + ++-----------------------------------------------------------------------+ +| #include \ | +| | +| #include \ | +| | +| #include \ | +| | +| int verify_file(char \*const filename) { | +| | +| /\* Get /etc/passwd entry for current user \*/ | +| | +| struct passwd \*pwd = getpwuid(getuid()); | +| | +| if (pwd == NULL) { | +| | +| /\* Handle error \*/ | +| | +| return 0; | +| | +| } | +| | +| const size_t len = strlen( pwd-\>pw_dir); | +| | +| if (strncmp( filename, pwd-\>pw_dir, len) != 0) { | +| | +| return 0; | +| | +| } | +| | +| /\* Make sure there is only one \'/\', immediately after homedir \*/ | +| | +| if (strrchr( filename, \'/\') == filename + len) { | +| | +| return 1; | +| | +| } | +| | +| return 0; | +| | +| } | ++-----------------------------------------------------------------------+ + +1) 不合规代码 + +在不合规示例中,argv\[1\]包含源自受污染源的文件名。引用的文件名argv\[1\]可能包含特殊字符,例如目录字符,会使验证变得困难。此外,argv\[1\]可能是符号链接,导致文件名引用无效文件。如果未正确执行验证,则调用fopen()可能会导致访问意外的文件。 + ++-----------------------------------------------------------------------+ +| if (!verify_file(argv\[1\]) { | +| | +| /\* Handle error \*/ | +| | +| } | +| | +| if (fopen(argv\[1\], \"w\") == NULL) { | +| | +| /\* Handle error \*/ | +| | +| } | ++-----------------------------------------------------------------------+ + +2) 合规代码 + +realpath()函数可以帮助将路径名称转换为其规范形式。该函数的许多手册页都带有警告。尽管有警告,但分配第2个参数为NULL或PATH_MAX大小缓冲区的用法是安全的。例如如下的合规代码,这个代码适用于argv\[1\]指向的文件存在的情况: + ++-----------------------------------------------------------------------+ +| char \*realpath_res = NULL; | +| | +| realpath_res = realpath(argv\[1\], NULL); | +| | +| if (realpath_res == NULL) { | +| | +| /\* Handle error \*/ | +| | +| } | +| | +| if (!verify_file(realpath_res) { | +| | +| /\* Handle error \*/ | +| | +| } | +| | +| if (fopen(realpath_res, \"w\") == NULL) { | +| | +| /\* Handle error \*/ | +| | +| } | +| | +| free(realpath_res); | +| | +| realpath_res = NULL; | ++-----------------------------------------------------------------------+ + +对于argv\[1\]指向的文件不存在的情况,建议realpath第2个参数为PATH_MAX大小的缓冲区: + ++-----------------------------------------------------------------------+ +| #include \ | +| | +| char \*realpath_res = NULL; | +| | +| char \*canonical_filename = NULL; | +| | +| size_t path_size = 0; | +| | +| path_size = (size_t)PATH_MAX; | +| | +| if (path_size \> 0) { | +| | +| canonical_filename = malloc(path_size); | +| | +| if (canonical_filename == NULL) { | +| | +| /\* Handle error \*/ | +| | +| } | +| | +| realpath_res = realpath(argv\[1\], canonical_filename); | +| | +| } | +| | +| if ( canonical_filename == NULL) { | +| | +| /\* Handle error \*/ | +| | +| } | +| | +| if (!verify_file( canonical_filename) { | +| | +| /\* Handle error \*/ | +| | +| } | +| | +| if (fopen( canonical_filename, \"w\") == NULL ) { | +| | +| /\* Handle error \*/ | +| | +| } | +| | +| free(canonical_filename); | +| | +| canonical_filename = NULL; | ++-----------------------------------------------------------------------+ + +3) 风险评估 + +与文件相关的漏洞通常可以被利用,导致具有提升权限的程序访问意外文件。 + +等级:L2 + +4) 相关指南 + ++-----------------------------------+-----------------------------------+ +| MITRE CWE | CWE-22,路径遍历 | +| | | +| | CWE-23,相对路径遍历 | +| | | +| | CWE-28,路径遍历:\'../filedir\' | +| | | +| | CWE- 41,无法解析路径 | +| | | +| | CWE-59,无法在 | +| | 文件访问之前解析链接(链接跟随) | +| | | +| | CWE-73,文件名或路径的外部控制 | ++-----------------------------------+-----------------------------------+ +| CERT.FIO02-C | Canonicalize path names | +| | originating from tainted sources | ++-----------------------------------+-----------------------------------+ + +# 环境 + +## 规则6.1 不调用system()或等价的函数 {#规则6.1-不调用system或等价的函数 .list-paragraph} + +C语言标准的system()函数通过调用命令处理器(例如Linux系统中的shell)来执行指定的命令。popen()函数也调用命令处理器,但在调用程序和执行的命令之间创建一个管道,返回一个指向可用于读写管道的流的指针。使用system()函数可能会导致可利用的漏洞,在最坏的情况下允许执行任意系统命令。对system()的调用具有高风险的情况包括: + +• 当传递源自受污染源的未经处理或处理不当的命令字符串时 + +• 如果指定的命令没有路径名,并且攻击者可以访问命令处理器路径名解析机制 + +• 如果指定了可执行文件的相对路径并且攻击者拥有当前目录的访问控制权限 + +• 如果指定的可执行程序可以被攻击者篡改 + +不要通过system()或等效函数通过命令处理器来执行命令。 + +1) 不合规代码 + ++-----------------------------------------------------------------------+ +| #include \ | +| | +| #include \ | +| | +| #include \ | +| | +| enum { BUFFERSIZE = 512 }; | +| | +| void func(const char \*input) { | +| | +| char cmdbuf\[BUFFERSIZE\]; | +| | +| int len_wanted = snprintf(cmdbuf, BUFFERSIZE, \"any_cmd \'%s\'\", | +| input); | +| | +| if (len_wanted \>= BUFFERSIZE) { | +| | +| /\* Handle error \*/ | +| | +| } else if (len_wanted \< 0) { | +| | +| /\* Handle error \*/ | +| | +| } else if (system(cmdbuf) == -1) { | +| | +| /\* Handle error \*/ | +| | +| } | +| | +| } | ++-----------------------------------------------------------------------+ + +如果此代码在 Linux +系统上以提升的权限编译和运行,则攻击者可以通过输入以下字符串来创建帐户 + + ----------------------------------------------------------------------- + happy\'; useradd \'attacker + + ----------------------------------------------------------------------- + +2) 合规代码 + +将system()替换为exec系列函数。exec系列函数不使用完整的shell解释器,因此不易受到命令注入攻击。 + ++-----------------------------------------------------------------------+ +| #include \ | +| | +| #include \ | +| | +| #include \ | +| | +| #include \ | +| | +| #include \ | +| | +| void func(char \*input) { | +| | +| pid_t pid; | +| | +| int status; | +| | +| pid_t ret; | +| | +| char \*const args\[3\] = {\"any_cmd\", input, NULL}; | +| | +| char \*\*env; | +| | +| extern char \*\*environ; | +| | +| /\* \... Sanitize arguments \... \*/ | +| | +| pid = fork(); | +| | +| if (pid == -1) { | +| | +| /\* Handle error \*/ | +| | +| } else if (pid != 0) { | +| | +| while ((ret = waitpid(pid, &status, 0)) == -1) { | +| | +| if (errno != EINTR) { | +| | +| /\* Handle error \*/ | +| | +| break; | +| | +| } | +| | +| } | +| | +| if ((ret != -1) && (!WIFEXITED(status) \|\| !WEXITSTATUS(status)) ) { | +| | +| /\* Report unexpected child status \*/ | +| | +| } | +| | +| } else { | +| | +| /\* \... Initialize env as a sanitized copy of environ \... \*/ | +| | +| if (execve(\"/usr/bin/any_cmd\", args, env) == -1) { | +| | +| /\* Handle error \*/ | +| | +| \_Exit(127); | +| | +| } | +| | +| } | +| | +| } | ++-----------------------------------------------------------------------+ + +exec系列函数中的path、file参数禁止使用命令解析器(如/bin/sh)。 + ++-----------------------------------------------------------------------+ +| 1\. int execl(const char \*path, const char \*arg, \...); | +| | +| 2\. int execlp(const char \*file, const char \*arg, \...); | +| | +| 3\. int execle(const char \*path, const char \*arg,\..., char \* | +| const envp\[\]); | +| | +| 4\. int execv(const char \*path, char \*const argv\[\]); | +| | +| 5\. int execvp(const char \*file, char \*const argv\[\]); | ++-----------------------------------------------------------------------+ + +例如,禁止如下使用方式: + + ----------------------------------------------------------------------- + execl(\"/bin/sh\", \"sh\", \"-c\", CMD, (VOS_CHAR \*) 0); + + ----------------------------------------------------------------------- + +3) 风险评估 + +如果传递给system()、popen()或调用命令处理器的其他函数的命令字符串未完全清理,则被利用的风险很高。在最坏的情况下,攻击者以脆弱进程的权限执行任意系统命令。 + +等级:L1 + +4) 相关指南 + ++-----------------------------------+-----------------------------------+ +| MITRE CWE | CWE | +| | -78,操作系统命令中使用的特殊元素 | +| | 的不正确处理(操作系统命令注入) | +| | | +| | CWE-88,参数注入或修改 | ++-----------------------------------+-----------------------------------+ +| CERT.ENV33-C | Do not call system() | ++-----------------------------------+-----------------------------------+ + +# 杂项 + +## 规则7.1 不要使用已弃用或过时的函数 {#规则7.1-不要使用已弃用或过时的函数 .list-paragraph} + +请勿使用已弃用或过时的函数。已弃用的函数由《C语言标准》定义,过时的函数由该规范定义。 + +**已弃用的函数** + +《C11标准》弃用了gets()函数。推荐的替代函数是《C11标准》附件K给出的gets_s()。 + +**过时的函数** + +在本规范中,下表第一列中的函数被定义为过时函数。为了修复对过时函数的调用,程序可以使用在所有方面都符合本规范的替代库或函数。 + + ------------------------------ ---------------------------------------- + 过时的函数 推荐的替代函数 + + asctime() asctime_s() + + atof() strtod() + + atoi() strtol() + + atol() strtol() + + atoll() strtoll() + + ctime() ctime_s() + + fopen() fopen_s() + + freopen() freopen_s() + + rewind() fseek() + + setbuf() setvbuf() + ------------------------------ ---------------------------------------- + +**未经检查的过时函数** + +如果使用支持《C11标准》附件K的平台,则下表第一列中的函数被定义为过时函数,第二列中的函数是附件K中的推荐替代项。 + + --------------------------------- ------------------------------------- + 过时的函数 推荐的替代函数 + + bsearch() bsearch_s() + + fprintf() fprintf_s() + + fscanf() fscanf_s() + + fwprintf() fwprintf_s() + + fwscanf() fwscanf_s() + + getenv() getenv_s() + + gmtime() gmtime_s() + + localtime() localtime_s() + + mbsrtowcs() mbsrtowcs_s() + + mbstowcs() mbstowcs_s() + + memcpy() memcpy_s() + + memmove() memmove_s() + + printf() printf_s() + + qsort() qsort_s() + + scanf() scanf_s() + + snprintf() snprintf_s() + + sprintf() sprintf_s() + + sscanf() sscanf_s() + + strcat() strcat_s() + + strcpy() strcpy_s() + + strerror() strerror_s() + + strlen() strnlen_s() + + strncat() strncat_s() + + strncpy() strncpy_s() + + strtok() strtok_s() + + swprintf() swprintf_s() + + swscanf() swscanf_s() + + vfprintf() vfprintf_s() + + vfscanf() vfscanf_s() + + vfwprintf() vfwprintf_s() + + vfwscanf() vfwscanf_s() + + vprintf() vprintf_s() + + vscanf() vscanf_s() + + vsnprintf() vsnprintf_s() + + vsprintf() vsprintf_s() + + vsscanf() vsscanf_s() + + vswprintf() vswprintf_s() + + vswscanf() vswscanf_s() + + vwprintf() vwprintf_s() + + vwscanf() vwscanf_s() + + wcrtomb() wcrtomb_s() + + wcscat() wcscat_s() + + wcscpy() wcscpy_s() + + wcslen() wcsnlen_s() + + wcsncat() wcsncat_s() + + wcsncpy() wcsncpy_s() + + wcsrtombs() wcsrtombs_s() + + wcstok() wcstok_s() + + wcstombs() wcstombs_s() + + wctomb() wctomb_s() + + wmemcpy() wmemcpy_s() + + wmemmove() wmemmove_s() + + wprintf() wprintf_s() + + wscanf() wscanf_s() + --------------------------------- ------------------------------------- + +1) 不合规代码 + + 不合规代码使用了过时的函数strcat()和strcpy(): + ++-----------------------------------------------------------------------+ +| #include \ | +| | +| #include \ | +| | +| enum { BUFSIZE = 32 }; | +| | +| void complain(const char \*msg) { | +| | +| static const char prefix\[\] = \"Error: \"; | +| | +| static const char suffix\[\] = \"\\n\"; | +| | +| char buf\[BUFSIZE\]; | +| | +| strcpy(buf, prefix); | +| | +| strcat(buf, msg); | +| | +| strcat(buf, suffix); | +| | +| fputs(buf, stderr); | +| | +| } | ++-----------------------------------------------------------------------+ + +2) 合规代码 + + 在合规代码中,过时的函数strcat()和strcpy()分别被替换为strcat_s()和strcpy_s(): + ++-----------------------------------------------------------------------+ +| #define \_\_STDC_WANT_LIB_EXT1\_\_ | +| | +| #include \ | +| | +| #include \ | +| | +| enum { BUFFERSIZE = 256 }; | +| | +| void complain(const char \*msg) { | +| | +| static const char prefix\[\] = \"Error: \"; | +| | +| static const char suffix\[\] = \"\\n\"; | +| | +| char buf\[BUFFERSIZE\]; | +| | +| strcpy_s(buf, BUFFERSIZE, prefix); | +| | +| strcat_s(buf, BUFFERSIZE, msg); | +| | +| strcat_s(buf, BUFFERSIZE, suffix); | +| | +| fputs(buf, stderr); | +| | +| } | ++-----------------------------------------------------------------------+ + +3) 风险评估 + +已弃用和过时的函数通常与软件漏洞相关联。 + +等级:L1 + +4) 相关指南 + ++-----------------------------------+-----------------------------------+ +| MITRE CWE | CWE-20,输入验证不足 | +| | | +| | CWE-73,文件名或路径的外部控制 | +| | | +| | CWE-79,网页生成期 | +| | 间输入的不正确中和(跨站点脚本) | +| | | +| | CWE-89,SQL注入 | +| | | +| | CWE-91,XML注入 | +| | | +| | CWE | +| | -94,代码生成控制不当(代码注入) | +| | | +| | CWE-114,过程控制 | +| | | +| | CWE-120,缓冲区复 | +| | 制没有检查输入大小(缓冲区溢出) | +| | | +| | CWE-192,整数强制错误 | +| | | +| | CWE-197,数字截断错误 | +| | | +| | CW | +| | E-367,检查时间,使用时间竞争条件 | +| | | +| | CWE-464,添加数据结构哨兵 | +| | | +| | C | +| | WE-601,URL重定向到不受信任的站点 | +| | | +| | CWE-676,使用潜在危险功能 | ++-----------------------------------+-----------------------------------+ +| CERT.MSC24-C | Do not use deprecated or | +| | obsolescent functions | ++-----------------------------------+-----------------------------------+ +| MISRA Rule 21.3 | The memory allocation and | +| | deallocation functions of | +| | \ | +| | | +| | shall not be used | ++-----------------------------------+-----------------------------------+ + +8. # 代码规范工具 + + 1. ## 待定 + +待定