ISMS代码编写安全管理规范V01.docx
《ISMS代码编写安全管理规范V01.docx》由会员分享,可在线阅读,更多相关《ISMS代码编写安全管理规范V01.docx(16页珍藏版)》请在冰点文库上搜索。
ISMS代码编写安全管理规范V01
*
主办部门:
系统运维部
执笔人:
审核人:
XXXXX
代码编写安全管理规范V0.1
XX-ISMS-SE-03001
2014年3月17日
[本文件中出现的任何文字叙述、文档格式、插图、照片、方法、过程等内容,除另有特别注明,版权均属XXXXX所有,受到有关产权及版权法保护。
任何个人、机构未经XXXXX的书面授权许可,不得以任何方式复制或引用本文件的任何片断。
]
文件版本信息
版本
日期
拟稿和修改
说明
V0.1
2014.3.17
拟稿
文件版本信息说明
记录本文件提交时当前有效的版本控制信息,当前版本文件有效期将在新版本文档生效时自动结束。
文件版本小于1.0时,表示该版本文件为草案,仅可作为参照资料之目的。
阅送范围
内部发送部门:
综合部、系统运维部、技术开发部
第一章总则
第一条为规范XXXXX应用系统开发应当遵循的应用安全标准,指导代码开发人员或安全检查人员进行代码安全开发的安全配置,以提高系统的安全防护能力,根据《金融行业信息系统信息安全等级保护实施指引》(JR/T0071—2012),结合XXXXX实际,制定本规定。
第二条本规范适用于所有信息系统业务系统开发项目。
第二章基本代码安全规范
第三条输入验证
(一)对函数入口参数的合法性和准确性进行检查;
(二)对输入数据、入口参数等进行边界检查;
(三)在B/S环境下,进行服务端的验证而不仅仅是客户端的验证(例如基于Javascript的验证)。
通过在客户端和服务器之间放置一个代理服务器,可以很容易绕过客户端验证。
有了代理服务器,攻击者可以在数据被客户端“验证”后修改数据(与“man-in-the-middle”攻击类似)。
(四)在实际的校验中,输入校验首先定义一个有效(可接受)的字符集,然后检查每个数据的字符是否在有效范围内。
如果输入中包含无效的字符,应用程序应该返回错误页面并说明输入中包含无效字符。
这样进行验证的原因是定义无效的字符集比较困难,并且一些不应该有效的字符通常不会被指出;
(五)边界检查(例如字符串的最大长度)应该在字符有效性检查以前进行。
边界分析可以防止大多数缓冲区溢出漏洞;
(六)从环境变量获得的数据也需要进行验证。
同时避免在环境变量中存放敏感数据(例如密码)。
某些Unix系统(例如FreeBSD)包含ps命令,可以让用户看到任何当前进程的环境变量,这常常会暴露保密性信息。
第四条SQL语句
(一)如果应用程序需要连接后端数据库,使用存储过程而不要在代码中使用SQL语句;
(二)使用程序以外的嵌入在代码中的SQL语句调用特别危险。
难以防止攻击者使用输入域或者配置文件(由应用程序载入)来执行嵌入式的SQL攻击。
当然,输入验证有助于缓解这种风险。
第五条注释代码
当应用程序在实际环境中开始应用时,应该删除所有的注释代码。
注释代码是用来调试或者测试的,它们不是最终应用程序的一部分。
无论如何应该在实际的环境中删除它们来避免意外的执行(一般注释标识被删除后就无法激活休眠的代码,但还是存在可能性的,所以强烈建议执行这项工作)。
第六条错误消息
所有为用户显示的错误信息都不应该暴露任何关于系统、网络或应用程序的敏感信息。
如果可能的话,最好使用包含编号的一般的错误信息,这种信息只有开发者和/或支持小组才能理解。
一般的错误信息的例子是“发生了错误(代码1234),请您与系统运维联系。
”
第七条URL内容
对于web应用,不要在URL上暴露任何重要信息,例如密码、服务器名称、IP地址或者文件系统路径(暴露了web服务器的目录结构)。
第八条设置PATH变量
设置PATH为一个已知的值,而不是仅仅使用启动时的缺省值。
攻击者可以在攻击应用程序时使用PATH变量,例如试图执行一个任意的程序。
这些也可以应用于大多数其他的语言。
第九条禁止使用XX和验证的代码。
第十条使用第三方代码,应对代码安全性进行评估和测试。
第十一条测试用的“后门”,应在发布版中去除。
第十二条规范代码的格式。
规范变量、函数的命名;规范程序的书写格式,确保程序的易读性。
第十三条对代码进行版本控制,确保代码的可用性。
第十四条防止程序员非授权修改代码,对代码的访问权限进行严格的权限控制。
禁止在程序中添加隐藏“恶意”的代码,防止与应用系统相关的程序员对系统的非授权修改。
第十五条应用系统不应在程序或进程中固化账户和口令。
第十六条系统应具备对口令猜测的防范机制和监控手段。
第十七条避免应用程序以错误的顺序运行,或者防止出现故障时,后续程序以不正常的流程运行。
第十八条采用正确的故障恢复程序,确保正确处理数据。
第十九条采取会话控制或批次控制,确保更新前后数据文件的一致性,例如:
检查操作前后文件打开和关闭的数目是否一致。
第二十条检查执行操作前后对象的差额是否正常,如:
句柄处理,堆栈等系统资源的占用与释放等。
第二十一条严格验证系统生成的数据。
第二十二条在网络传输过程中检查下载/上传的数据或软件的完整性。
第二十三条检查文件与记录是否被篡改。
例如通过计算哈希值(HASH)进行对比。
第三章代码安全漏洞防范要求
第二十四条缓冲区溢出安全
(一)所有的输入都必须进行正确的有效性检测;
(二)必须保证数组没有越界,增加数组操作函数的边界检查;
(三)安全地使用字符串处理函数,慎用那些有安全隐患的字符串处理函数;
(四)Format字符串的时候特别注意Unicode和ANSI的大小不一致的情况;
(五)注意字符串结束符的保护;
(六)仔细研究库函数内部的缓冲区分配,明确其限制。
不要使用realpath(),如果功能需要必须使用时,一定要检查试图规范化的路径的长度,确保其不长于MAXPATHLEN;
(七)时刻进行边界检查。
建议使用一些检查工具:
Purify、Stackguard等检查代码,保证没有缓冲区溢出的问题。
第二十五条格式化字符串安全
(一)使用固定的格式化字符串,或者来自可信源的格式化字符串;
(二)要检查并限定locale的请求为合法值;
(三)不要将用户输入直接作为格式化字符传给各是化函数。
第二十六条整数溢出安全
(一)对于涉及到内存分配大小的计算,要进行仔细检查,确保计算不会产生溢出;
(二)对于涉及到数组索引的计算,要进行仔细检查,确保计算不会产生溢出;
(三)要使用无符号整数表示数组偏移和内存分配大小。
第二十七条sql注入代码安全
(一)要检查输入的有效性和可信度;
(二)要使用参数化的查询、占位符、或者参数帮定来构造sql语句;
(三)要在程序之外存储数据库的连接信息,比如经过保护的配置文件或者windows注册表;
(四)即使使用的是存储过程,也不要使用字符串连接来构造sql语句;
(五)不要再存储过程内部使用字符串连接来构造sql语句;
(六)不要再存储过程内部执行不可新的参数;
(七)不要简单地双写单引号或者双引号;
(八)不要使用高权限账号连接数据库,比如sa或者root;
(九)不要在程序或者连接字符串中存储登录口令;
(十)不要在web根目录下存储数据库配置信息;
(十一)考虑从数据库中删除对所有用户自定义表的访问权限,同时只对存储过程授权,然后使用存储过程以及参数化的查询来构造查询字符串。
第二十八条命令注入代码安全
(一)在命令输入传递给命令处理程序之前要进行验证;
(二)如果输入验证失败,要安全地处理失败信息;
(三)不要向任何命令解释器传递未验证的输入信息,即使这些输入仅仅是数据信息;
(四)避免使用正则表达式来进行输入验证,而是手工去写一些简单而又清晰的验证代码。
第二十九条异常处理代码安全
(一)要检测每个安全相关函数的返回值;
(二)对于每一个更改用户设定或者及其设定的函数,都要检查其返回值;
(三)要有从错误条件中进行恢复的考虑,避免拒绝服务攻击;
(四)逐个处理所有的异常,要将异常情况进行分类处理,避免在异常处理代码中的漏洞发生。
第三十条跨站脚本代码安全
(一)要对所有基于web的输入进行输入验证和可信度验证;
(二)在没有验证合法性之前,不要对基于web的输入进行回显;
(三)不要在cookie中存储敏感数据。
第三十一条保护网络流量的代码安全:
(一)使用强大的初始认证机制;
(二)对应用程序所产生的所有网络流量都要执行过程中消息认证;
(三)尽可能使用SSL/TLS进行网络加密传输。
第三十二条应用中的弱口令代码安全:
(一)确保口令在网络上认证时不被窃听;
(二)要在登录失败时给出错误提示,并记录失败口令尝试;
(三)尽可能使用基于hash强壮的单向加密函数来进行口令存储;
(四)为用户更改口令提供安全的机制;
(五)不要使用默认账号和默认口令对,若用了,必须在首次登录后进行修改;
(六)不在程序、后台存储明文的口令;
(七)口令要有一定的强度,应当参照系统的账号口令策略要求。
第四章SOCKET网络编程安全基本要素
第三十三条在socket函数调用时,明确参数中绑定的端口、IP地址和网卡接口。
Windows环境下,在遇到多个网卡的情况时,需要通过注册表来获得网卡接口和IP地址的信息,包括WindowsNT和windows2000。
第三十四条判断连接的合法身份。
即,为防止恶意的连接以及可能是无效的连接,建议在socket连接期间,判断连接的对端是否是合法的真正的连接。
第三十五条对于UDP连接,可以获得连接对方的IP地址和端口,从而可以判断对方的有效性和合法性;对于TCP连接,由于每次连接需要三次握手,而且还有超时机制,存在两种方式来控制。
第三十六条对于TCP连接,需要尽量在三次握手完成前完成判断,同时防止端口扫描的攻击。
第三十七条尽可能确保SOCKET应用能通过合理设置的防火墙。
第三十八条在可能的情况下,尽量减少socket连接数目。
第三十九条尽量不要使用回拨的技术。
第四十条尽量采用有连接状态的协议,例如TCP协议。
由于防火墙一般采取禁止一切的策略,对于UDP协议比较难以设置。
第四十一条在一个应用程序中,尽量使用同一种协议,不要使用多种协议。
第四十二条尽量将客户端和服务器端的端口做成可以配置,不要硬编码在程序中。
第五章Web编程安全基本要素
第四十三条输入检查
(一)限制用户输入HTML和Script(JavaScript、VBScript)代码。
即,输入恶意HTML或Script(JavaScript、VBScript)代码可能会对其他浏览者造成混淆、欺骗或恶意破坏的结果;
(二)检查用户输入数据的长度。
即输入超出限定长度的数据,可能造成服务器端程序溢出;
(三)防止用户输入特殊字符改变SQL语义。
即,输入含特殊字符的字串,篡改SQL语句的语义,可能造成SQL查询执行了不该执行的操作,以此绕过身份认证获取非法权限、甚至对数据进行破坏;
(四)限制用户能够访问的最顶层目录。
即,编写对服务器端文件、目录操作的程序时应该注意限定此类程序能够访问的最顶层目录,防止用户构造输入字串借助程序功能访问服务器关键文件导致泄漏服务器敏感信息;
(五)对所有类型的用户输入都要做检查,并严格限定什么是合法的用户输入,限定一个合法输入的范围,同时过滤有可能造成危险的特殊字符;
(六)对于从不可信任域发送到可信任域的数据一定要进行检查。
(七)尽可能在服务器端完成用户输入检查,不要轻易相信客户端脚本的检查结果。
即,虽然客户端的Script脚本也能完成一部分的用户输入检查功能,但这种检查的结果是不可信任的,攻击者可以自己制作表单程序绕过客户端脚本验证,将非法数据提交到服务器;
(八)在输入变为输出时,也要对特殊字符做检查和转换。
第四十四条敏感数据的存放和传递
(一)敏感数据不要存放在Web页中;
(二)不要把敏感的数据存储在cookie、隐藏字段或者潜在地可能会被用户修改的地方;
(三)客户端向服务器端提交敏感数据应该经过加密(例如使用SSL),尽量不要明文传输;
(四)密码等敏感信息存放在数据库中应该加密,并采用健壮的加密算法;
(五)防止数据库被攻破后泄漏用户密码。
第六章JAVA安全开发规范
第四十五条跨站脚本(XSS)
(一)跨站脚本是最普遍的web应用安全漏洞。
当应用程序在发送给浏览器的页面中包含用户提供的数据,但没有经过适当验证或转译那些内容,这就导致跨站脚本漏洞;
(二)攻击者能在受害者浏览器中执行脚本以劫持用户会话、迫害网站、插入恶意内容、重定向用户、使用恶意软件劫持用户浏览器等等;
(三)已知有三种著名跨站漏洞:
存储式、反射式和基于DOM;
(四)反射式跨站脚本通过测试或代码分析很容易找到。
第四十六条验证输入:
检查每个输入的有效性。
这可能意味着很多东西,但在典型的和简单的情况下,这意味着检查输入类型和数据的长度。
例如,如果你是从一个文本框接受一个标准的邮政编码,你会知道,唯一有效的类型是一个数字(0-9),而长度应该是6,不能多也不能少。
第四十七条编码输出:
(一)对验证输入的另一面就是编码输出;
(二)编码输出,是用来确保字符被视为数据,而不是作为HTML元字符被浏览器解析。
这些技术定义一些特殊的“转义”字符;没有正确转义的数据它仍然会在浏览器中正确解析;
(三)编码输出只是让浏览器知道数据是不是要被解析,达到攻击无法实现的目的;
(四)需要编码的部分:
HTML实体、HTML属性、JavaScript、CSS、URL。
第四十八条SQL注入:
(一)注入往往是应用程序缺少对输入进行安全性检查所引起的,攻击者把一些包含指令的数据发送给解释器,解释器会把收到的数据转换成指令执行,注入漏洞十分普遍,通常能在SQL查询、LDAP查询、Xpath查询、OS命令、程序参数等中出现;
(二)注入能导致数据丢失或数据破坏、缺乏可审计性或是拒绝服务。
注入漏洞有时甚至能导致完全接管主机;
(三)SQL注入包含了SQL注入、XPATH注入、LDAP注入、OS命令注入等。
第四十九条恶意文件执行:
(一)恶意文件执行是一种能够威胁任何网站形式的漏洞,只要攻击者在具有引入(include)功能程式的参数中修改参数内容,WEB服务器便会引入恶意程序内容从而受到恶意文件执行漏洞攻击;
(二)攻击者可利用恶意文件执行漏洞进行攻击取得WEB服务器控制权,进行不法利益或获取经济利益;
第五十条不安全的直接对象引用,即Insecuredirectobjectreferences,意指一个已经授权的用户,通过更改访问时的一个参数,从而访问到了原本其并没有得到授权的对象。
Web应用往往在生成Web页面时会用它的真实名字,且并不会对所有的目标对象访问时来检查用户权限,所以这就造成了不安全的对象直接引用的漏洞.
第五十一条跨站请求伪造,也被称成为“oneclickattack”或者sessionriding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。
尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。
XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。
与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
攻击者能让受害用户修改可以修改的任何数据,或者是执行允许使用的任何功能。
解决方法:
(一)新建CSRF令牌添加进用户每次登陆以及存储在httpsession里,这种令牌至少对每个用户会话来说应该是唯一的,或者是对每个请求是唯一的。
(二)令牌同样可以包含在URL中或作为一个URL参数标记/隐藏字段。
(三)在服务器端检查提交令牌与用户会话对象令牌是否匹配。
(四)在注销和会话超时,删除用户对象会话和会话销毁。
第五十二条信息泄露和错误处理不当
(一)应用程序常常产生错误信息并显示给使用者。
很多时候,这些错误信息是非常有用的攻击,因为它们揭示实施细则或有用的开发信息利用的漏洞;
(二)泄露太多的细节(如错误堆栈跟踪信息、SQL语句等等);
(三)登录失败后,通知用户是否用户ID或密码出错——登录失败可能是由于ID或密码错误造成的。
这为一个对关键资产发动蛮力攻击的攻击者提供重要信息;
第五十三条残缺的认证和会话管理
(一)与认证和会话管理相关的应用程序功能往往得不到正确实施,这就导致攻击者破坏密码、密匙、会话令牌或利用实施漏洞冒充其他用户身份;
(二)这些漏洞可能导致部分甚至全部账户遭受攻击。
一旦攻击成功,攻击者能执行合法用户的任何操作。
因此特权账户会造成更大的破坏;
(三)编程要求:
1.使用内置的会话管理功能;
2.通过认证的问候;
3.使用单一的入口点;
4.确保在一开始登录SSL保护的网页;
5.获取注销的权利;
6.添加超时;
7.确保你使用的是安全相关的功能;
8.使用强大的认证;
9.不进行默认身份验证。
第五十四条加密存储安全
(一)保护与加密敏感数据已经成为网络应用的最重要的组成部分。
简单不加密的敏感数据是非常普遍。
不加密的应用程序、设计不当往往含有密码,或者使用不恰当的密码或密码做出强烈的严重错误使用。
这些缺陷可以导致违反披露敏感数据的遵守;
(二)攻击者能够取得或是篡改机密的或是私有的信息;
(三)攻击者通过这些秘密的窃取从而进行进一步的攻击;
(四)造成企业形象破损,用户满意度下降,甚至会有法律诉讼等;
(五)编程要求:
1.验证你的结构
2.识别所有的敏感数据;
3.识别这些数据存放的所有位置;
4.确保所应用的威胁模型能够应付这些攻击;
5.使用加密手段来应对威胁
6.使用一定的机制来进行保护
7.文件加密;
8.数据库加密;
9.数据元素加密。
10.正确的使用这些机制
11.使用标准的强算法;
12.合理的生成,分发和保护密钥;
13.准备密钥的变更。
14.验证实现方法
15.确保使用了标准的强算法;
16.确保所有的证书、密钥和密码都得到了安全的存放;
17.有一个安全的密钥分发和应急处理的方案。
第五十五条通信安全
(一)对于不加密的应用程序的网络信息传输,需要保护敏感的通信。
加密(通常SSL)的,必须用于所有身份验证的连接,特别是通过Internet访问的网页,以及后端的连接。
否则,应用程序将暴露身份验证或会话令牌;
(二)攻击者能够取得或是篡改机密的或是私有的信息;
(三)攻击者通过这些秘密的窃取从而进行进一步的攻击;
(四)造成企业形象破损,用户满意度下降,甚至会有法律诉讼等;
(五)编程要求:
1.提供合理的保护机制;
2.对于敏感数据的传输,对所有连接都要使用TLS;
3.在传输前对单个数据都要进行加密(如XML-Encryption);
4.在传输前对信息进行签名(如XML-Signature);
5.正确的使用这些机制
6.使用标准的强算法;
7.合理管理密钥和证书;
8.在使用前验证SSL证书。
第五十六条限制URL访问失效
(一)常见的错误是,我们在用户认证后只显示给用户认证过的页面和菜单选项,而实际上这些仅仅是表示层的访问控制而不能真正生效,攻击者能够很容易的就伪造请求直接访问未被授权的页面;
(二)举个例子来说明这个过程:
1.攻击者发现他自己的访问地址为/user/getAccounts;
2.他修改目录为/admin/getAccounts或/manager/getAccounts;
3.这样攻击者就能够查看到更多的账户信息了。
(三)编程要求:
1.如果这个URL不是公开的,那么必须限制能够访问他的授权用户;
2.加强基于用户或角色的访问控制;
3.完全禁止访问未被授权的页面类型(如配置文件、日志文件、源文件等);
4.在每一个层次都使用简单肯定的模型;
5.确保每一层都有一个访问机制;
6.不要使用自动化的分析工具;
7.确保每个URL都被外部过滤器或其他机制保护;
8.确保服务器的配置不允许对非授权页面的访问。
第七章C/C++安全开发规范
第五十七条缓冲区溢出:
避免使用不执行边界检查的字符串函数,因为它们可能被用来进行缓冲区溢出攻击。
下面是应该避免使用的函数。
同时,也列出了每个函数相应的比较安全的替换方式。
(一)不使用strcpy(),使用strncpy()
(二)不使用strcat(),使用strncat()
(三)不使用sprintf(),使用snprintf()
(四)不使用gets(),使用fgets()
第五十八条格式化字符串攻击。
该类攻击往往与缓冲区溢出相关,因为它们往往主要利用了某些函数的假设,例如sprintf()和vsprintf()假设缓冲区的长度是无限的。
然而即使使用snprintf()替换sprintf()也无法完全保护程序不受格式化字符串的攻击。
这些攻击通过直接将格式说明符(formatspecifiers)(%d,%s,%n等)传递到输出函数接收缓冲区来进行。
例如,以下的代码就是不安全的:
snprintf(buffer,sizeof(buffer),string)。
第五十九条执行外部程序:
推荐使用exec()函数而不是system()函数来执行外部程序。
这是因为system()接收整个命令行的随机的缓冲区来执行程序。
第六十条竞争条件。
进程需要访问资源时(无论是磁盘、内存或是文件)通常需要执行两个步骤:
(一)首先测试资源是否空闲可用;
(二)如果可用,就访问该资源,否则它等到资源不再使用为止再去访问它。
第六十一条检验有效的返回值:
检验有效的返回值非常重要。
一个例子是旧的/bin/login的实现中不检验错误的返回值,导致当它找不到/etc/passwd文件时返回root的访问权限。
第七章附则
第六十二条本规定由网络与信息安全工作领导小组办公室负责制定、解释和更新。
第六十三条本规定自颁布之日起实行。