1、ICS 35.080 L70/84 HS 中 华 人 民 共 和 国 海 关 行 业 标 准 HS/T 332011 .NET 安全编码规范 Secure coding specification for .NET 2011 - 08 - 12 发布 2011 - 10 - 01 实施 中华人民共和国海关总署 发 布 HS/Z XXXX I 目 次 前言 . II 引言 . III 1 范围 . 1 2 术语和定义 . 1 3 代码安全性分类 . 2 4 代码安全性声明要求 . 3 5 中间结果和状态信息处理要求 . 3 6 限制方法调用要求 . 4 7 遗留系统代码封装要求 . 4 8 敏感
2、数据操作异常要求 . 5 9 其他 . 5 附录A(资料性附录) 安全编码示例 . 7 A.1 代码访问安全性示例 . 7 A.2 中间结果和状态信息处理示例 . 9 A.3 限制方法调用示例 . 10 A.4 越权访问敏感信息的示意过程 . 12 A.5 遗留系统代码封装要求示例 . 13 A.6 敏感数据操作异常示例 . 14 参考文献 . 18 HS/Z XXXX II 前 言 本标准按照GB/T 1.1-2009给出的规则起草。 本标准由中华人民共和国海关总署科技发展司提出。 本标准由中华人民共和国海关总署政策法规司归口。 本标准起草单位:中华人民共和国海关总署科技发展司、全国海关信息
3、中心(全国海关电子通关中心)。 本标准主要起草人:*、*。 本标准是第一次制定。 HS/Z XXXX III 引 言 随着海关信息化的深入,.NET应用编码中的安全问题受到普遍关注。现阶段,.NET开发技术已在中国海关普遍应用,在稳步推进等级保护、分级保护的过程中,.NET编码的安全问题日益受到重视。 安全编码方法是指运用科学的编码技巧和手段, 稳妥的实现应用功能, 并针对主要编码漏洞提出有针对性的防护对策和整改措施,进而防范和化解应用编码安全风险,将风险控制在可接受的水平,为最大限度的保障信息系统安全提供技术保障。 安全编码方法作为信息安全保障工作的基础性工作和重要手段, 应贯穿于海关信息系
4、统建设、 维护过程,是海关信息系统实现安全开发的重要科学方法之一。 本标准是以海关既有.NET项目的开发、 使用情况为基础, 确定.NET应用编写过程中需要遵循并沿革的相关安全规范。 本标准编制遵循通用性原则,确定.NET安全编码的基本原则、方法、要求,而不对具体实现技巧和编码细节进行过于详尽的描述。HS/Z XXXXXX 1 .NET 安全编码规范 1 范围 本标准给出了海关信息系统实施中安全编码的原则性要求,适用于海关自建、合建、委托外部单位建设的信息系统或相关模块的开发工作。 注:本标准所指“代码”包括生产代码、测试程序代码、工具代码以及用于调试和维护的其他代码。如没有特别说明,本标准中
5、提及的“应用”其含义均为“.NET应用”,本标准中提及的“项目”其含义均为“.NET项目”。本标准提及的“敏感信息”的界定应依据海关相关管理规定。 2 术语和定义 下列术语和定义适用于本文件。 2.1 公共库代码 common library 专门用于项目间共享使用的程序库代码。 2.2 程序集 assembly .NET应用程序编译结果的存储形式。 所有托管类型和资源都包含在某个程序集内, 并被标记为只能在该程序集的内部访问,或者被标记为可以从其他程序集中的代码访问。 2.3 安全策略 security policy 规定如何在组织或系统中管理、保护、分发包括敏感信息在内的资产的规则、命令、
6、条例。 HS/T 22-2009, 定义3.5.10 2.4 代码访问安全性 code access security (CAS) 公共语言运行时提供的一种机制,通过该机制,安全策略授予托管代码权限,并且这些权限是强制的,从而帮助限制允许代码执行的操作。 2.5 视窗通信基础 windows communication foundation(WCF) 一种 Windows 托管技术,用于生成并管理面向服务的系统。 2.6 序列化 serialization HS/Z XXXXXX 2 将对象的状态信息转换为可以存储或传输的格式的过程。 注:在序列化期间,对象将其当前状态写入到临时或持久性存储区
7、。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。 2.7 方法 method 描述行为的函数。 2.8 证据 evidence 标识代码所用安全策略的属性。 注:如数字签名或其原位置的区域或站点,安全策略使用其为代码授予权限。 2.9 信息系统 information system 由计算机及其相关的和配套的设备、设施(含网络)构成的,按照一定的应用目标和规则对信息进行采集、加工、存储、传输、检索等处理的人机系统。 典型的信息系统由三部分组成:硬件系统(计算机硬件系统和网络硬件系统);系统软件(计算机系统软件和网络系统软件);应用软件(包括由其处理、存储的信息)。 GB/T
8、 20984-2007,定义3.8 2.10 托管代码 managed code 由公共语言运行库环境执行的代码。 2.11 非托管代码 unmanaged code 直接由操作系统执行的代码。 2.12 遗留系统 legacy system 采用旧版本技术或.NET异构平台技术建设的信息系统。 3 代码安全性分类 根据安全性要求,海关.NET项目代码划分如下: a) 安全性无关的代码(N 类:Neutral):技术上可以运行于任何系统权限的代码; b) 普通的应用逻辑描述性代码(B 类:Business):实现业务逻辑、业务实体、业务流程的代码; c) 非托管代码(U 类:Unmanaged
9、):直接调用运行环境非托管资源的代码、直接调用操作系统API、本地.Lib、COM+的代码; d) 公共库代码(C 类:Common); e) 直接访问海关敏感技术资源的公共库代码(S 类:Sensitive):例如访问海关内网安全系统、活动目录、审计系统的代码。 HS/Z XXXXXX 3 同一个系统中,各类代码的安全性要求如图1。 NBCUS代码安全性要求低高 图1 各类代码的安全性要求 4 代码安全性声明要求 下列情景应采用该方式定义代码访问权限: a) 对已明确需要增加访问权限控制的代码,声明采用最小权限; b) 涉及表 1 所列权限,应在代码中明确声明; c) 所有互操作调用应显式声
10、明需要访问非托管代码; d) WCF 访问中,为了提高代理类的安全性,应采用代码声明安全。 表1 敏感代码权限表 权限 说明 SecurityPermission 一般性安全访问要求。 UnmanagedCode 允许托管代码调用非托管代码。 SkipVerification 如果没有验证,代码可以进行任何操作。 ControlEvidence 允许采用失效的证据欺骗安全策略。 ControlPolicy 允许修改安全策略,也可禁用安全性。 SerializationFormatter 可通过序列化规避代码访问安全性机制。 ControlPrincipal 可设置当前主体身份进而欺骗基于角色的
11、安全。 ControlThread 可控制与线程关联的安全状态。 ReflectionPermission 允许通过反射获得系统安全策略要求及其它敏感业务信息。 MemberAccess 可使私有成员可访问性机制无效。 S、U 类代码应采用,C 类代码宜采用,B、N 类代码可采用。 示例参见附录 A 的 A.1。 HS/Z XXXXXX 4 5 中间结果和状态信息处理要求 S、U、B类代码中类型的实例状态应声明为private,对于C类代码最大限度声明为internal。具体要求如下: a) 为了防止通过继承获得访问,包括敏感信息的类声明为 sealed; b) 敏感状态信息严禁声明为 pro
12、tected; c) 除非有特殊网络保护,严禁将包括敏感状态信息的类声明为可序列化; d) 运行环境统一使用发布(Release)版本的程序集。 S、U、C、B 类代码应采用,N 类代码宜采用。 示例参见附录 A 的 A.2。 6 限制方法调用要求 类型实例方法访问控制应用中应按照安全性要求高低,采用表2中所列访问控制符。 表2 安全性要求与访问控制符对应关系表 访问控制符 说明 安全性要求 public 访问不受限制。 低 protected 访问仅限于包含类或从包含类派生的类型。 中 internal 访问仅限于当前程序集。 高 protected internal 访问仅限于当前程序集或
13、从包含类派生的类型。 高 private 访问仅限于包含类型。 最高 为确保调用过程的安全性,应对方法调用做如下限制: a) 涉及敏感资源的调用,应对调用者身份进行检查; b) 涉及敏感资源的调用,应对调用者权限进行检查; c) 涉及调用敏感资源的类型应明确其子类必须具有何种身份或者权限; d) 涉及调用敏感资源的类型定义虚方法时应限制其子类的身份或权限要求; e) 最终业务实体类应禁止被子类继承(sealed)。 S、U、C 类代码应采用,B 类代码宜采用,N 类代码可采用。 示例参见附录 A 的 A.3。 7 遗留系统代码封装要求 下列情形应在封装遗留系统代码时进行安全检查: a) 后绑定
14、方式调用 COM+; b) 直接引用既有系统组件(COM+、.Net 1.1、Java Applet 等); c) 直接调用操作系统本地 API; 调用相关系统 ActiveX 控件。 U 类代码应采用。 示例参见附录 A 的 A.4、A.5。 HS/Z XXXXXX 5 8 敏感数据操作异常要求 如控制不当,应用异常易造成敏感信息泄漏。为此,应在相关处理过程进行限制,防止敏感信息及过度的技术信息泄漏。异常处理流程如图2。 出现异常是否为应用自身相关异常?抛出异常完成是否需要审计?记录审计信息是否需要替换敏感信息?替换敏感信息抛出异常否是是否否是 图2 异常处理流程 异常处理流程应遵循如下原则
15、: a) 对于非应用自身相关异常直接抛向上层逻辑; b) 对于需要审计的错误环节或错误类型,应先写审计日志; c) 写审计日志过程中如出现异常不应回滚操作,应将异常同时记录; d) 如异常存在嵌套结构,应记录异常完整的嵌套结构; e) 如异常中涉及敏感错误信息应先对错误信息替换,并抛出已替换敏感信息的异常。 S 类代码应采用,B 类代码宜采用,C、U、N 类代码可采用。 示例参见附录 A 的 A.6。 9 其他要求 应用开发中还应实施如下安全编码措施: HS/Z XXXXXX 6 a) 应始终对用户输入的信息进行必要的安全检查; b) 应使用 checked 关键字检查算术运算溢出; c) 应
16、始终对参数使用贴切的数据类型; d) 应验证用于生成 SQL 语句的各类参数; e) 应使用海关统一要求的安全组件完成加密、签名功能; f) 应为程序集指定强名称; g) 不应在除审计日志以外的其他任何日志中保留敏感信息; h) 不应在 XML 或其他配置文件中存储敏感信息; i) 应对涉及敏感信息的代码补充安全注释,说明安全要求和处理规范; j) 不应将密码或其他敏感信息编码到应用程序中。 HS/Z XXXXXX 7 A A 附 录 A (资料性附录) 安全编码示例 A.1 代码访问安全性示例 对已明确需要增加访问权限控制的代码,声明采用最小权限。 示例1: 程序集级文件访问权限声明: C#
17、 using System.Security.Permissions; assembly: FileIOPermissionAttribute(SecurityAction.RequestMinimum, Write = entry.txt) 示例2: 类级文件访问权限声明: C# using System; using System.IO; using System.Security.Permissions; assembly: FileIOPermission(SecurityAction.RequestMinimum, Read=entry.txt) namespace ChinaCus
18、toms.Training.Guidline.Security public class TestConsole public static void Main(string args) / Attempt to create a file using (Stream s = new FileStream(entry.txt, FileMode.Create) using (StreamWriter sw = new StreamWriter(s) sw.Write(This is some test data.); / Attempt to open the file that was pr
19、eviously created. using (Stream s = new FileStream(entry.txt, FileMode.Open) using (StreamReader sr = new StreamReader(s) Console.WriteLine(sr.ReadLine(); HS/Z XXXXXX 8 执行结果 This is some test data. 所有互操作调用应显示声明需要访问非托管代码。 示例 3: 互操作访问 H2000 COM+: C# using System.Security.Permissions; assembly:Security
20、PermissionAttribute(SecurityAction.RequestMinimum, Flags = SecurityPermissionFlag.UnmanagedCode) namespace ChinaCustoms.Training.Guidline.Security using System; using System.Runtime.InteropServices; WCF 调用中,为了提高代理类的安全性,宜采用代码声明安全。 示例 4: WCF 中声明只有完全信任的类型可调用 WCF 服务: C# assembly: AllowPartiallyTrustedCa
21、llers ServiceContract public interface IMyContract OperationContract void MyMethod(); PermissionSet(SecurityAction.Assert, Name = FullTrust) public class MyContractClient : ClientBase, IMyContract, IDisposable public MyContractClient() public MyContractClient(string endpointName) : base(endpointName
22、) #region Constructors public void MyMethod() Channel.MyMethod(); HS/Z XXXXXX 9 public new void Close() base.Close(); void IDisposable.Dispose() Close(); #endregion A.2 中间结果和状态信息处理示例 为了防止通过继承获得访问,包括敏感信息的类声明为 sealed; 示例: 由于设计不当导致恶意代码通过继承修改税费信息: C# using System; namespace ChinaCustoms.Training.Guidlin
23、e.Security class BugTaxForm protected double tax = 0; public double Tax get return tax; class ViciousTaxForm : BugTaxForm public ViciousTaxForm() tax = 5000; public class TestConsole public static void Main(string args) BugTaxForm tax = new ViciousTaxForm(); Console.WriteLine(tax.Tax); HS/Z XXXXXX 1
24、0 执行结果 5000 A.3 限制方法调用示例 采用 LinkDemand 和 InheritanceDemand 关键字保护报关单实体类。 示例 1: 未 sealed 的报关单类: C# using System; using System.Security.Permissions; namespace ChinaCustoms.Training.Guidline.Security PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = FullTrust) PermissionSetAttribute(Securi
25、tyAction.LinkDemand, Name = FullTrust) public class Entry 示例 2: sealed 的报关单类: C# using System; using System.Security.Permissions; namespace ChinaCustoms.Training.Guidline.Security PermissionSetAttribute(SecurityAction.LinkDemand, Name = FullTrust) public sealed class Entry 示例 3: 公共抽象类型(public abstra
26、ct) ,应定义为 LinkDemand 和 InheritanceDemand: C# using System; using System.Security.Permissions; namespace ChinaCustoms.Training.Guidline.Security HS/Z XXXXXX 11 PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = FullTrust) PermissionSetAttribute(SecurityAction.LinkDemand, Name = FullTrust
27、) public abstract class IcCardBase 示例 4: 限制恶意程序覆盖报关单类放行方法,方式 1: C# using System; using System.Security.Permissions; namespace ChinaCustoms.Training.Guidline.Security abstract class Entry private bool isReleased; PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = FullTrust) PermissionSet
28、Attribute(SecurityAction.LinkDemand, Name = FullTrust) public virtual void Release() isReleased = false; 示例 5: 限制恶意程序覆盖报关单类放行方法,方法 2: C# using System; using System.Security.Permissions; namespace ChinaCustoms.Training.Guidline.Security abstract class Entry PermissionSetAttribute(SecurityAction.Inher
29、itanceDemand, Name = FullTrust) PermissionSetAttribute(SecurityAction.LinkDemand, Name = FullTrust) public abstract void Release(); HS/Z XXXXXX 12 对于涉及敏感方法的公共接口,需要限制具体实现方法具有特定访问权限。 示例 6: 接口方法明确要求的安全权限在子类中必须严格遵从: C# using System; using System.Security.Permissions; namespace ChinaCustoms.Training.Guid
30、line.Security public interface IEntry PermissionSetAttribute(SecurityAction.LinkDemand, Name = FullTrust) PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = FullTrust) void Release(); PermissionSetAttribute(SecurityAction.LinkDemand, Name = FullTrust) PermissionSetAttribute(SecurityActi
31、on.InheritanceDemand, Name = FullTrust) class Entry : IEntry public void Release() A.4 越权访问敏感信息的示意过程 出于进度和成本的考虑, 海关信息化建设中经常需要对既有组件进行封装, 如不对此类调用严格限制,易形成安全隐患,为此应在封装代码环节增加必要的安全控制。图A.1中显示出通过封装遗留代码,越权访问敏感信息的示意过程。 HS/Z XXXXXX 13 图 A.1 通过封装遗留代码越权访问敏感的示意过程 A.5 遗留系统代码封装要求示例 示例: 后绑定调用 COM+时声明权限要求: C# using Sy
32、stem; using System.Reflection; using System.Security.Permissions; namespace ChinaCustoms.Training.Guidline.Security assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, Flags = SecurityPermissionFlag.UnmanagedCode) public class NativeHelper PermissionSetAttribute(SecurityAction.LinkD
33、emand, Name = FullTrust) public static object CreateObject(string progId) Type comType = Type.GetTypeFromProgID(progId); object result = Activator.CreateInstance(comType); return result; HS/Z XXXXXX 14 PermissionSetAttribute(SecurityAction.LinkDemand, Name = FullTrust) public static object Invoke(ob
34、ject comObject, string method, object arguments) if (comObject = null) throw new NullReferenceException(); return comObject.GetType().InvokeMember( method, BindingFlags.InvokeMethod, null, comObject, arguments); A.6 敏感数据操作异常示例 由于 Finally 方法会被严格执行,异常重新抛出前 Finally 部分已经提前调用。因此,访问敏感信息的过程中,应在 Finally 部分显
35、示释放非托管资源和其他重要的系统资源。 示例 1: 存在错误的异常处理: C# using System; using System.Diagnostics; namespace ChinaCustoms.Training.Guidline.Security sealed class BugEntry private bool isReleased = false; public void InternalWorkflow() Trace.WriteLine(Release Status : + isReleased); try isReleased = true; Trace.WriteLi
36、ne(Release Status : + isReleased); throw new Exception(); / 试图挽救错误情况下放行标志设置, 但该段代码没机会真正执行 isReleased = false; finally HS/Z XXXXXX 15 Trace.WriteLine(Release Status : + isReleased); public void AboveWorkflow() try InternalWorkflow(); catch Trace.WriteLine(Release Status : + isReleased); public class
37、TestConsole public static void Main() BugEntry entry = new BugEntry(); entry.AboveWorkflow(); 执行结果: Release Status : False Release Status : True Release Status : True Release Status : True 说明试图恢复放行标志的逻辑没有执行 由于 Finally 方法自身出现错误时不会抛出异常,因此出于审计、运行监控等需要,内层应用逻辑应采取直接抛出异常的方式,不应在 Finally 部分抛出处理后的异常信息。 示例 2:
38、抛出层次型异常: C# using System; using System.Diagnostics; HS/Z XXXXXX 16 namespace ChinaCustoms.Training.Guidline.Security sealed class BugEntry private bool isRelease; public void InternalWorkflow() try isRelease = true; Trace.WriteLine(Internal try); throw new Exception(); catch isRelease = false; Trace
39、.WriteLine(Internal catch); throw; finally Trace.WriteLine(Internal finally); public void AboveWorkflow() isRelease = true; try Trace.WriteLine(External try); InternalWorkflow(); catch isRelease = false; Trace.WriteLine(External catch); finally Trace.WriteLine(External finally); HS/Z XXXXXX 17 Trace
40、.WriteLine(isRelease); public class TestConsole public static void Main() BugEntry entry = new BugEntry(); entry.AboveWorkflow(); 执行结果: External try Internal try Internal catch Internal finally External catch External finally False 说明即便内层、外层都可能存在异常的情况下,如果均涉及有严格容量限制的资源访问,均可以在Finally部分进行释放,异常情况下设置“放行”
41、标可以采用这种纵深try. catch.finally的方式进行保护。为保护程序堆栈,应确保finally部分不会发生未捕获的异常。 HS/Z XXXXXX 18 参 考 文 献 1GB/T 18336-2008 信息技术 安全技术 信息技术安全性评估准则 2GB/T 19715.1-2005 信息技术 信息技术安全管理指南 第1部分:信息技术安全概念和模型 3GB/T 5271.8-2001 信息技术 词汇 第8部分:安全 4HS/T 22-2009 海关信息化术语 5GB/T 20984-2007 信息安全技术 信息安全风险评估规范 6Visual Studio 和 .NET Framework 词汇表 微软 ,该文献以互联网文件的形式存于网页 http:/ _