技术分享|代码签名的安全注意事项

  • 时间:2018-08-31 22:19 作者:威努特工控安全 来源:威努特工控安全 阅读:359
  • 扫一扫,手机访问
摘要:代码签名(或者软件签名)为可信计算环境提供技术支持,能有效保障软件在开发、构建、分发、维护过程中可信任、不被篡改。基于代码签名实现白名单机制,能有效减少白名单的生成和维护成本。同时签名系统自身的安全性也至关重要,假如自身不安全,会导致整个信任链不安全,带来严重的安全问题。根据我国等保4级的技术要求,

代码签名(或者软件签名)为可信计算环境提供技术支持,能有效保障软件在开发、构建、分发、维护过程中可信任、不被篡改。基于代码签名实现白名单机制,能有效减少白名单的生成和维护成本。同时签名系统自身的安全性也至关重要,假如自身不安全,会导致整个信任链不安全,带来严重的安全问题。根据我国等保4级的技术要求,在安全计算环境相关章节,提到“应构建从操作系统到上层应使用程序的信任链,以实现系统运行过程中可执行程序的完整性检验,防范恶意代码等攻击,并在检测到其完整性受到破坏时采取措施恢复,例如采使用可信计算等技术”,代码签名技术就是一种实现该信任链的技术方案。

NIST(美国国家标准和技术研究院)在2018年1月26日发布了《Security Considerations for Code Signing》的技术白皮书,详情了代码签名的技术基础、基本架构和安全风险,为代码签名系统提供安全指导,原文可以在NIST的官方网站查找下载:https://csrc.nist.gov/publications。

本文对该技术白皮书进行了翻译,详情给国内的安全工作者。

---------------------------------------------

1前言

最近的安全相关事件表明,在软件的开发、构建、分发和维护阶段,需要一个安全的软件供应链来保护软件产品(或者者称为代码)。特别值得关注的是安装和升级软件,对于平台的安全性起着关键作使用,必需以安全和自动的方式分发和升级各种软件产品,包括固件,操作系统、移动应使用程序和应使用程序容器映像,以防止伪造和篡改。保护软件的一种有效且常见的方法是对软件应使用数字签名。数字签名既提供数据完整性验证,以证实代码未被修改,还提供源代码验证,以标识签名时谁控制了代码。当用者验证签名时,他即可以确信软件来源正确,并且传输过程中未被篡改。

本白皮书针对正在实施代码签名系统或者审查现有系统安全性的软件开发人员和产品供应商,旨在提高系统安全性,提高用户对代码真实性和完整性的信心。系统集成商和管理员可能会担心在其系统上安装并运行的应使用程序的可信赖性,他们可以从代码签名处理方案中取得想要的信息,以保护他们的软件供应链。

本白皮书详情了当今广泛部署的典型代码签名处理方案的功能和架构,形容了几种典型的代码签名使用例,并确定了在将代码签名处理方案应使用于这些使用例时可能出现的少量安全问题。最后,本文提供了规避这些安全问题的方案建议,并提供了更多信息资源作为参考。正确应使用这些建议将有助于确保软件供应链的安全。

NIST计划开发进一步的指导以帮助组织评估、部署或者管理代码签名系统。本文档中形容的少量粗粒度的建议下一步将会进行细化,成为代码签名的实践指导。

2基础知识

本节简单形容一下代码签名过程是如何工作的,整个工作过程中有三个基本角色:开发者、签名者和验证者。

开发者负责编写、构建和提交将要签名的代码。开发者维护一个安全的开发环境,包括源代码库,在完成开发和测试流程后将代码提交给签名者。

签名者负责管理使用于签订软件的密钥。这个角色可以和开发人员属于同一个组织,也可以是独立公正的第三方。该过程的安全性依赖于私钥的保护,所以签名者必需在保证安全的设施上生成代码签名的私钥/公钥对。在许多情况下,签名者通过证书签名请求将公钥提供给证书颁发机构(CA)。CA将确认签名者的身份,并提供与签名者绑定的签名证书。任何人都可以用与此证书关联的公钥来验证用此密钥对签订的代码的真实性和完整性。假如没有用CA,则必需用可信的带外机制来分发公钥。

