宝塔服务器面板,一键全能部署及管理,送你10850元礼包,点我领取

软件安全策略

@author:alkaid

生命以负熵为食 —— 《生命是什么》薛定谔

前文

见 软件安全策略-上

正文

对抗中间人

背景

在前文中提到的三大基石策略——身份认证、访问控制和会话管理,在通信过程都涉及到与远程服务器交换秘密信息,同时在实际的业务过程中,也包含了大量的个人隐私信息。
如果这些信息被窃取,可能会对社会、个人造成巨大的影响。

概念

在具体讨论怎么对抗中间人之前,我们首先来看看中间人到底是什么?

从名字来看,中间——那肯定是在什么之间。

信息系统常见几个重要的主体,应用、操作系统、网络链路、客户端、服务端,通信过程如下:
软件安全策略-下-风君雪科技博客

一般而言,我们所考虑的中间人攻击的情况是图中虚线的框框——网络设备,攻击者可能控制了相关的路由器或者交换机,进而对应用的相关数据包进行监听、篡改。

一般不考虑应用与操作系统、操作系统与网卡之间拦截,一方面由于这些操作都需要对客户端/服务端的操作系统进行控制,如果能进行控制,那么有其他更加丰富的方式获
取相关的数据,包括但不仅限于hook相关的技术、屏幕录像。 另一方面,由于需要获取操作系统的控制权,一般而言是个例,不具有普遍性,在资源有限的情况,不会进行考虑。同时在这类场景下,更关键是需要解决恶意攻击者获得操作系统控制权的问题。

当然,如果有特殊的要求确实需要纳入到考虑范围的情况,那肯定需要在应用层面去完成,自然是最方便的途径,从数据的源头进行防护,设计的要求同针对网络设备的中间人一致。

对抗中间人攻击,不可能去解决掉中间人,而不可能去保证每个人一个人的链路的安全。

需要解决如何在不可性的链路上去构建一个可信或者相对可信的链路。

风险与处理

风险其实在背景里已经提到了就是信息被窃取、篡改,而处理的解决方式就是需要去构建可信信道。

具体的风险可以细化成以下四种:

虚拟身份或者临时身份被窃取
重放
监听(隐私信息采集等)
业务数据包被篡改

从风险可知,构建的可信信道需要满足

数据被加密,防止被窃取身份,被采集信息

加密应该保证每个对象与对象之间不同(如果是现代密码学算法应该保证每组通信采用不同的密钥)。

需要支持完整性的校验
需要支持对抗重放数据——即每个数据包有自己的标识

已有技术

提到中间人,不得不提到的一定是SSL、TLS,以及结合http协议形成的https,一般情况其代码实现已经集成在操作系统中。
理想情况下,TLS或者SSL协议能够打成我们的目标,但是它们在构建可信信道的过程中,依赖于数字证书技术。如果不当使用数字证书,例如自签证书、不可信CA滥发证书,那么可信信道就无法构建。
无共享信息的可信信道,基本上无法建立,除了量子。
那么为了部分解决SSL/TLS的数字证书问题,只能采取增加部分预置信息的方式,例如HSTS——浏览器缓存证书,SSL Pinning——内置证书进行比较

注意事项

由于SSL/TLS是对抗中间人的完整性校验和对抗重放,重放的另一个威胁源来自客户端自身在应用层发起的请求,这类情况无法适用SSL/TLS
一般建议在应用层面的核心业务,再次实现完整性校验和对抗重放的技术。例如交易。

异常处理

渗透测试的小伙伴应该会这样的体会——只有当输入信息与我们预期的正常情况存在出入的时候,才会引起注意,例如页面500报错、异常的业务流程、预计之外数据输出。
所以异常可以算是一切攻击的源头,如果所有的情况都能符合预期,那么我想攻击者的途径应该会少很多吧。
可惜的是人非圣贤,异常难以避免。
对研发而言,我们希望异常越清晰越好,查看异常越简单越好,能够协助我们尽快的定位bug,分析业务。
在攻击者在挖掘漏洞的过程,同样希望异常越清晰越好,与开发者们的预期一致,在频繁的上线和更新代码的过程中,经常会遗忘掉这些暗门,从而使攻击者能够从研发留下的痕迹中收获不少敏感信息。
所幸的是目前部分框架已经支持对全局异常的统一处理
剩下的需要解决的是配置问题,在下文中也会单独的讲这个问题,不过在这个篇章里索性就先提一点。

