前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >浅谈.NET中敏感信息的保护和存储

浅谈.NET中敏感信息的保护和存储

作者头像
JusterZhu
发布2025-01-23 21:06:34
发布2025-01-23 21:06:34
920
举报
文章被收录于专栏:JusterZhuJusterZhu

背景故事

随着企业和个人对网络安全的愈发重视,软件的安全开发生命周期(Secure Development Lifecycle)也被越来越多的提及。本篇对SDL常见的信息保密需求,结合.NET中敏感信息保护和存储的实践做简单讨论,其中安全需求部分参考IEC(国际电委员协会)62443-4-2 CR 4.1 Information confidentiality(信息保密)。 IEC62443是国际上被广泛认可的工控系统标准,其中62443-4-2部分描述了在具体技术实现上的信息安全要求。

CR 4.1 Information confidentiality定义的安全需求内容大体翻译如下:

  1. 提供保护静态信息机密性的能力,并支持明确的读取授权。
  2. 支持保护传输中信息的机密性,如EC 62443-3-3 SR 4.1 标准。

本篇讨论的范围局限于第一点,即对静态信息的保护。在软件程序中,第一点需求通常可以被分解为以下:

  • 敏感信息不能以明文,人类可阅读的格式存储。
  • 加密算法要符合行业规范,不能使用过时的,有缺陷的加密算法。
  • 对敏感信息的加密,应是安装实例(或机器)相关的,而不是相同密钥。

敏感信息的识别

结合.NET应用软件开发的常见场景,假定识别出以下敏感信息,作为示例,分别对具体的保护方案展开讨论。

  • 软件自身的License文件。
  • 身份验证用的JWT security key。
  • 数据库连接密码。
  • 第三方系统的凭证信息(用户名,密码)。

.NET对敏感信息的保护和存储

.NET作为全功能的开发平台,对安全相关内容做了非常好的支持。本篇讨论的敏感信息保护和存储分为两个部分。其中数据保护依赖ASP.NET Core Data Protection API,可理解为对数据的加密和解密。保护后的数据还需要做安全存储,同样依赖.NET Configuration的相关特性。

ASP.NET Core Data Protection API

ASP.NET Core Data Protection API(本文简称DPAPI)是一套加密API,可用于数据保护,包括密钥管理和轮换。这里注意一般情况下密钥管理和轮换无需开发人员操作,.NET会处理算法选择和密钥生存周期。

数据保护过程主要包括以下步骤:

  1. 从数据保护提供程序(Data Protection Provider)创建数据保护程序(Data Protector)。
  2. 对要保护的数据调用Protect方法(加密)。
  3. 对要恢复为纯文本的数据调用Unprotect方法(解密)。

随着我们对DPAPI的实际使用,还会发现以下特点,这里先不做展开。

  • 契合.NET 技术栈,使用简单方便。
  • 可实现机器相关,甚至用户相关的非固定密钥加密。
  • 通过ApplicationName和Purpose灵活实现密钥的共享或隔离。

敏感信息的存储

敏感信息在通过DPAPI保护后,可采用以下存储方案之一或组合:

  • 指定目录下的特定文件,例如软件自身的License。
  • 操作系统环境变量,例如JWT security key。
  • 应用程序运行目录下的配置文件,例如开发环境调试用的Password。
  • 数据库表存储,例如第三方系统的用户名,密码。

.NET Configuration

本篇对敏感信息的存储,一定程度上依赖.NET处理配置信息的顺序。在ASP.NET Core中,通过Host对象启动的应用程序按以下顺序读取配置(优先级高到低):

  1. 使用命令行配置提供程序通过命令行参数提供。
  2. 使用环境变量配置提供程序通过环境变量提供。
  3. 应用在 Development 环境中运行时的应用机密。
  4. 使用 JSON 配置提供程序通过 appsettings.json 提供。
  5. 使用 JSON 配置提供程序通过 appsettings.Environment.json 提供 。 例如,appsettings.Production.json 和 appsettings.Development.json。

通过DPAPI对数据进行保护,结合.NET 读取配置的优先级,针对不同数据区别存储位置,共同构建了本篇对于敏感信息保护和存储的实践。

下面根据适用场景将做区分讨论。示例如无特殊说明,均为Windows单服务器部署。Application / Web Service可以是安装包程序,桌面程序,Web应用程序和Windows Service。

单一应用程序的数据保护和存储

  • 单个Application / Web Service中的数据保护。
  • 多个Application / Web Service,但Protect/Unprotect操作仅在单个Application/Web Service发生。
  • Application / Web Service不想承担管理密钥的职责。

单一应用程序数据保护的定义应符合以上描述,示例场景如下:

某工控软件在年度渗透测试中,得到反馈:软件自身License的内容不能以明文存储。

对软件自身License的加密,识别为单一应用程序数据保护。

  • 要求对License的内容做用户或机器相关的加密。
  • 要求License文件在工控软件安装后,由用户操作生成。
  • 要求License文件存储位置为指定路径。

数据保护

使用默认设置的ASP.NET Core DPAPI对License文本进行Protect和Unprotect操作。具有如下特点:

  • 无需考虑任何设置,使用成本极低。
  • 密钥是用户相关的,安全性有保障。

这里需要说明的是,在默认设置下,DPAPI对数据的保护是用户相关的。

以Windows举例,可能是运行软件,执行License操作的当前登录账户。也可能是安装过程中,申请的具有安装权限的特定系统用户(如LocalSystem)。这取决于软件具体的操作逻辑。

但要注意,默认情况下,不同用户是无法成功Unprotect,互相解密读取数据的。

数据存储

单一应用程序的数据存储一般无要求,上述示例中,License文件可以指定存放固定位置,或由用户指定位置。

多应用程序单用户共享保护数据的场景

  • 多个Application / Web Service 对同一份数据做 Protect / Unprotect 操作。
  • 多个Application / Web Service 的用户相同。
  • 被保护数据能够被多个Application / Web Service 共享访问。
  • 多个Application / Web Service 均不承担密钥的管理职责。

符合以上描述的示例场景如下:

某内网部署的工业软件,由多个Application / Web Service组成,均存在对数据库Password的访问。

  • 数据库Password对不同客户,应做机器相关加密,而不是所有安装实例使用相同密钥。
  • 多个Application / Web Service访问相同被保护的数据库Password。
  • 多个Application / Web Service部署于同一服务器,使用相同用户(假定为LocalSystem)运行。
  • 要求Password存储到指定位置。
  • 对DPAPI用来Protect的加密密钥位置无约束(密钥位置需要能够被Application / Web Service访问)。

数据保护

和单一应用程序不同,多个Application / Web Service需要以相同账户(假定为LocalSystem)运行,因为密钥和用户相关联。

同时需要注意,DPAPI要以相同ApplicationName创建和共享同一个Data Protection Provider。

并且使用这个相同的Data Protection Provider,以相同的Purpose,创建和共享同一个Data Protector。

数据存储

数据库Password属于敏感信息,要求做用户或机器相关加密,不能以相同密钥加密后,预先写入appsettings.json。

相比在安装过程中用户填写密码,加密后再覆盖配置文件appsettings.json,使用环境变量则更为简单便捷。

根据.NET 配置的优先级顺序。环境变量中对应配置项会自动覆盖配置文件。

区分Development和Production环境

使用DPAPI+环境变量能够满足对敏感信息的数据保护和安全存储。

但实际工作中,开发团队的小伙伴反馈以下问题:

  • 本地开发也需要Protect Password存储到环境变量。
  • 远程连接开发环境服务器调试,Password无法Unprotect。因为Protect是用户相关的。

以上问题影响了开发效率。我们需要区分Dev和Prod环境,改进对敏感数据保护和存储的方案。

  • 本地开发、DIT Server,使用固定密钥。支持本地代码 + DIT环境Server调试。
  • SIT Server、安装包版本,使用用户相关的加密。

数据保护

  • 根据Environment.IsDevelopment()区分数据保护的方式。
  • FixedKeyInfoProtector将使用固定密钥的加密方式,相同密钥将产生相同的密文。
  • DynamicKeyInfoProtector将使用DPAPI做数据保护,用户相关的密钥产生密文不固定。

数据存储

  • Development环境使用appsettings.development.json的配置项。
  • Development环境同样支持使用环境变量覆盖配置文件配置项。
  • 非Development环境要求必须使用环境变量中的配置项。

多用户场景对相同数据的保护和存储

  • 多Application / Web Service的用户可能是特定Windows用户,LocalSystem和LocalService的任意组合。
  • 多Applicatoin / Web Service需要共享密钥。

以同一高权限账户来运行所有程序,无论从开发者还是使用者角度,都是一件轻松的事情。但同样根据IEC 62443-4-2 CR 2.1 Authorization enforcement的需求,我们应该只分配最小权限给到人或者进程。所以我们会存在不同进程不同用户的场景。

以常见的Windows Service部署方式举例,默认情况下可能都是以高权限的LocalSystem账户运行。但理论上绝大多数Windows Service都可以被降级为Local Service账户。

数据保护

  • 相同ApplicationName,以共享同一个DataProtectorProvider。
  • 相同Purpose,以共享同一个DataProtector。
  • DPAPI的密钥存储位置,要求多Application / Web Service能够访问,以共享同一个密钥。
  • 对密钥本身可再做一次LocalMachine相关的加密(注意这里是机器相关,而不是用户相关)。

数据存储

  • 同样要求通过环境变量存储敏感数据,如Password。
  • 环境变量由用户(假定为LocalSystem)环境变量变更为System环境变量。
  • 使用非固定密钥的Development环境无以上要求。

非共享密钥向共享密钥场景的升级

原则上不推荐上述场景的升级,就和接口设计一样,敏感数据保护的安全设计,从最初就应该是稳定的,而不是轻易改变的。如果密钥的变更在我们的设计中是可以轻易实现的,那么别有用心的用户突破约束也不会是一件很难的事情。

升级理论上存在以下场景:

  • 单Application简单保护,向多Application / Web Service单用户的升级。
  • 单Application简单保护,向多Application / Web Service多用户的升级。
  • 多Application / Web Service单用户保护,向多Application / Web Service多用户的升级。

在不变更用户的情况下,处理起来较为简单。核心原则就是为多Application/ Web Service共享ApplicationName和Purpose。ApplicationName和Purpose并不是敏感信息,升级也需要通过修改源代码来重新发布程序。

变更用户则要复杂许多,我们需要通过原用户使用原ApplicationName和Purpose对数据做Unprotect。

再通过新用户产生新密钥到多Application / Web Service共享的位置,然后还需要新用户使用新ApplicationName和Purpose对数据做Protect。

在生产环境,这通常会导致一系列灾难的发生。我希望你永远不需要这么做。

一些值得关注的点

  • ASP.NET Core依赖注入拿到的ProtectorProvider,会基于应用程序的Content Root路径做应用隔离。使得不同程序的Protector对象不共享。
  • 即使共享物理密钥,ApplicationName不同仍会被隔离。
  • DPAPI密钥存储的位置和Windows以及用户相关,不完全可控。
    • 密钥将保存到 %LOCALAPPDATA%\ASP.NET\DataProtection-Keys 文件夹
    • LocalSystem用户对应的位置
      • C:\Windows\System32\config\systemprofile\AppData\Local\ASP.NET\DataProtection-Keys
  • 给环境变量添加前缀能够有效避免重名
  • LocalSystem的用户环境变量,双刃剑。
    • 普通用户不可见,可有效避免来自用户的修改。
    • 对开发调试不友好。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-12-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JusterZhu 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景故事
  • 敏感信息的识别
  • .NET对敏感信息的保护和存储
    • ASP.NET Core Data Protection API
    • 敏感信息的存储
    • .NET Configuration
  • 单一应用程序的数据保护和存储
    • 数据保护
    • 数据存储
  • 多应用程序单用户共享保护数据的场景
    • 数据保护
    • 数据存储
  • 区分Development和Production环境
    • 数据保护
    • 数据存储
  • 多用户场景对相同数据的保护和存储
    • 数据保护
    • 数据存储
  • 非共享密钥向共享密钥场景的升级
  • 一些值得关注的点
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档