签名人通过技术和程序控制确保只有受权代码被签订。当开发人员提交代码进行签名时,签名人将验证他们的身份和权限以请求签名。签名者也可能采取额外的步骤来验证代码能否可信。最终,可能需要代码签名系统的两个或者多个可信代理商来批准请求,并生成数字签名。在某些情况下,还可以将签名代码提供给时间戳受权机构,以标记代码签名的时间。

验证者负责验证代码签名。验证者可能是与签名代码相同的开发者提供的软件组件(例如:使用于签名固件升级),或者者也可能是由平台提供的共享组件(例如:操作系统)。

3 结构组成

代码签名体系结构由多种逻辑组件组成。图1所示的代码签名/验证体系结构具备四个不同的组件:代码签名系统(CSS)、证书颁发机构(CA)、时间戳受权机构(TSA)和验证程序。

技术分享|代码签名的安全注意事项

3.1 代码签名系统(CSS)

CSS接收准备签名的代码,对提交者进行身份验证和受权,并生成签名。为了生成这些签名,CSS有一个或者多个私人签名密钥,必需严格保护这些私钥,防止被窃取或者未经受权的用。

3.2认证机构(CA)

通常CSS利使用CA来对签名者的身份进行身份验证。CA根据证书政策颁发证书给签订人,证书政策规定了CA在签发证书时遵循的安全控制和实践,并对证书主题施加要求。NIST机构间报告(Interagency Report)7924 定义了一个可以参考的证书策略,它制定了颁发代码签名证书的CA的大部分要求。另外还有诸如CA/Browser Forum和CA Security Council等行业组织已经发布了使用于签发代码签名证书的要求文件。

3.3时间戳认证(TSA)

少量代码签名体系结构用TSA来标记签名时间。用TSA时,签名会发送给TSA,TSA会将自己的签名和签名时间应使用于软件包。TSA独立于CSS运行,并保持时钟与权威时间源同步。假如签名密钥在代码签名时有效,即便密钥在验证时已过期或者密钥在签名之后某个时间受到损害,这也不会影响原来签名的有效性。

3.4 验证者

验证者负责验证签名者以及签名者用的任何证书和时间戳,还管理使用于验证证书的信任锚。签名者或者独立方可能负责开发验证组件。

3.5信任锚(Trust Anchors)

管理验证组件的一个关键任务是管理使用于验证签名的信任锚,它使用于验证代码签名证书。信任锚是数据对象,通常是公钥,它们被安装并安全地存储在验证平台上。信任锚的可信度基于其安装、存储和管理的方法。信任锚一般不使用于直接验证代码,但通常是签订代码签名CA证书的根CA的公钥。假如丢失个人代码签名CA或者代码签名者拥有的私钥,通过信任锚可以提供恢复的手段。信任锚必需以足够安全的方式进行存储,假如相应的私钥遭到破坏,将导致整个平台容易受到攻击而且无法修复。

4 典型使用例

CSS系统的实现及策略制定取决于实际的使用例,本节详情四个典型使用例:固件签名、驱动程序签名、可信应使用程序商店和应使用程序软件签名。请注意,这些例子仅使用于示例说明; 它们既不反映每个使用例的所有实例,也不包含所有代码签名使用例。

4.1固件签名

固件的安全分发是软件供应链的一个例子,其中代码签名的所有工作通常由单一组织负责:软件开发、受权签订代码、CSS的管理、以及最后的验证。典型的工作流程包括一组开发人员,在将代码传递给构建系统之前,他们在版本控制系统中跟踪提交的代码。在开发过程中,CSS可能会用开发或者测试密钥签订非生产版本,这些签名将仅使用于测试,不会使用于验证明际发布的代码。

当代码准备打包发布时,开发人员将其提交给签名部门。受权审批人(可能有多个审批人)根据组织政策检查代码,并提交代码批准签名。CSS检查这一套数据(代码,批准和元数据)以确定能否满足所有要求,而后对该软件包用生产密钥进行签名。密钥可以针对每个项目单独设置,所有生产密钥都需要集中安全保存,比方位于硬件安全板块(HSM)中,每个相应的公钥安全地安装在固件所针对的平台上的验证器组件中。

