`
huangyongxing310
  • 浏览: 476275 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

安全编码规范

阅读更多
名词定义
规范化:将数据的各种编码方式和表式转换成为一种单一的简单形式。
跨站点请求伪造:一个外部网站或应用程序强迫一个客户端制作一个非意愿的请求到另一个有活跃会话的客户端应用程序。当它们使用已知的、可预见的 URL和参数时,并且当浏览器对每个发往应用程序的请求自动传输所有需要的会话信息时,应用程序是可被攻击的。
利用:使用一个漏洞。通常而言,这是一种有意的行为,旨在利用漏洞危及软件的安全控制。
危险字符:任何字符或编码表示的字符,可以影响应用程序预期的操作,或者被解释为具有特殊的意义、预期用途以外的字符。这些字符可用于:

修改现有代码或语句的结构;
插入新的非预期的代码;
修改路径;
程序功能或程序导致非预期的结果;
导致错误的条件;
下游应用程序或系统拥有上述任何效果。


流程描述
输入验证
在可信系统(比如:服务器)上执行所有的数据验证;
识别所有的数据源,并将其分为可信的和不可信的。验证所有来自不可信数据源(比如:数据库,文件流,等)的数据;
应当为应用程序应提供一个集中的输入验证规则;
为所有输入明确恰当的字符集,比如:UTF-8;
在输入验证前,将数据按照常用字符进行编码(规范化);
丢弃任何没有通过输入验证的数据;
确定系统是否支持 UTF-8扩展字符集,如果支持,在 UTF-8解码完成以后进行输入验证;
在处理以前,验证所有来自客户端的数据,包括:所有参数、URL、HTTP头信息(比如:cookie名字和数据值)。确定包括了来自JavaScript、Flash或其他嵌入代码的 post back信息;
验证在请求和响应的报头信息中只含有 ASCII字符;
核实来自重定向输入的数据(一个攻击者可能向重定向的目标直接提交恶意代码,从而避开应用程序逻辑以及在重定向前执行的任何验证);
验证正确的数据类型;
验证数据范围;
验证数据长度;
采用 白名单 形式,验证所有的输入;
如果任何潜在的危险字符必须被作为输入,确保执行了额外的控制,比如:输出编码、特定的安全 API、以及在应用程序中使用的原因。危险字符的例子包括:< > " ' % ( ) & + \ \' \"。
输出编码
在可信系统(比如:服务器)上执行所有的编码;
为每一种输出编码方法采用一个标准的、已通过测试的规则;
通过语义输出编码方式,对所有返回到客户端的来自于应用程序信任边界之外的数据进行编码。HTML实体编码是一个例子,但不是在所有的情况下都可用。
除非对目标编译器是安全的,否则请对所有字符进行编码。
针对SQL、XML和LDAP查询,语义净化所有不可信数据的输出。
对于操作系统命令,净化所有不可信数据输出。
身份验证和密码管理
除了那些特定设为公开的内容以外,对所有的网页和资源要求身份验证;
所有的身份验证过程必须在可信系统(比如:服务器)上执行;
建立并使用标准的、已通过测试的身份验证服务;
为所有身份验证控制使用一个集中实现的方法,其中包括利用库文件请求外部身份验证服务;
将身份验证逻辑从被请求的资源中隔离开,并使用重定向到或来自集中的身份验证控制;
所有的身份验证控制应当安全的处理未成功的身份验证;
所有的管理和账户管理功能至少应当具有和主要身份验证机制一样的安全性;
如果应用程序管理着凭证的存储,那么应当保证只保存了通过使用强加密单向 salted算法得到的密码,并且只有应用程序具有对保存密码和密钥的表/文件的写权限;
密码哈希必须在可信系统(比如:服务器)上执行;
只有当所有的数据输入以后,才进行身份验证数据的验证,特别是对连续身份验证机制;
身份验证的失败提示信息应当避免过于明确。比如:可以使用用户名和/或密码错误 ,而要使用 用户名错误或者密码错误;
为涉及敏感信息或功能的外部系统连接使用身份验证;
用于访问应用程序以外服务的身份验证凭据信息应当加密,并存储在一个可信系统(比如服务器)中受到保护的地方。源代码不是一个安全的地方;
只使用HTTP Post请求传输身份验证的凭据信息;
非临时密码只在加密连接中发送或作为加密的数据(比如,一封加密的邮件),通过邮件设临时密码可以是一个例外;
通过政策或规则加强密码复杂度的要求(比如:要求使用字母、数字和/或特殊符号);身份验证的凭据信息应当足够复杂以对抗在其所部署环境中的各种威胁攻击;
通过政策和规则加强密码长度要求。常用的是 8个字符长度,但是16个字符长度更好,或者考虑使用多单词密码短语;
输入的密码应当在用户的屏幕上模糊显示(比如:在 Web表单中使用 输入类型);
当连续多次登录失败后(比如:通常情况下是 5次),应强制锁定账户。账户锁定的时间必须足够长,以阻止暴力攻击猜测登录信息,但是不能长到允许执行一次拒绝服务攻击;
密码重设和更改操作需要类似于账户创建和身份验证的同样控制等级;
如果使用基于邮件的重设,只将临时链接或密码发送到预先注册的邮件地址;
临时密码和链接应当有一个短暂的有效期,例如5分钟;
当再次使用临时密码时,强制修改临时密码;
当密码重新设置时,使用邮件通知用户;
阻止密码重复使用;
密码在被更改前应当至少使用了一天,以阻止密码重用攻击;
根据政策或规则的要求,强制定期更改密码。关键系统可能会要求更频繁的更改。更改时间周期必须进行明确;
为密码填写框禁用记住密码功能;
用户账号的上一次使用信息(成功或失败)应当在下一次成功登录时向用户报告;
在执行关键操作以前,对用户再次进行身份验证;
为高度敏感或重要的交易账户使用多因子身份验证机制;
如果使用了第三 身份验证的代码,仔细检查代码以保证其不会受到任何恶意代码的影响。
会话管理
使用服务器或者框架的会话管理控制,应用程序应当只识别有效的会话标识符;
会话标识符必须总是在一个可信系统(比如:服务器)上创建;
会话管理控制应当使用通过审查的算法以保证足够的随机会话标识符;
为包含已验证的会话标识符的cookie设置域和路径,以为站点设置一个恰当的限制值;
注销功能应当完全终止相关的会话或连接;
注销功能应当可用于所有受身份验证保护的网页;
在平衡的风险和业务功能需求的基础上,设置一个尽量短的会话超时时间。通常情况下,应当不超过几个小时;
禁止连续的登录并强制执行周期性的会话终止,即使是活动的会话。特别是对于支持网络连接或连接到关键系统的应用程序。终止时机应当可以根据业务需求调整,并且用户应当收到足够的通知已减少带来的负面影响;
如果一个会话在登录以前就建立,在成功登录以后,关闭该会话并创建一个新的会话;
在任何重新身份验证过程中建立一个新的会话标识符;
不允许同一用户ID的并发登录;
不要在URL、错误信息或日志中暴露会话标识符,会话标识符应当只出现在 HTTP cookie头信息中。比如,不要将会话标识符以 GET参数进行传递;
通过在服务器上使用恰当的访问控制,保护服务器端会话数据免受来自服务器其他用户的未授权访问;
生成一个新的会话标识符并周期性地使旧会话标识符失效(这可以缓解那些原标识符被获得的特定会话劫持情况);
在身份验证的时候,如果连接从 HTTP变为 HTTPS,则生成一个新的会话标识符。在应用程序中,推荐持续使用 HTTPS,而非在 HTTP和HTTPS之间转换;
为服务器端的操作执行标准的会话管理,比如,通过在每个会话中使用强随机令牌或参数来管理账户,该方法可以用来防止跨站点请求伪造攻击;
通过在每个请求或每个会话中使用强随机令牌或参数,为高度敏感或关键的操作提供标准的会话管理;
为在TLS连接上传输的cookie设置安全属性;
将cookie设置为 HttpOnly属性,除非在应用程序中明确要求了客户端脚本程序读取或者设置cookie的值。
访问控制
只使用可信系统对象(比如:服务器端会话对象)以做出访问授权的决定;
使用一个单独的全站点部件以检查访问授权,这包括调用外部授权服务的库文件;
安全的处理访问控制失败的操作;
如果应用程序无法访问其安全配置信息,则拒绝所有的访问;
在每个请求中加强授权控制,包括:服务器端脚本产生的请求, 和来自象AJAX和
FLASH那样的富客户端技术的请求;
将有特权的逻辑从其他应用程序代码中隔离开;
限制只有授权的用户才能访问文件或其他资源,包括那些应用程序外部的直接控制;
限制只有授权的用户才能访问受保护的 URL;
限制只有授权的用户才能访问受保护的功能;
限制只有授权的用户才能访问直接对象引用;
限制只有授权的用户才能访问服务;
限制只有授权的用户才能访问应用程序数据;
限制通过使用访问控制来访问用户、数据属性和策略信息;
限制只有授权的用户才能访问与安全相关的配置信息;
服务器端执行的访问控制规则和表示层实施的访问控制规则必须匹配;
如果状态数据必须存储在客户端,使用加密算法,并在服务器端检查完整性以捕获状态的改变;
强制应用程序逻辑流程遵照业务规则;
限制单一用户或设备在一段时间内可以执行的事务数量,事务数量/时间应当高于实际的业务需求,但也应该足够低以判定自动化攻击;
仅使用 referer 头作为补偿性质的检查,它永远不能被单独用来进行身份验证检查,因为它可以被伪造;
如果长的身份验证会话被允许,周期性的重新验证用户的身份,以确保他们的权限没有改变。如果发生改变,注销该用户,并强制他们重新执行身份验证;
执行帐户审计并将没有使用的帐号强制失效(比如:在用户密码过期后的30天以内);
应用程序必须支持帐户失效,并在帐户停止使用时终止会话(比如:角色、职务状况、业务处理的改变等);
服务帐户,或连接到或来自外部系统的帐号,应当只有尽可能小的权限;
建立一个访问控制政策以明确一个应用程序的业务规则、数据类型和身份验证的标准或处理流程,确保访问可以被恰当的提供和控制。这包括了为数据和系统资源确定访问需求。
加密规范
所有用于保护来自应用程序用户秘密信息的加密功能都必须在一个可信系统(比如:服务器)上执行;
保护主要秘密信息免受未授权的访问;
安全的处理加密模块失败的操作;
为防范对随机数据的猜测攻击,应当使用加密模块中已验证的随机数生成器生成所有的随机数、随机文件名、随机 GUID和随机字符串;
建立并使用相关的政策和流程以实现加、解密的密钥管理。
错误处理和日志
不要在错误响应中泄露敏感信息,包括:系统的详细信息、会话标识符或者帐号信息;
使用错误处理以避免显示调试或堆栈跟踪信息;
使用通用的错误消息并使用定制的错误页面;
应用程序应当处理应用程序错误,并且不依赖服务器配置;
当错误条件发生时,适当的清空分配的内存;
在默认情况下,应当拒绝访问与安全控制相关联的错误处理逻辑;
所有的日志记录控制应当在可信系统(比如:服务器)上执行;
日志应记录用户登录的成功和失败操作;
日志应记录访问控制变更的成功和失败操作;
日志应记录用户写、更改和删除数据的成功和失败操作;
日志应记录账户创建、变更和删除的成功和失败操作;
日志应记录配置变更的成功和失败操作;
记录所有失败的输入验证;
记录明显的修改事件,包括对于状态数据非期待的修改;
记录连接无效或者已过期的会话令牌尝试;
记录所有的系统例外;
记录所有的管理功能行为,包括对于安全配置设置的更改;
记录所有失败的后端TLS链接;
记录加密模块的错误;
日志记录控制应当支持记录特定安全事件的成功或者失败操作;
确保日志记录包含了重要的日志事件数据;
确保日志记录中包含的不可信数据,不会在查看界面或者软件时以代码的形式被执行;
限制只有授权的个人才能访问日志;
为所有的日志记录采用一个主要的常规操作;
不要在日志中保存敏感信息,包括:不必要的系统详细信息、会话标识符或密码;
确保一个执行日志查询分析机制的存在;
使用加密哈希功能以验证日志记录的完整性。
数据保护
授予最低权限,以限制用户只能访问为完成任务所需要的功能、数据和系统信息;
保护所有存放在服务器上缓存的或临时拷贝的敏感数据,以避免非授权的访问,并在临时工作文件不再需要时被尽快清除;
即使在服务器端,仍然要加密存储的高度机密信息,比如,身份验证的验证数据。总是使用已经被很好验证过的算法;
保护服务器端的源代码不被用户下载;
不要在客户端上以明文形式或其他非加密安全模式保存密码、连接字符串或其他敏感信息;这包括嵌入在不安全的形式中:MS viewstate、Adobe flash 或者已编译的代码;
删除用户可访问产品中的注释,以防止泄露后台系统或者其他敏感信息;
删除不需要的应用程序和系统文档,因为这些也可能向攻击者泄露有用的信息;
不要在HTTP GET请求参数中包含敏感信息;
禁止表单中的自动填充功能,因为表单中可能包含敏感信息,包括身份验证信息;
禁止客户端缓存网页,因为可能包含敏感信息。 Control: no ,可以和 HTTP报头控制 - 一起使用,该控制不是非常有效,但是与 HTTP/1.0向后兼容;
应用程序应当支持,当数据不再需要的时候,删除敏感信息(比如:个人信息或者特定财务数据);
为存储在服务器中的敏感信息提供恰当的访问控制。这包括缓存的数据、临时文件以及只允许特定系统用户访问的数据。
通讯安全
为所有敏感信息采用加密传输。其中应该包括使用 TLS对连接的保护,以及支持对敏感文件或非基于HTTP连接的不连续加密;
TLS证书应当是有效的,有正确且未过期的域名,并且在需要时,可以和中间证书一起安装;
没有成功的TLS连接不应当后退成为一个不安全的连接;
为所有要求身份验证的访问内容和所有其他的敏感信息提供TLS连接;
为包含敏感信息或功能、且连接到外部系统的连接使用TLS;
使用配置合理的单一标准 TLS连接;
为所有的连接明确字符编码;
当链接到外部站点时,过滤来自 HTTP referrer 中包含敏感信息的参数。
系统配置
确保服务器、框架和系统部件采用了认可的最新版本;
确保服务器、框架和系统部件安装了当前使用版本的所有补丁;
关闭目录列表功能;
将Web服务器、进程和服务的账户限制为尽可能低的权限;
当例外发生时,安全的进行错误处理;
移除所有不需要的功能和文件;
在部署前,移除测试代码和产品不需要的功能;
通过将不进行对外检索的路径目录放在一个隔离的父目录里,以防止目录结构在robots.txt文档中暴露;然后,在 robots.txt文档中 禁止 整个父目录,而不是对每个单独目录的 禁止;
明确应用程序采用哪种 HTTP方法:GET或POST,以及是否需要在应用程序不同网页中以不同的方式进行处理;
禁用受限制的HTTP方法,例如WebDAV扩展(例如HTTP PUT、 DELETE以及TRACE方法等)。如果需要使用一个扩展的 HTTP方法以支持文件处理,则使用一个好的经过验证的身份验证机制;
避免不需要的HTTP方法,包括ACL, ARBITRARY, BASELINE-CONTROL, CHECKIN, CHECKOUT, CONNECT, COPY, INDEX, LABEL, LINK, LOCK, MERGE, MKACTIVITY, MKCOL, MKDIR, MKWORKSPACE, MOVE, OPTIONS, ORDERPATCH, PATCH, PROPFIND, PROPPATCH, REPORT, RMDIR, SEARCH, SHOWMETHOD, SPACEJUMP, TEXTSEARCH, TRACK, UNCHECKOUT, UNLINK, UNLOCK, UPDATE, and VERSION-CONTROL;
如果Web服务器支持 HTTP1.0和1.1,确保以相似的方式对它们进行配置,或者确保理解它们之间可能存在差异(比如:处理扩展的 HTTP方法);
移除在HTTP相应报头中有关 OS、Web服务版本和应用程序框架的无关信息;
应用程序存储的安全配置信息应当可以以可读的形式输出,以支持审计;
使用一个资产管理系统,并将系统部件和软件注册在其中;
从生成网络隔离开,并只提供给授权的开发和测试团队访问。开发环境往往没有实际生成环境那么安全,攻击者可以使用这些差别发现共有的弱点或者是可被利用的漏洞;
使用一个软件变更管理系统以管理和记录在开发和产品中代码的变更。
数据库安全
使用强类型的参数化查询方法;
使用输入验证和输出编码,并确保处理了元字符。如果失败,则不执行数据库命令;
确保变量是强类型的;
当应用程序访问数据库时,应使用尽可能最低的权限;
为数据库访问使用安全凭证;
连接字符串不应当在应用程序中硬编码。连接字符串应当存储在一个可信服务器的独立配置文件中,并且应当被加密;
使用存储过程以实现抽象访问数据,并允许对数据库中表的删除权限;
尽可能地快速关闭数据库连接;
删除或者修改所有默认的数据库管理员密码。使用强密码、强短语,或者使用多因子身份验证;
关闭所有不必要的数据库功能(比如:不必要的存储过程或服务、应用程序包、仅最小化安装需要的功能和选项(表面范围缩减));
删除厂商提供的不必要的默认信息(比如:数据库模式示例);
禁用任何不支持业务需求的默认帐户;
应用程序应当以不同的凭证为每个信任的角色(比如:用户、只读用户、访问用户、管理员)连接数据库。
文件管理
不要把用户提交的数据直接传送给任何动态调用功能;
在允许上传一个文档以前进行身份验证;
只允许上传满足业务需要的相关文档类型;
通过检查文件报头信息,验证上传文档是否是所期待的类型。只验证文件类型扩展是不够的;
不要把文件保存在与应用程序相同的 Web环境中。文件应当保存在内容服务器或者数据库中;
防止或限制上传任意可能被 Web服务器解析的文件;
关闭在文件上传目录的运行权限;
通过装上目标文件路径作为使用了相关路径或者已变更根目录环境的逻辑盘,在 UNIX中实现安全的文件上传服务;
当引用已有文件时,使用一个白名单记录允许的文件名和类型。验证传递的参数值,如果与预期的值不匹配,则拒绝使用,或者使用默认的硬编码文件值代替;
不要将用户提交的数据传递到动态重定向中。如果必须允许使用,那么重定向应当只接受通过验证的相对路径 URL;
不要传递目录或文件路径,使用预先设置路径列表中的匹配索引值;
绝对不要将绝对文件路径传递给客户;
确保应用程序文件和资源是只读的;
对用户上传的文件扫描进行病毒和恶意软件。
内存管理
对不可信数据进行输入和输出控制;
重复确认缓存空间的大小是否和指定的大小一样;
当使用允许多字节拷贝的函数时,比如 strncpy(),如果目的缓存容量和源缓存容量相等时,需要留意字符串没有 NULL终止;
如果在循环中调用函数时,检查缓存大小,以确保不会出现超出分配空间大小的危险;
在将输入字符串传递给拷贝和连接函数前,将所有输入的字符串缩短到合理的长度;
关闭资源时要特别注意,不要依赖垃圾回收机制(比如:连接对象、文档处理,等);
在可能的情况下,使用不可执行的堆栈;
避免使用已知有漏洞的函数(比如:printf,strcat,strcpy,等);
当方法结束时和在所有的退出节点时,正确地清空所分配的内存。
通用编码实践
为常用的任务使用已测试且已认可的托管代码,而不创建新的非托管代码;
使用特定任务的内置 API以执行操作系统的任务。不允许应用程序直接将代码发送给操作系统,特别是通过使用应用程序初始的命令shell;
使用校验和或哈希值验证编译后的代码、库文件、可执行文件和配置文件的完整性;
使用死锁来防止多个同时发送的请求,或使用一个同步机制防止竞态条件;
在同时发生不恰当的访问时,保护共享的变量和资源;
在声明时或在第一次使用前,明确初始化所有变量和其他数据存储;
当应用程序运行发生必须提升权限的情况时,尽量晚点提升权限,并且尽快放弃所提升的权限;
通过了解使用的编程语言的底层表达式以及它们是如何进行数学计算,从而避免计算错误。密切注意字节大小依赖、精确度、有无符合、截尾操作、转换、字节之间的组合、 a 计算、以及对于编程语言底层表达式如何处理非常大或者非常小的数;
不要将用户提供的数据传递给任何动态运行的功能;
限制用户生成新代码或更改现有代码;
审核所有从属的应用程序、第三方 和库文件,以确定业务的需要,并验证功能的安全性,因为它们可能产生新的漏洞;
执行安全更新。如果应用程序采用自动更新,则为代码使用加密签名,以确保下载客户端验证这些签名。使用加密的信道传输来自主机服务器的代码。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics