如何分析软件安全性需求
软件安全性需求是指系统可靠地控制、监控和审计谁能够在哪种资源上执行哪种动作的能力,以及检测安全漏洞并从中恢复的能力。
作者简介
Gavin,程序员、软件架构师、企业架构师,关注智能制造。
本文是专栏《智能制造系统架构》中的文章,其它文章请参阅入坑智能制造系统架构。
软件安全性需求是指系统可靠地控制、监控和审计谁能够在哪种资源上执行哪种动作的能力,以及检测安全漏洞并从中恢复的能力。
安全策略与安全机制
软件系统通过安全策略定义安全性需要。安全策略定义了系统对资源的控制和保证,以及应该给当事人赋予的表示,以确定对系统中的每种资源(或者每种类型的资源)有什么样的访问。典型的安全策略会根据系统内不同类型的当事人,各种类型的信息,以及每组当事人所需要的访问类型来定义信息访问策略。安全性策略还需要定义如何控制特定敏感系统操作的执行。策略也应该定义必须执行的信息完整性约束以及保护信息不会收到授权变更。
安全策略通过安全机制来保证。安全机制是执行安全策略确定规则所需的技术、配置选项以及过程,它还会提供系统所需的机密性、完整性、可说明性和可用性的保证。
常见安全机制包括:
- 验证、授权和审计
- 信息私有性和完整性机制
- 不可否认机制
- 系统可用性机制
- 安全监控机制
分析软件安全性需求的步骤
分析软件安全性需求的步骤包括:
- 确定敏感资源:首先要确定要确保哪些资源的安全。系统所有的安全性都需要由关键的关注点来驱动。
- 定义安全策略:通过安全策略定义谁应该被信任、对哪些系统资源做出什么样的访问(以及所有在这种访问上的约束,如限制在特定的时间段或者每周特定的几天)、系统需要确保的完整性,以及访问敏感资源时所需要的可说明性。策略一般应该根据资源和用户的分组来定义(通常基于组织的单元和角色),而不是列举大量特定的情况。并且注意策略不是设计,因此它需要定义哪种访问会提供给谁,而不是定义如何到达这种访问方式。
- 识别对系统的威胁:识别出对安全策略可能存在的威胁。识别威胁清晰地定义了需要保护什么,以及需要针对什么威胁来保护。
- 设计安全实现:设计系统范围的安全性基础架构,从而可以在面临威胁模型中的风险时执行系统安全策略。这个步骤中,要考虑使用特定的安全技术,像单点登录系统、网络防火墙、SSL通信链接安全性、加密技术、策略管理系统等。
- 评估安全风险:为系统设计好安全性基础架构之后,需要重新评估风险,考虑安全性基础架构是否达到了可接受的成本和风险之间的平衡。
安全性原则
安全性原则包括:
- 尽可能赋予最少量的权限:总是给安全性用户赋予他们执行任务所需的最少量权限。
- 保证最弱环节的安全性:识别并改善系统安全性的最弱环节,直到安全性风险达到一种可接受的等级。
- 深度防御:与其依赖于一种安全措施来应对系统的所有威胁,不如考虑对防御进行分层来提供更好的防护。
- 分离和划分:应该尽量清晰地分离不同的责任,从而在需要的情况下,把各种责任的权限分配给不同的用户,并划分系统不同部分的职责,以实现独立控制。
- 保持安全设计简单:安全性需求较强的系统需要足够简单,以使我们能够保证它的安全并加以验证。
- 不要依赖于隐晦:系统的设计假设潜在的攻击者知道它如何实现。
- 使用安全默认值:确保安全的默认行为对使用的系统安全性有效。
- 安全地出现故障:确保即使系统出现了故障,也能安全地处理。
- 假设外部实体不受信任:要确保所有外部实体在验证之前都是不受信任的,从而避免意料之外的情况违背安全性原则。
- 审计敏感事件:大多数系统都包含了大量与安全相关的关键事件,如重新设置密码,分配强大的角色,以及操作审计轨迹等。这些敏感事件需要安全地进行审计,从而监控对它们的使用。
安全性需求
在软件架构设计时,应该考虑如下安全性相关的需求:
遵守安全性原则
对用户进行身份验证
身份验证是要可靠地识别使用系统的参与者。特别是对于制造企业,随着网络化建设,互联网与企业的进一步融合,用户和设备及应用程序和数据正在向传统企业边界和控制区域之外迁移。这意味着,如果有人拥有正确的用户凭据,则他们将被允许进入他们请求的任何站点、应用程序或设备。这导致暴露的风险增加,从而瓦解了曾经值得信任的企业控制区域,并使许多公司面临数据泄露、恶意软件和勒索软件攻击的风险。因此企业网络的内部越来越不值得信任。因此,基于严格身份验证过程,定义了称为零信任的网络安全模式,只有经过身份验证和授权的用户和设备才能访问应用程序和数据。
具体要求包括:
- 唯一标识:系统中的每位参与者都应该由唯一标识
- 账户管理方式:账户的产生、修改、变更、删除以及身份认证应采用统一的身份认证平台来实现。当参与者可能需要通过多种身份验证技术在不同系统作多重登录时,推荐在不同的底层系统上使用某种形式的单点登录技术作统一层。
- 认证失败后的处理方式设计,防止黑客暴力猜测:连续失败登录后锁定账户。账户锁定后可以由系统管理员解锁,也可以在一段时间后自动解锁。
- 区分公共区域和受限区域:将站点分割为公共访问区域和受限访问区域,受限区域只能接受特定用户的访问,而且用户必须通过站点的身份验证。当未经认证的用户试图访问受限资源时,应用应自动提示用户认证。
- 使用强密码策略:内部系统的口令规则需要符合口令管理规则, 要求输入至少 8 位字符,其中要包含大写字母、小写字母、数字和特殊字符。
- 能够禁用账户:在系统受到威胁时使凭证失效或禁用账户,则可以避免遭受进一步的攻击。
- 不在用户存储中存储密码:如果必须验证密码,可以不实际存储密码。相反,可以存储一个单向哈希值,然后使用用户所提供的密码重新计算哈希值。为减少对用户存储的词典攻击威胁,可以使用强密码,并将随机 salt 值与该密码结合使用。
- 支持密码有效期:密码不应固定不变,而应作为常规密码维护的一部分,通过设置密码有效期对密码进行更改。
- 不在网络上以纯文本形式发送密码:以纯文本形式在网络上发送的密码容易被窃听。为了解决这一问题,应确保通信通道的安全,例如,使用 SSL 对数据流加密。
- 保护身份验证 Cookie:身份验证 cookie 被窃取意味着登录被窃取。可以通过加密和安全的通信通道来保护验证凭证。另外,还应限制验证凭证的有效期,以防止因重复攻击导致的欺骗威胁。
- 同一用户同时只允许登录一个:对进入保护区域的用户需要进行重新认证(比如从普通用户操作改变到管理员级别权限的操作、修改个人密码的操作)。
- 不使用多重关键字查找:使用多重关键字查找用户记录可能会导致SQL或LDAP注入问题。比如同时使用用户名和密码作为键来查找用户记录,且不检测SQL或LDAP注入,则任一字段都可能产生风险。
授权访问
一旦识别了参与者,授权就会涉及限制和强迫允许那些参与者在系统中能做什么。具体要求包括:
- 应用软件应包含用户权限分配和管理功能设计。如:
- 系统读、写、执行权限设计。
- 系统查看、配置、修改、删除、登录、运行等权限设计。
- 数据访问范围的权限设计
- 应用功能模块使用权限的设计
- 限制用户对系统级资源的访问(系统级资源包括文件、文件夹、注册表项、Active Directory 对象、数据库对象、事件日志等。)
- 应用使用的数据库账户必须是普通权限账户,只能访问允许的数据库;
- 应用启动进程的权限应遵循“最小授权”原则
- 应用使用的系统账号(运行环境中的)应遵循“最小授权”原则。不使用“Administrator”, “root”, “sa”, “sysman”, “Supervisor”或其它所有的特权用户被用来运行应用程序或连接到网站服务器,数据库,或中间件。
- 调用方被映射到应用程序逻辑中间层中的角色,并基于角色成员身份限制对类和方法的访问权限。使用由当前调用方的角色成员身份所确定的有限标识集来执行下游资源访问。
- 在条件允许的情况下,尽量采用统一的访问控制机制。
确保信息保密性
保密性确保只有信息的所有者以及他们选择的共享者才能够读取信息。
保护敏感信息,具体要求包括:
- 尽量避免存储机密:在软件中以完全安全的方式存储机密是不可能的。可以接触到服务器的系统管理员可以访问这些数据。例如,当仅仅是验证用户是否知道某个机密时,则没有必要存储该机密。在这种情况下,可以存储代表机密的哈希值,然后使用用户提供的值计算哈希值,以验证该用户是否知道该机密。
- 不要在代码中存储机密:不要在代码中对机密进行硬编码。即使不将源代码暴露在 Web 服务器上,但从编译过的可执行文件中仍然可以提取字符串常量。配置漏洞可能会允许攻击者检索可执行文件。
- 不要在永久性 cookie 中存储敏感数据:避免在永久性 cookie 中存储敏感数据。如果存储的是纯文本数据,最终用户能够看到并修改该数据。如果对其加密,必须考虑密钥管理。
- 不要使用 HTTP-GET 协议传递敏感数据:避免使用 HTTP-GET 协议存储敏感数据,因为该协议使用查询字符串传递数据。使用查询字符串不能确保敏感数据的安全性,因为查询字符串经常被服务器记录下来。
- 对数据进行加密或确保通信通道的安全:如果在网络上向客户端发送敏感数据,应对数据进行加密或确保通信通道的安全。通常的做法是在客户端与 Web 服务器之间使用 SSL。当应用系统无法达到此要求时可以通过网络访问控制等手段限制可以访问应用系统的用户。
- 不要向客户端泄漏信息:发生故障时,不要暴露将会导致信息泄漏的消息。例如,不要暴露包括函数名以及调试内部版本时出问题的行数的堆栈跟踪详细信息。应向客户端返回一般性错误消息。
- 记录详细的错误信息:向错误日志发送详细的错误消息。应该向服务或应用程序的客户发送最少量的信息,如一般性错误消息和自定义错误日志 ID,随后可以将这些信息映射到事件日志中的详细消息。确保没有记录密码或其他敏感数据。
- 捕捉异常:使用结构化异常处理机制,并捕捉异常现象。这样做可以避免将应用程序置于不协调的状态,这种状态可能会导致信息泄漏。它还有助于保护应用程序免受拒绝服务攻击。
选择合适的加密方法,具体要求包括:
- 不使用自创加密方法:成功开发出加密算法和例程是非常难的。因此,应尽量使用平台提供的经过验证和测试的加密服务。
- 使用正确的算法和密钥大小:选择了正确的算法非常重要,另外,应确保所使用的密钥大小能提供足够的安全级别。密钥越大,安全性越高。
- 确保加密密钥的安全:加密密钥是输入加密及解密进程的秘密数字。为保证加密数据的安全,必须保护好密钥
确保信息完整性
完整性确保信息在未授权的情况下不会被变更(特别是在消息传递的过程中)。正确的输入验证是防御目前应用程序攻击的最有效方法之一。具体要求包括:
- 对所有的输入进行安全验证:开始输入验证时,首先假定所有输入都是恶意的,除非有证据表明它们并无恶意。无论输入是来自服务、共享文件、用户还是数据库,只要其来源不在可信任的范围之内,就应对输入进行验证。
- 采用集中验证方法:将输入验证策略作为应用程序设计的核心元素。考虑集中式验证方法,例如,通过使用共享库中的公共验证和筛选代码。这可确保验证规则应用的一致性。此外,还能减少开发的工作量,且有助于以后的维护工作。
- 在服务器端进行验证:应使用服务器端代码执行其自身的验证。使用客户端验证可以造成攻击者绕过客户端或关闭客户端脚本例程(例如,通过禁用JavaScript 脚本)。
- 确保用户没有绕过检查:确保用户没有通过操作参数而绕过检查。防止最终用户可以通过浏览器地址文本框操作 URL 参数。
- 不信任 HTTP 头信息:HTTP 头在 HTTP 请求和响应开始时发送。应确保 Web 应用程序的任何安全决策都不是基于 HTTP 头中包含的信息,因为攻击者很容易操作 HTTP 头。
- 注意标准化问题:标准化是指将数据转化为标准形式的过程。接受输入文件名、URL或用户名时必须先进行标准化。
- 限制、拒绝和净化:输入输入验证的首选方法是从开始就限制允许输入的内容。按照已知的有效类型、模式和范围验证数据。使用以下策略:
- 限制输入:定义一个筛选器,根据类型、长度、格式和范围来筛选输入的数据。定义应用程序字段可以接受的数据输入,并强制应用该定义。拒绝一切有害数据。
- 验证数据的类型、长度、格式和范围:在适当的地方对输入数据使用强类型检查,检查字符串字段的长度,检查字符串的格式是否正确。
- 拒绝已知的有害输入:要拒绝有害数据,需假定应用程序知道恶意输入的所有变体。
- 净化输入:向客户端写回数据时,对用户输入的数据进行 HTML 编码和 URL 编码检查,过滤特殊字符(包括HTML关键字以及&,\r\n,两个\n等字符)。
- SQL注入防范:进行数据库操作的时候,对用户提交的数据必须过滤 ’ ; -- 等特殊字符。
- XML注入防范:当使用XML文件格式存储数据时,若使用Xpath和XSLT功能,必须过滤用户提交数据中的< > / ' = " 等字符。
确保可负责性
很多系统都要求某些或者所有用户对他们的动作负责。在信息系统中可能需要两种不同形式的可负责性:消息的审计和不可抵赖性。审计通过记录系统用户所执行的操作日志,用于确定特定的情况是如何发生的。不可抵赖性要求能够以某种方式确定地识别出消息的创建者,而让他无法抵赖。
审计的要求包括:
- 审核并记录跨应用层的访问:审核并记录跨应用层的访问,以便用于认可。考虑应用程序如何在多重应用层间传送调用方标识。
- 确保日志数据的安全:限制对日志数据的访问,加大了攻击者篡改日志数据以掩饰其攻击行为的难度。应将有权操作日志数据的个人数量减到最小。只为高度信任的账户(如管理员)授予访问权限。
- 定期备份和分析日志数据:如果从不对日志数据进行分析,则记录活动没有任何意义。应定期(至少一月一次)备份生产服务器上的日志数据。
保护可用性
系统可用性既包括可靠性、软件复制、灾难恢复等,也包括可用性相关的安全性内容,保护系统使其免受降低可用性的恶意攻击。这样的攻击叫做拒绝服务(Denial Of Service, Dos)。
应能设置系统会话时间,防止会话劫持和重复攻击的风险。
- 限制会话寿命:对于高度保护的应用系统,可将超时时间设置为5分钟,低风险的应用系统设置不能超过20分钟。
- 对身份验证 cookie 的内容进行加密:如果Cookie信息包含了身份验证信息,则必须对 cookie 内容进行加密。
整合安全性技术
安全性一般需要跨系统的多个部分来实现,所以需要对如何在系统中实现端到端的安全性尽早做出设计决定。在系统的安全设计方面,部分重要工作使确保安全性一致地实现,并且将不同部分的技术组合到一起,组成完整、整合的安全系统。
提供安全性管理
要确保计划和安全性实现能够得到有效的管理。
对配置管理必须的安全要求包括:
- 确保配置存储的安全:基于文本的配置文件、注册表和数据库是存储应用程序配置数据的常用方法。应避免在应用程序的 Web 空间使用配置文件,以防止可能出现的服务器配置漏洞导致配置文件被下载。应避免以纯文本形式存储机密,如数据库连接字符串或账户凭据。通过加密确保这些项目的安全,然后限制对包含加密数据的注册表项、文件或表的访问权限。
- 使用最少特权进程和服务账户:应用程序配置的一个重要方面是用于运行 Web 服务器进程的进程账户,以及用于访问下游资源和系统的服务账户。应确保为这些账户设置最少特权。
使用第三方的安全性基础架构
尽可能地策略执行推到系统的底层基础设备中。
检查列表
获取需求的检查列表
- 你是否确定了系统中包含的敏感资源?
- 你是否确定了一系列需要访问资源的用户?
- 你是否确定了系统对信息完整性保证的需求?
- 你是否确定了系统的可用性需求?
- 你是否确定了一种安全性策略,来定义系统所需要的安全性,包括允许哪些用户在哪些资源上执行哪些操作以及需要实施的信息完整性?
- 安全策略是否简单?
- 你是否已创建出正式的威胁模型,来识别系统所面临的安全性风险?
- 你是否考虑了系统外部人员和内部人员的威胁?
- 你是否考虑了系统外部人员和内部人员的威胁?
- 你是否考虑了系统的部署环境如何根据系统的威胁而改变?
- 你是否和利益相关者一起推出了示例场景,从而他们理解计划使用的安全策略以及系统所面临的安全性风险?
- 你是否与外部专家一起对安全性需求进行了评审?
架构定义的检查列表
- 你是否在威胁模型中按照要求程度说明了每种威胁?
- 你是否尽可能多地使用了第三方安全技术?
- 你是否为安全性解决方案创建了集成的总体设计?
- 在设计安全性基础架构的时候,你是否考虑了所有标准的安全性原则?
- 你的安全性基础架构是是否尽量简单?
- 你是否定义了如何识别违背安全性的情况以及如何从中恢复?
- 你是否对所有影响到的视图都应用了安全性视角?
- 外部专家是否评审了你的安全设计?
参考资料
- Software Systems Architecture, 2nd. 中文版 《软件系统架构》
- https://mp.weixin.qq.com/s/hRbgD6wcg8bMkKd1QfD1kA
- https://blog.csdn.net/momo_sleet/article/details/83054215
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)