编码安全规范V1.0拟制:安全中心关键字:安全, 编码规范内容范畴:信息安全文档类别:开发技术文档保密级别:保密文件名:编码安全规范.doc 范围:全体员工版本: 1.0文档历史第一篇防止堆栈溢出类漏洞 (4)1.1对任何用户输入数据必须首先校验其长度,避免由于长度越界引起的缓冲区溢出。
(4)1.2C++和MFC程序字符串处理,选择现有的处理类库,禁止自己编写类库。
(4)1.3编码中禁止使用危险函数。
(4)1.4Unicode和ANSI缓冲区大小不匹配问题,必须注意大小计算的单位。
(5)1.5不将用户输入串拼接到任何格式字符串内。
避免字符格式化漏洞。
(6)1.6多个字符串存储在一个数据区时,尽量不依靠分隔符区分边界。
用户数据需要转义后传输,存储。
(7)1.7 C\C++中数组大小应该是sizeof(pArray)/sizof(pArray[0]) (7)1.8其他可能出现缓冲区溢出的函数 (7)第二篇防止SQL恶意构造性漏洞 (8)2.1 防止SQL恶意构造漏洞。
不直接使用外部输入的数字、字符串拼接SQL语句。
(8)2.2 web编程对于用户的任何输入必须做关键字过滤 (9)第三篇防止目录,文件名恶意构造性漏洞 (9)3.1必须:禁止使用外部输入字串作为下列函数的参数的一部分, 确保用户不能欺骗系统从而执行任意命令。
如果必须传递参数,从数据库、文件、管道、套接字等IPC通信方式传递。
(9)3.4验证所有可能的数据,甚至包括数据库中的数据,本地文件。
(10)3.5不将用户输入串直接加入html文件、js脚本、xml文件、配置文件、模板文件。
(10)3.6 避免使用有安全风险的windows API。
(10)第四篇防止内存堆溢出漏洞 (11)4.1分配内存,要判断返回值。
(11)4.2内存操作,特别是内存拷贝,必须检查长度是否超出分配内存的大小 (11)4.3对于无效指针,一定要置NULL,同时数组不要保存无效指针 (12)4.4时刻注意表达式是否会上溢、下溢 (13)4.5过程/函数中分配的资源(包括内存、文件等),在过程/函数退出之前要释放。
(13)4.6 MFC中使用CArray删除数据,需要倒后遍历. (13)第五篇其他一些注意事项 (14)5.1检查所有与安全相关的函数的返回值 (14)5.2调用可能被预测的函数前,引入随机量 (14)5.3 在代码中添加安全性注释 (15)关键词:摘要:为了提高公司软件安全质量,公司对安全编程作出统一的规范约束。
本规范由安全中心负责维护更新。
本规范是一个最初级的基本规范。
所有的开发者均应熟练掌握。
本规范的示例多以C\C++为背景。
缩略语清单:必须:强制必须遵守的原则。
建议:可以加以考虑的原则。
禁止:必须加以避免的原则。
示例:对此规则或建议从正、反两个方面给出例子。
本规范从属于编码层面,不包含应用安全架构设计,不包含应用安全部署以及应用安全运营等方面的内容。
开发者除了本规范以外,还必须熟悉App设计方面的安全规范,协议接口设计规范,熟悉部署层面安全规范,以及熟悉运营层面的安全规范。
在编码层面,我们主要关心以下内容:(1) 防止堆栈溢出类漏洞(*) 防止缓冲区溢出漏洞(2) 防止恶意SQL构造性漏洞(3) 防止文件名,路径恶意构造漏洞(4) 防止内存堆溢出类漏洞,防止进程Core Dump 的漏洞第一篇防止堆栈溢出类漏洞1.1对任何用户输入数据必须首先校验其长度,避免由于长度越界引起的缓冲区溢出。
字符串长度计算。
尽量使用单独保存的长度变量或read等输入函数返回的长度来计算字符串,不能完全相信strlen()。
示例:main(int argc, char *argv[]){char buff[128]={0} ;strcpy(buff,argv[1])//可能溢出}1.2C++和MFC程序字符串处理,选择现有的处理类库,禁止自己编写类库。
建议:使用MFC 的Cstring 类、A TL 的CComBSTR 类或者STL 的string 类等等。
1.3编码中禁止使用危险函数。
禁止:\tcodescan\index.html建议:对于Windows Client Side 的代码,建议使用microsoft SDK中的strsafe.h提供的字符串安全函数,使用手册可以参考:/library/default.asp?url=/librar y/en-us/winui/winui/windowsuserinterface/resources/string s/usingstrsafefunctions.asp1.4Unicode和ANSI缓冲区大小不匹配问题,必须注意大小计算的单位。
Windows系列操作系统中,一般同时支持,但Unicode函数按宽字符(2个字节)计算大小,而不是按单字符(1个字节)计算大小。
示例:BOOL GetName(char *szName){WCHAR wszUserName [256 ]; //将ANSI名称转换到Unicode.MultiByteToWideChar(CP_ACP,0, szName, -1, wszUserName, sizeof(wszUserName));}WszUserName是一个Unicode字串、256个宽字符。
宽字符具有两个字节,因此实际上sizeof(wszUserName)是512字节。
以下是这个函数的正确写法:MultiByteToWideChar(CP_ACP,0, szName, -1, wszUserName, sizeof(wszUserName)/sizeof(wszUserName [0 ]));可能出现问题的函数还有:MultiWideToByteChar1.5不将用户输入串拼接到任何格式字符串内。
避免字符格式化漏洞。
可能用到格式字符串的函数如下:scanf(),fscanf(),sscanf(),vscanf(),vsscanf(),vfscanf(),printf(),fprintf(),sprintf(),vprintf(),vfprintf(),vsprintf(),syslog(),vsyslog(),err(),errx(),warn(),warnx(),verr(),verrx(),vwarn(),vwarnx(),setproctitle() (BSD系统与某些linux系统)示例:#include <stdio.h>int main(int argc, char *argv[]){char buffer[512]="";strncpy(buffer,argv[1],500);printf(buffer);//非安全编程实践:格式控制串由外部提供,输入//%.622496x%.622496x%n类似的东西就会发生格式化漏洞return 0;}常见错误:printf("%s %d %d %d\n",buf,i,j); 个数不匹配sprintf(buff,fmt,ap);//当fmt为用户输入时1.6多个字符串存储在一个数据区时,尽量不依靠分隔符区分边界。
用户数据需要转义后传输,存储。
建议:在数据设计的时候,避免使用| / \ $ ,;:— + !\0等符号做多个字符串分隔符,目前较为安全可靠的办法是通过字符串长度来决定字符串的边界。
示例:char string[] = "user input:A string\tof ,,tokens\nand some more tokens";char seps[] = " ,\t\n";//这些分割符是不可靠的char *token;void main( void ){printf( "%s\n\nTokens:\n", string );/* Establish string and get the first token: */token = strtok( string, seps );while( token != NULL ){/* While there are tokens in "string" */printf( " %s\n", token );/* Get next token: */token = strtok( NULL, seps );}}1.7 C\C++中数组大小应该是sizeof(pArray)/sizof(pArray[0])示例:int pArray[10];//数组大小应该是sizeof(pArray)/sizeof (pArray[0]),以下访问越界for( int i=0; i<sizeof(pArray); i++)pArray[i] = 123;1.8其他可能出现缓冲区溢出的函数realpath()getopt()getpass()streadd()strecpy()strtrns()getwd()对这类函数的参数应该小心处理int main (int argc, char **argv){int oc;char *b_opt_arg;while((oc = getopt(argc, argv, "ngl:")) != -1){switch(oc){case 'n':printf("My name is Lyong.\n");break;case 'g':printf("Her name is Xxiong.\n");break;case 'l':b_opt_arg = optarg;printf("Our love is %s\n", optarg);break;}}return 0;}第二篇防止SQL恶意构造性漏洞本段落的编码规范,主要是防止恶意的SQL构造漏洞。
除了这个编码的规范以外,还必须在Database的访问模式上,采用更为安全的应用接口封装的模式。
在接入层,比如CGI等,严禁使用SQL-Client 来访问Database。
所有的Database接口必须封装在APP-Interface中。
详见《接入层安全规范》以及《DB层安全规范》。
2.1 防止SQL恶意构造漏洞。
不直接使用外部输入的数字、字符串拼接SQL语句。
数字串:应首先判断每个单字符的合法性,再将数字串转化为数字,最后应校验数字范围合法性。
不能直接调用atoi()。