研发人员和攻击者都关注异常信息,自然不可能把异常信息全都屏蔽,那么对于研发人员可能是一场灾难。
那么如何把两者划开来呢,测试环境自不必说,对于生产环境而言,攻击者能接触到的应用页面、通信的数据包,而研发人员在授权的情况下,理论上可以接触到所有数据的,所以我们可控制异常信息的输出,输出到攻击者无法接触的地方,例如操作系统的某个固定目录下、统一的日志收集平台。
当然有个后话,如何保证相关目录的安全、日志平台安全以及哪些数据需要隐藏又是我们需要继续考虑的问题。

注意事项

异常处理的手段其实在本质上并不能解决信息泄露的问题,只是通过对异常处理的控制,尽可能地降低从异常中获取的信息量,提高攻击者的攻击成本和利用难度,从而降低风险。

(没有任何回显,本身就是一种异常。只是造成这类异常的情况丰富且复杂,从而降低从异常中获取得信息量)
PS:信息量/信息熵等概念,可自行搜索了解,本质上是为了量化信息。

配置管理

对于应用系统而言,经常需要部署在不同的运行环境,我们引入了配置从而避免了因为环境的变动就需要对应用进行重新编码,重新测试的情况,同时各种各样的配置项可以支持各式各样的组件和程序不同的运行方式,极大的提高了效率。

场景一 不同的运行环境

跨平台的编程语言解决了应用需要在不同操作系统部署的问题,优化了大量的时间投入。但是它们没办法解决不同抽象的运行环境,例如开发环境、测试环境、准生产、生产环境,不同的抽象运行环境对应着不同的组件、网络以及信息安全的要求。

开发环境/测试环境:对于信息安全的要求应该是最低,同时也是输出信息最为丰富、系统最不稳定的。
准生产/生产环境:对于信息安全有明确的要求,仅保留必要的输出,系统最为稳定。

风险与处理

在从开发环境切换到准生产/生产环境,难免需要更新具体的配置,一般而言会考虑引入编译的配置选项来解决,实现一键切换,例如maven的profile属性,不同的属性值对应了不同的策略,包括不同的打包策略、不同的配置文件。
这类方式是提高系统可靠性的重要方式,但是也存在一些副作用,需要使用者进行控制。

如果管理不当,开发者有可能接触到生产环境的具体配置信息,对生产经营产生影响
如果打包策略/配置文件未进行检查和校验,导致多个环境信息被一起打包。
如果缺少对具体配置项的检查,导致生产环境采用了测试环境的配置,进而可能产生信息泄露事件。
各个组件(中间件、容器等)的配置。虽然目前有docker一类的容器技术,用于实现运行环境的标准化配置,但是标准化配置不是一个不再需要关注的点而是一个更加需要关注的点,试想如果某个标准化上配置存在弱口令账号或者所有的标准化环境共享一个账号,会带来什么样的风险。

场景二 日志管理

日志功能相关的组件越来越成熟,大多通过配置进行实现,索性就纳入到了配置管理模块。
日志是目前所有系统审计的重要依据,同时也是发现攻击者和内鬼的重要手段,但是随着SSL/TLS等相关加密方式普及,位于通信链路上的相关设备越来越难以捕获到明文信息,应用系统自身的日志显得越来越重要。 我想随着云相关技术的进一步推广,应用系统的日志会更加重要。
如何管理这些日志,采集哪些日志就是需要进行考虑的。

风险与处理

日志最好也能有全局的日志控制。
当然,如果需要最大发挥日志的价值,一般是需要汇集到统一的日志平台,用于支持搜索。而日志往往包含了最详尽的业务信息,从某种意义上而言,这些日志可能是在诱导犯罪。(不知道是不是对前文中关于临时身份有印象,拿到这些临时身份的令牌,就可以完成身份窃取)
一类风险是正式这些日志信息造成,我们需要有明确的规定有指导数据记录,例如敏感信息、个人隐私信息、令牌、身份等信息,不要存储全文,需要进行部分的模糊化。
另一类风险正是引入日志平台其本身带入的风险。
日志的具体配置不当,例如本地的日志文件存放到了web的相关目录,从而能直接访问,造成大量信息泄露。(相关实例可自行搜索)

场景三 权限配置

目前越来越来多的应用支持复杂的权限配置和资源配置,有效维护这类信息,能够大幅度降低安全风险。
具体涉及的权限内容,可查看访问控制策略章节了解

软件技术栈

概念

