Tencent编码安全规范_第1页
Tencent编码安全规范_第2页
Tencent编码安全规范_第3页
Tencent编码安全规范_第4页
Tencent编码安全规范_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

编码安全规范 V1.0 拟 制:安全中心关键字:安全, 编码规范内容范畴:信息安全文档类别:开发技术文档保密级别:保密文件名:编码安全规范.doc范围:全体员工 版本:1.0文档历史日期作者版本号备注wolfliuV0.1applelinV0.22007-02-19Tony, CoolcyangV0.3 分割了一下原来的V0.2的文档,抽出一个单列的格式,以便后续修改。2007-2-28applelinV0.4根据新的格式整理并补充2007-3-8stevezhengV0.52007-3-12Dum applelinV0.6补充示例第一篇 防止堆栈溢出类漏洞51.1对任何用户输入数据必须首先校验其长度,避免由于长度越界引起的缓冲区溢出。51.2C和MFC程序字符串处理,选择现有的处理类库,禁止自己编写类库。51.3编码中禁止使用危险函数。51.4Unicode和ANSI缓冲区大小不匹配问题,必须注意大小计算的单位。61.5不将用户输入串拼接到任何格式字符串内。避免字符格式化漏洞。71.6多个字符串存储在一个数据区时,尽量不依靠分隔符区分边界。用户数据需要转义后传输,存储。81.7 CC+中数组大小应该是sizeof(pArray)/sizof(pArray0)81.8其他可能出现缓冲区溢出的函数8第二篇 防止SQL恶意构造性漏洞92.1 防止SQL恶意构造漏洞。 不直接使用外部输入的数字、字符串拼接SQL语句。92.2 web编程对于用户的任何输入必须做关键字过滤10第三篇 防止目录,文件名恶意构造性漏洞103.1必须:禁止使用外部输入字串作为下列函数的参数的一部分, 确保用户不能欺骗系统从而执行任意命令。如果必须传递参数,从数据库、文件、管道、套接字等IPC通信方式传递。103.4验证所有可能的数据,甚至包括数据库中的数据,本地文件。113.5不将用户输入串直接加入html文件、js脚本、xml文件、配置文件、模板文件。123.6 避免使用有安全风险的windows API。12第四篇 防止内存堆溢出漏洞134.1分配内存,要判断返回值。134.2内存操作,特别是内存拷贝,必须检查长度是否超出分配内存的大小134.3对于无效指针,一定要置NULL,同时数组不要保存无效指针144.4时刻注意表达式是否会上溢、下溢144.5过程/函数中分配的资源(包括内存、文件等),在过程/函数退出之前要释放。154.6 MFC中使用CArray删除数据,需要倒后遍历.15第五篇 其他一些注意事项155.1检查所有与安全相关的函数的返回值155.2调用可能被预测的函数前,引入随机量165.3 在代码中添加安全性注释16关键词:摘 要:为了提高公司软件安全质量,公司对安全编程作出统一的规范约束。本规范由安全中心负责维护更新。本规范是一个最初级的基本规范。所有的开发者均应熟练掌握。本规范的示例多以CC+为背景。缩略语清单:必须:强制必须遵守的原则。建议:可以加以考虑的原则。禁止:必须加以避免的原则。 示例:对此规则或建议从正、反两个方面给出例子。本规范从属于编码层面,不包含应用安全架构设计,不包含应用安全部署以及应用安全运营等方面的内容。开发者除了本规范以外,还必须熟悉 App设计方面的安全规范,协议接口设计规范,熟悉部署层面安全规范,以及熟悉运营层面的安全规范。在编码层面,我们主要关心以下内容:(1)防止堆栈溢出类漏洞(*)防止缓冲区溢出漏洞(2)防止恶意SQL构造性漏洞(3)防止文件名,路径恶意构造漏洞(4) 防止内存堆溢出类漏洞,防止进程Core Dump 的漏洞第一篇 防止堆栈溢出类漏洞1.1对任何用户输入数据必须首先校验其长度,避免由于长度越界引起的缓冲区溢出。字符串长度计算。尽量使用单独保存的长度变量或read等输入函数返回的长度来计算字符串,不能完全相信strlen()。示例:main(int argc, char *argv)char buff128=0 ;strcpy(buff,argv1)/可能溢出1.2C和MFC程序字符串处理,选择现有的处理类库,禁止自己编写类库。建议:使用MFC 的Cstring 类、ATL 的CComBSTR 类 或者STL 的string 类等等。1.3编码中禁止使用危险函数。禁止: 禁止使用替换函数strcpy, wcscpy, lstrcpy, strcpy, _tcscpy, _ftcscpy,_mbscpystrncpy,wcsncpy,lstrcpyn,_tcsncpy,_ftcsncpy,_mbsncpystrcat, wcscat, lstrcat, strcat, _tcscat, _ftcscat,_mbscatstrncatvsprintf, vswprintf, wvsprintf, wvnsprintf, _vstprintf_vsnprintf, _vsnwprintf, _vsntprintfsprintf, swprintf, wsprintf, wnsprintf, _stprintf_snprintf, _snwprintf, _sntprintfgets, _getws, _gettsfgetws fgets可以使用安全中心提供危险函数扫描工具:tcodescanindex.html建议:对于Windows Client Side 的代码, 建议使用microsoft SDK中的strsafe.h提供的字符串安全函数 ,使用手册可以参考:/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/resources/strings/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 int main(int argc, char *argv)char buffer512=;strncpy(buffer,argv1,500);printf(buffer); /非安全编程实践:格式控制串由外部提供, 输入 /%.622496x%.622496x%n类似的东西就会发生格式化漏洞return 0;常见错误:printf(%s %d %d %dn,buf,i,j); 个数不匹配sprintf(buff,fmt,ap);/当fmt为用户输入时1.6多个字符串存储在一个数据区时,尽量不依靠分隔符区分边界。用户数据需要转义后传输,存储。建议:在数据设计的时候,避免使用 | / $ , ; : + !0等符号做多个字符串分隔符,目前较为安全可靠的办法是通过字符串长度来决定字符串的边界。示例:char string = user input:A stringtof ,tokensnand some more tokens;char seps = ,tn;/这些分割符是不可靠的char *token;void main( void ) printf( %snnTokens:n, string ); /* Establish string and get the first token: */ token = strtok( string, seps ); while( token != NULL ) /* While there are tokens in string */ printf( %sn, token ); /* Get next token: */ token = strtok( NULL, seps ); 1.7 CC+中数组大小应该是sizeof(pArray)/sizof(pArray0)示例:int pArray10;/数组大小应该是sizeof(pArray)/sizeof (pArray0),以下访问越界for( int i=0; isizeof(pArray); i+)pArrayi = 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 %sn, optarg); break; return 0;第二篇 防止SQL恶意构造性漏洞本段落的编码规范,主要是防止恶意的SQL构造漏洞。除了这个编码的规范以外,还必须在Database的访问模式上,采用更为安全的应用接口封装的模式。 在接入层,比如CGI等,严禁使用SQL-Client 来访问Database。所有的Database接口必须封装在 APP-Interface中。详见 接入层安全规范 以及 DB层安全规范。2.1 防止SQL恶意构造漏洞。 不直接使用外部输入的数字、字符串拼接SQL语句。数字串:应首先判断每个单字符的合法性,再将数字串转化为数字,最后应校验数字范围合法性。不能直接调用atoi()。字母串:应先保证每个字符必须在规定的范围内,比如大小写字母、下划线等。建议使用正则表达式做有效性校验。必须:拼接SQL语句前字符串必须经过转义。混合串:应严格限制非字母数字符号以及不可显示符号的使用。建议使用正则表达式做有效性校验如不能避免,必须:拼接SQL语句前字符串必须经过转义。mysql 转义函数mysql_escape_string()mysql_real_escape_string()2.2 web编程对于用户的任何输入必须做关键字过滤详见 CGI安全规范 中的HTML字符控制规范第三篇 防止目录,文件名恶意构造性漏洞在ClientSide 的应用中,当需要进行目录访问,文件存取的时候,比较容易出现参数检查不严格,出现被恶意构造的安全漏洞。3.1必须:禁止使用外部输入字串作为下列函数的参数的一部分。对于涉及文件名,或者目录名的参数,需要双重保障的代码。 Windows 中文件类函数CreateDirectory, CreateDirectoryEx DeleteFile CreateFile OpenFile MoveFileMFC:Cfile 进程类函数 ShellExecute ShellExecuteEx CreateProcess WinExec CreateProcessAsUser CreateProcessWithLogonWLinux中execl()execlp()execle()execv()execvp()system()popen()access()函数应严格限制相关路径上的目录的权限。fchown()替代chown()fchgrp()替代chgrp()fchmod()替代chmod()vfork()、tmpfile()在某些系统上有问题,尽量使用fork()、clone()tmpnam()、tempnam()、mktemp()PHP中system()使用 escapeshellarg() 或 escapeshellcmd()来传递参数popen()使用 escapeshellarg() 或 escapeshellcmd()来传递参数exec()使用 escapeshellarg() 或 escapeshellcmd() 来传递参数passthru()使用 escapeshellarg() 或 escapeshellcmd() 来传递参数proc_open()使用 escapeshellarg() 或 escapeshellcmd() 来传递参数应使用内部自行生成的递增递减数字串、时间串或者字母串做文件名路径名。如实在无法避免,应严格验证字符的有效性。路径字符串内绝对禁止出现 . 符号 ,绝对禁止以 / 或者 / 开头。禁止出现任何非字母数字下划线的字符,尤其是不可显示字符。最后应检验路径是否在规定的路径之下,禁止跳出范围访问。尽量避免使用符号链接。示例:一个可被恶意构造字符串的Client的例子,CString strFileName = “.autoexec.bat”;CString strFilePath = “C:Program filetencent” + strFileName;CFile file;if( file.Open(strFilePath,CFile:modeCreate|CFile:modeWrite|CFile:typeBinary) )file.Write(pszFileData,nFileLength);file.Close();后果: 1恶意者可能通过构造恶意文件路径,修改任何系统文件,移植木马。3.2验证所有可能的数据,甚至包括数据库中的数据,本地文件。不能完全信任本地文件、数据库数据,这些文件很可能是由用户输入间接转化过来的,因次使用这些输入数据时,必须校验其有效性。示例:getenv()不可信。3.3不将用户输入串直接加入html文件、js脚本、xml文件、配置文件、模板文件。应首先验证每个字符必须在可控的范围内,在有可能执行的位置,必须严格过滤各种可执行的组合。在使用key-value对时(例如配置文件中),应禁止使用用户输入的数据做key。应尽量禁止使用多个value(为了避免使用字符串分隔符的情况)。3.4 避免使用有安全风险的windows API。CreateProcess、CreateProcessAsUser、CreateProcessWithLogonW、WinExec 等函数参数中的可执行程序的名称必须是第一个用空格分隔的字符串。但是,如果可执行程序的名称或路径名中有空格,则存在一定的风险,因为如果空格处理不当,就可能会运行恶意的可执行程序。以下示例是危险的,因为该进程将试图运行“Program.exe”(如果该程序存在),而不是“foo.exe”。示例:CreateProcess(NULL, C:Program Filesfoo, .) 如果恶意用户要在系统中创建名为“Program.exe”的特洛伊程序,那么任何使用“Program Files”目录不正确地调用 CreateProcess 的程序都将启动特洛伊程序,而不是要调用的应用程序。注意不要传递 NULL,以避免函数根据其运行时参数来分析并确定可执行文件路径名。否则,如果参数 lpApplicationName 为 NULL,则用引号将 参数lpCommandLine 中的可执行路径引起。示例:CreateProcess(NULL, C:Program Filesfoo.exe -L -S, .) WinExec(C:Program Filesfoo.exe -L -S, .)SetSecurityDescriptorDacl最好不要创建具有 NULL DACL 的安全描述符(即:pDacl 为 NULL),因为这样的 DACL 无法为对象提供安全性。实际上,攻击者可在对象上设置一个 Everyone (Deny All Access) ACE,从而拒绝每个人(包括管理员)访问该对象。NULL DACL 没有为对象提供任何免受攻击的保护。示例:SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);会导致编译器警告:c:CodetestDACLtestDACL.cpp(21) : warning C6248: Setting a SECURITY_DESCRIPTORs DACL to NULL will result in an unprotected object第四篇 防止内存堆溢出漏洞4.1分配内存,要判断返回值。 调用malloc等函数前,要预先计算好大小,并检查大小是否在可接受范围内。调用结束要检查函数返回值是否可用。4.2内存操作,特别是内存拷贝,必须检查长度是否超出分配内存的大小内存操作主要是指对数组、指针、内存地址等的操作。内存操作越界是软件系统主要错误之一,后果往往非常严重,所以当我们进行这些操作时一定要仔细小心。示例:假设某软件系统最多可由10个用户同时使用,用户号为1-10,那么如下程序存在问题。#define MAX_USR_NUM 10unsigned char usr_login_flgMAX_USR_NUM= ;void set_usr_login_flg( unsigned char usr_no ) if (!usr_login_flgusr_no) usr_login_flgusr_no= TRUE; 当usr_no为10时,将使用usr_login_flg越界。可采用如下方式解决。void set_usr_login_flg( unsigned char usr_no ) if (!usr_login_flgusr_no - 1) usr_login_flgusr_no - 1= TRUE; 示例:BYTE* p1 = new BYTE10;Memcpy(p1,p2,20);/拷贝内存越界4.3对于无效指针,一定要置NULL,同时数组不要保存无效指针错误示例:CObject* pObject = new CObject;CArray arrObject;arrObject.Add(pObject);Delete pObject;For (int i=0; iSave();建议:1对象销毁后,把指针置NULL,可以防止出错。2数组内对象销毁,要把对象从数组移出,或者把指针置NULL。3使用NULL指针,可以很快的定位出错位置,但是使用已经销毁的对象指针,往往会把问题隐藏,导致一些不可定位的crash。4.4时刻注意表达式是否会上溢、下溢示例:如下程序将造成变量下溢。unsigned char size ;while (size- = 0) / 将出现下溢 . / program code当size等于0时,再减1不会小于0,而是0xFF,故程序是一个死循环。应如下修改。char size; / 从unsigned char 改为charwhile (size- = 0) . / program code4.5过程/函数中分配的资源(包括内存、文件等),在过程/函数退出之前要释放。4.6 MFC中使用CArray删除数据,需要倒后遍历.示例:CArray arrData;int nCount = arrData.GetSize();For( int i=0 ; i nCount; i+)arrData.RemoveAti;/这里访问越界第五篇 其他一些注意事项5.1检查所有与安全相关的函数的返回值 如果对安全相关函数的调用,因任何原因而失败,则不允许对客户端进行模拟。客户端请求将在进行调用的进程所在的安全环境中进行。如果进程作为高度特权化的帐户(如 LocalSystem)来运行,或作为管理组的成员来运行,则用户可能可以执行在其他情况下不允许进行的操作。所以,您务必要始终检查调用的返回值,如果该值未报出错误,则不要继续执行客户端请求。可能存在的问题的函数:RpcImpersonateClient ImpersonateNamedPipeClient SetThreatToken ImpersonateSelf CoImpersonateClient ImpersonateDdeClientWindow ImpersonateSecurityContext ImpersonateLoggedOnUser示例:RPC_STATUS status = RpcImpersonateClient(NULL); if ( status != RPC_S_OK ) IF_DBGPRINT( DBG_RPC, ( RpcImpersonateClient failed - error %dn, status ) ); return status; HANDLE hToken;DWORD dwError = OpenThreadToken( GetCurrentThread(),TOKEN_ALL_ACCESS, TRUE, &hToken); if(!dwError ) IF_DBGPRINT( DBG_RPC, ( OpenThreadToken failed - error %dn, dwError ) ); 调用RpcImpersonateClient()的代码,如果没有检查该函数调用是否成功了,判断其返回值是否为RPC_S_OK,后面的操作可能就执行不应该有的权限操作。5.2调用可能被预测的函数前,引入随机量必须:调用此类函数应首先引入随机量。直接调用可能会被预测,导致欺骗、暴力破解。drand48()erand48()jrand48()lcong48()lrand48()mrand48()nrand48()random()seed48()setstate()srand()strfry()#include ; #include ; main() int ram,i; srandom(int)time(0);/ 引入随机量for(i=5;i;0;i-) ram=random()%100000;/控制位数 printf(ram:%dn,ram); 5.3 在代码中添加安全性注释 安全注释可以节约大量别人阅读的时间,给代码审计提供帮助,降低日常运维修改的风险。如果你的代码有安全要求或执行了与安全有关的操作,必须在代码的相应位置注释示例: / SECURITY. 使用数据保护API存储口令 / SECURITY. 口信和附加的信息从GatherDetails()传递给我们 / SECURITY. pOut是一个从GatherDetails()传递给我们的指针 assert(pOut != NULL); if (pOut != NULL) DATA_BLOB blobPwd=cbPwd,szPwd; DATA_BLOB blobEntropy=cbEntropy,bEntropy; BOOL fRet = CryptProtectData(blobPwd, Lpassword, blobEntrpoy, NULL,NULL, CRYPTPROTECT_UI_FORBIDDEN, pOut); 附录:Security Recommendations for Design1. All functional and design specifications should contain a section describing impacts on security. 2. Security Architecture Documentation: A security architecture document minimally contains the following items:a. Attack Surface Measurement: After all design specifications are complete, teams should define and document what the default and maximum attack surface for the product will be. The magnitude of the attack surface is an indication of the products likelihood for being successfully attacked. Minimizing the attack surface will reduce the odds of a successful attack. Reviewing attack surface during design is strongly recommended. b. Product structure or layering: Software that exhibits a high degree of structure and well-defined dependencies among components is less likely to exhibit vulnerabilities than software with less structure. Ideally the software should be structured in a layered hierarchy so that higher components (layers) depend on services of lower, but lower layers never depend on higher. Developing layered designs of this sort is a difficult task, and may not be feasible with legacy or pre-existing software. However teams developing new products should consider layered designs and seek to achieve as high a degree of structure as possible.3. Minimize default attack surface/Enable Least Privilege:a. All feature specifications should consider whether the features should be enabled by default. Less frequently used features should be disabled. Careful consideration should be given to not enabling less frequently used functionality by default.b. If the product needs to create new user accounts, ensure they have the least privileges possible for the required function and that they also have strong passwords. c. Pay close attention to access control. Always run code with the least possible privilege. When code fails, instead of raising the privilege, find out why it failed and fix the problem. The higher the privilege demanded by any code, the more exposed it is to abuse. 4. Default installation is secure: For the functionality that is enabled by default and constitutes the attack surface, all exposed features should be carefully reviewed to ensure that no vulnerabilities exist.5. Defense in Depth: Begin considering “defense in depth.” The most exposed entry points should have multiple protection mechanisms to reduce the likelihood that remaining security vulnerabilities can be exploited successfully.6. If there are competitive products with similar functionality in the marketplace, it is helpful to review public sources of information for known vulnerabilities in competitive products and to analyze the vulnerabilities in order to determine if the same issues can exist in this product. If so, appropriate design considerations will enable the product to avoid the same mistakes.7. If the product is a new release of an existing product, it is helpful to examine past vulnerabilities in previous versions of the product and analyze their root causes. This analysis may uncover additional instances of the same classes of problems.8. Deprecate outdated functionality: If the product is a new release of an existing product, evaluate support for of older protocols, file formats and standards and strongly consider removing them in the new release. Older code written before security awareness was as prevalent almost always contains security vulnerabilities.9. All sample source code released with the product should be reviewed by the product team for security issues with the same level of scrutiny as object code released with the product.10. If the product is a new release of an existing product, migrating any possible legacy code from unmanaged code to managed code should be considered.11. For any new code developed, implement new code using managed code whenever possible. 12. When developing with managed code, take advantage of .NET security features:a. Refuse unneeded permissions.b. Request optional permissions.c. Be careful in your use of CodeAccessPermission Assert and LinkDemand. Use Assert in as small a window as possible.d. Disable tracing and debugging before deploying ASP.NET applications. 13. Watch for canonical representation issues: Hackers will try to force code into following a dangerous path or URL by hiding their intent in escaped characters or obscure conventions. Always design code to deal with full canonical representations and not act directly upon externally provided data. The canonical representation of something is the standard, most direct and least ambiguous way to represent it. 14. Remain informed on security issues in the industry. Attacks and threats are evolving constantly, so keeping up to date is critically important. Keep the product team informed about new threats and vulnerabilities.15. Ensure that everyone on your team knows about unsafe functions and coding patterns. Maintain a list of your codes vulnerabilities. Add the code patterns to PREfast so that others can use them. When new vulnerabilities are found, publish them to the whole team so that folks can find similar or related problems. Make security everyones business.16. Be careful with error messages. If sensitive information is displayed in the error message that

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论