4.2驱动签名

设施驱动程序是运行在计算机系统内核周围的特权进程,使用于控制硬件组件并与之通信。典型的个人电脑具备多个具备相关驱动程序的硬件设施。尽管驱动程序通常由相关硬件供应商开发,但代码签名的所有其余工作依然由中央认证机构进行控制。尽管细节不尽相同,但设施驱动程序通常由预配置的中央可信受权机构签订。对于操作系统(OS)的驱动程序,批准和签名过程通常由OS供应商执行。固件级驱动程序(例如统一可扩展固件接口(UEFI)驱动程序)通常依赖于中央第三方签名服务,由原始设施制造商(OEM)管理信任锚。在这个例子中,驱动程序开发人员不会取得他们自己的代码签名密钥和证书。相反,他们将代码提交给中央可信机构(例如操作系统供应商或者OEM厂商),后者验证开发人员的身份并为提交的驱动程序提供签名。假如后续发现驱动程序不可信或者恶意,则可信机构有机制撤销已经颁发给该开发机构或者人员的签名。

4.3可信应使用商店

现在计算设施通常用应使用程序商店向使用户分发签名的应使用程序,包括由第三方开发的软件。不同的平台以不同的方式执行代码签名,但在大多数情况下,应使用程序商店由操作系统或者平台供应商维护经营,只分发经过审查的应使用程序(请参见NIST的SP 800 -163 )。尽管单个开发人员可能拥有自己的签名密钥,无论是为了开发目的还是为了向商店进行身份验证,使用于签订应使用程序的私钥受商店的控制,该商店在CSS上提供服务。开发人员将他们的应使用程序提交给商店,并在应使用程序进行审核之前验证其身份。假如一切顺利,商店就会对应使用程序进行签名并发布,以供下载。设施可以配置为仅安装由应使用商店控制的密钥签名的应使用。

4.4应使用软件签名

操作系统通常支持独立供应商开发和分发应使用程序。根据系统的配置,有效的代码签名可能是安装的先决条件,或者者操作系统可能只允许已签名的应使用程序对受保护的系统资源进行访问。要让这些签名被操作系统接受,应使用程序开发人员必需从操作系统供应商信任的CA获取代码签名证书。操作系统供应商可能为此经营一个CA,或者者与商业CA合作提供此服务。开发人员生成一个代码签名密钥对,并从CA请求一个公钥密钥。CA在颁发证书之前验证开发人员的身份,开发人员用其私钥签订为该OS开发的任何应使用程序。这些签名确定了开发人员的身份,并允许操作系统验证应使用程序未被篡改。 开发人员也可以从TSA获取时间戳,这样即便在证书过期后操作系统也能够验证签名。操作系统可以确定应使用程序的出处,系统管理员或者使用户可能会讯问能否信任开发人员的代码,由于操作系统供应商不会审查应使用程序。当然,假如某个开发人员曾经提交过恶意代码,受信任的CA将会拒绝向他颁发证书,以保证后续签名代码的安全可信。

5 CSS面临的威胁

本节列举了CSS的少量潜在威胁。

私人签名密钥的盗使用:没有被正确保护的私人签名密钥有被盗风险,被盗后即可能被攻击者使用于签订任意代码。少量代码签名系统对已签名的软件没有有效的撤销机制,这也会加剧这种威胁的严重性。

颁发未经受权的代码签名证书:使用于颁发代码签名证书的CA私钥缺乏保护或者使用于颁发这些证书的审核程序过弱,可能允许攻击者获取一个或者多个未经受权的代码签名证书。

错误放置的证书或者密钥:假如少量证书或者密钥素来不打算使用于代码签名,就不应该放置在验证程序的信任库里面。在某些情况下,验证者可能允许使用户将信任扩展到不值得信任的证书或者签名者,从而产生错误的验证结果。

签订未经受权或者恶意代码:代码签名程序可能允许恶意或者未经受权的代码被无意识地签名,可能的起因包括:合法错误、糟糕的管理、内部人员攻击、成功侵入软件/固件开发或者代码签名系统。同样,对开发系统或者代码签名基础设备本身的入侵可能导致恶意代码被签名。