软件技术栈——我姑且这么写如果有更好的名称可以私信我,这里主要想提一提应用系统中那些无法进行掌控的第三方组件,例如java的第三方jar、框架、中间件。
对于现在的应用程序而言,从零开始的搭建已经有点不可能了,不是技术不可能,而是业务上不可能,我们需要速度,在已有轮子的前提下,肯定不需要再造轮子,即使造轮子,你有能力保证造的轮子就比别人的好使吗?
但是呢,这类第三方的代码与我们编写的代码在运行时共享的是同样的权限、系统资源,如果这些代码出现了问题,又当如何?

风险与处理

至少需要能管理、了解到底用了哪些第三方的代码。唯有这样,在相关的第三方出现安全问题时,能够快速响应,做到止损。(相关工具:SCA——软件成分分析软件)
尽可能不使用存在已知问题的组件,不使用停止维护/维护不当的第三方内容(如果是开源的,己方有能力维护可以不纳入考虑)。

敏感数据

敏感数据现在是属于法律法规领域最关注的一个点了,虽然互联网上的应用五花八门,但是所有这些虚拟身份的背后都是一个唯一的实体人。生命以负熵为食,人天生喜欢规律也是有规律的,大量数据可能能够重新去定义一个实体人,通过定向的投放去影响和控制人,甚至盗取这个人的现实身份,这也是为什么敏感数据会成为各国法律法规的关注点。
所以在应用系统设计的初期,我们必须需要明确哪些是所谓的敏感数据,以及围绕着敏感数据的生命周期要如何处置

哪些是敏感数据

个人隐私

CISSP ALL in One 在隐私章节里给出部分属于隐私的数据类型,如下:
软件安全策略-下-风君雪科技博客

敏感的业务数据

财务相关交易记录
…… 需要根据具体内容去决定

敏感数据的生命周期

一般而言,生命周期至少包括数据的产生、存储、使用、销毁,该过程映射到实际的应用系统中可能还需要进行更加细节的处理。

传输

应用系统涉及到信息交互,那么首先要新增的一个过程就是传输,在传输过程中的敏感信息要如何进行处理是需要进行明确。明文传输肯定是不行的。

产生

我觉得更明确的词,应该是采集。
采集就涉及到到底是采用完整的数据,还是部分关键即可,如果是部分关键,那么将采集出的数据直接转成Hash摘要可作为一种参考方式。

存储

避免明文存储
如果不需要明文的敏感数据,建议采用hash算法等方式转化数据,仅用于对比
如果需要明文的敏感数据进行操作,建议采用加密算法保障
其他情况

使用

使用可能涉及到多个场景,例如客户端页面的展示、业务操作的需要,如不必要进行展示,尽量不进行展示。

销毁

一般这类敏感数据是需要提供销毁数据的功能的,是真正从数据库清空相关信息,而不是通过标志位实现的假删除方式

注意: 这里的说明,仅仅是提供敏感数据相关策略的参考,具体内容以相关的法律法规以及业务自行设计。

输入输出

概念

输入与输出,绝大多数的漏洞都在体现在这方面,假如一个系统完全没有输入和输出,开个玩笑,如果真有这个系统,有和没有又有什么区别?
输入与输出,这两个词虽然简单但是里面缺少了一个东西——主体,什么东西的输入输出。

假如实体服务器,那么输入输出基本上就是我们在通信链路上来回输送的数据,但是这些数据有点驳杂,没有办法再进一步的处理,唯一能做是采用一些全局的过滤器或者拦截器,但是误杀又太高。

所有站在这个维度,虽然实现起来相对容易,但是把握度的难度会比较困难

假如把实体的粒度划的再细一点,定义成应用软件(软件,而非系统)。从这个维度来看,系统的输入和输出类型就丰富来起来

输入:来自文件系统上的文件、数据库中的数据、中间件/容器传递的业务数据、其他组件的数据输入、
输出:文件系统、数据库、其他组件、中间件/容器

此时的输入输出可以看得出与部分漏洞有了联系,例如与文件系统相关的文件上传漏洞、任意文件读取漏洞

记住,原则上一切的输入和输出都不可信,只是经过校验和过滤的数据才能提高可信度。

风险与处理

通过缩小实体的粒度,我们更加明确了输入与输出,后续的风险便是围绕着具体的输入信息和输出的信息进行分析,构建针对性的过滤和处理。
当然,这种方法因为缩小了粒度所以在实现上就要复杂的多,主要是分析工作量增大,需要有针对性。

引用

深度解读SSL/TLS实现
SpringBoot开发详解(六)– 异常统一管理以及AOP的使用