用不安全的密码学:假如用比较弱或者不安全的密码算法或者密钥生成方法,用现在的密码分析技术或者强力攻击方式可能恢复私钥或者获取欺诈性证书。在未来随着新的密码分析技术、新的漏洞,或者量子计算机的发展,可能使先前部署的系统不再安全。

6安全建议

本节详情如何通过在开发、构建、分发和维护阶段保护代码来提高软件供应链的安全性。

识别和认证(I&A)可信誉户:实施I&A计划,充分识别能够签订代码或者提交代码进行签名的使用户。

受权可信誉户:确定谁有权提交代码进行签名,维护一个列表并定期审查,指定谁可以提交代码以及他们可以提交哪些代码(例如:他们可以提交哪些项目)。考虑要求两个人批准使用于签名或者用多因素认证的代码。

CSS进行角色分工:分离运行CSS的关键角色并将其分配给不同的人,特别是将CSS的管理角色与受权的代码提交者的角色分开。

建立检视、审查和批准代码的政策和程序:签名代码说明组织接受该固件或者软件,所以签订代码之前,组织应检视和审查代码以确保其值得信赖。组织现有的安全软件开发和构建流程应该支持这些程序。

用强大的加密技术:用设计良好的、经过测试和维护的加密库,并选择NIST批准的哈希和签名算法。

保护签名密钥:必需保持签名密钥的保密性,它们应该被隔离在具备最小应使用程序和连接的机器上。假如可能的话,密钥应该以最少的功能存储在HSM中(例如签名)。

用单独的CSS进行开发:假如代码需要定期签名进行开发验证,创立一个物理或者逻辑上不同的CSS,这些CSS将在开发过程中用并且不使用于签订生产代码。在这种分离的场景,开发密钥和生产密钥应用不同的根密钥。

隔离和保护CSS:CSS是一个基础安全系统,应作为关键资产加以保护。尽最大可能将CSS与生产网络(以及任何外部网络)隔离开来。

利使用审计系统定期审查日志:审核签名密钥的用情况,定期查看日志以查找密钥的异常用情况。制定保护机制,不允许CSS覆盖历史日志。

利使用信用良好的CA:假如用CA来建立对签名者和公钥的绑定的信任,则可以用安全CA或者从信用良好的CA购买证书。假如没有用CA,则通过单独拥有私人签名密钥来建立信任。在这种情况下肯定要重点保护好签名密钥,由于以后将很难进行密钥的升级。

利使用有信用的TSA:假如用TSA来提供代码签名时间,则需要确保经营一个安全的TSA,或者者用有信用的TSA的服务。

管理信任锚:在许多情况下,可以升级信任锚。但是应该注意只有在适当受权的情况下,信任锚才会发生变化。信任锚不能随便更改,必需按照定义明确的过程进行升级。

管理代码版本:假如需要阻止回退,则应将代码版本作为包中元数据的一部分进行签名,并在验证过程中由验证者进行验证。只有当提供的代码版本比系统上已经存在的代码版本升级时,才会继续进行更新升级。

验证证书:假如用CA,验证者必需能够确定包含公共签名验证密钥的证书是有效的。它应检查证书上的签名能否有效并来自受权的CA, 还应检查包括有效期和密钥用字段的关键字段。

验证时间戳:假如签名代码包含时间戳,验证者必需能够确定时间戳由其信任的TSA签订,并且要验证代码签名时间戳的有效性。

验证签名:验证者必需能够验证签名并确定与签名关联的公钥可以链接回受权签名者。请注意在某些情况下没有CA,必需根据公钥确定受权。

检查证书撤销:有时证书需要在有效期结束前撤销。 验证者应该能够检查证书吊销或者具备使用于升级信任锚的安全机制。

7 总结

本白皮书详情了使用于保护软件供应链的代码签名处理方案的安全注意事项。代码签名可以确保软件是真实的,并且在开发、构建、分发和维护阶段没有被篡改,并且验证者可以在运行时验证这些属性。代码签名处理方案的核心组件包括CA、TSA、CSS和验证程序,文中详情了几个典型的签名使用例,定义了相关的部署模型。

  • 全部评论(0)
手机二维码手机访问领取大礼包
返回顶部