在业务安全SDK测试中,最核心的一项工作是评估异常检测和加解密算法的效果。比如,加解密算法类似于黑盒子,如何来保证这个黑盒子的质量?数据敏感,样本少,如何快速生产测试数据样本?功能迭代,频繁发版,如何保证回归测试的质量与效率,覆盖更多的场景?本文将分享58同城在业务安全三端“移动端、H5、服务端”SDK方面的探索经验和当前取得的成果。
▲58同城测试架构师刘元
嘉宾介绍:58同城测试架构师,10年测试开发经验,从2020年至今,在58集团-技术工程平台群-研发管理部担任测试架构师。负责业务安全SDK项目的质量保证工作、集团性能测试平台开发工作,致力于从实践中总结经验,将优秀的方法论及工具平台引入到实际工作中。
以下是刘元老师在SACC2022大会的演讲实录:
一、背景介绍
什么是安全?安全是产品的属性之一,它和产品的功能、性能、稳定性归属于同一维度。那么,安全的目标是为了保障在产品当中,信息资产的保密性、完整性、可用性。其中,保密性是指未经授权的数据不可访问;完整性是指未经授权的数据不可篡改;可用性是指已授权的用户可正常的访问。
围绕这个目标,使用安全架构才能达成。在安全架构领域,有三道防线,分别是产品安全架构、安全技术体系架构、审计架构。结合实际落地的过程中,对它进行逻辑上的抽离,从而得到几个核心要素。也就是,业内比较认可的安全架构5A方法论:资产保护、身份认证、授权、访问控制、可审计。
在了解整个大背景之后,无论是对测试对象进行评审,还是对测试设计,包括最终的测试覆盖做评估,我们都要从目标、手段、5A方法论层面出发。
以时间轴划分,我们当前所处的是一个怎样的时间节点。首先,从最早以信息为中心的信息安全时代,历经了以网络为中心的网络安全时代,到现在以数据安全的采集、传输、使用、存储、转换、销毁整个全生命周期为中心的数据安全时代。
我国相继建立《网络安全法》、《数据安全法》、《个人信息保护法》,保护个人、组织与数据有关的权益,提升数据安全治理和数据开发利用水平,促进以数据为关键生产要素的数字经济发展。
2021年,大家都是在合规整改当中度过。我国三法建立之后,对整个工作影响较大,从原来的只需要保证信息安全、网络安全层面,过渡到以数据安全为主的保证范围之内,无论是用户的数据,还是企业自身的数据。
随着数据价值提升,越来越多的攻击目标转向企业的业务数据和用户数据。常见场景为被友商、黑产爬取产品价格、内容信息、运营活动等恶意行为。基于此,自2020年10月起,我们开启金盾项目,用来保护企业级业务数据安全。
上图是去年8月份,58同城本地版数据访问量大盘的情况。第一周,紫色线有明显的激增。当时,运营同事反馈数据不太正常,这个时间节点既没有节假日,也没有运营活动。通过排查,我们怀疑访问量激增的背后,是有人在抓取数据。但谁在抓取,抓取了多少量,我们并不知晓。
自此,我们顺势将金盾项目推到业务线当中做集成。经过一天时间,我们将SDK紧急集成到安卓iOS双端里面,通过紧急发版。同时,后端通过集成金盾的包,管控有异常拦截的接口。接着,我们发现的确有问题,有一批黑产不停地变换IP在抓取我们的数据。最后,我们对它进行了封禁处理。大家可以看到,从第六天开始,所有的线已经恢复正常。
金盾是一套针对接口请求和响应的安全防护体系,通过客户端SDK、服务端SDK、管理后台,来实现通信加解密、数据埋点、风控监测、异常拦截等能力。通过技术手段,针对移动应用“APK、IPA、WAP”与业务服务器之间的数据,通过“加密与解密”的方式,实现数据安全与业务安全。
所有配置类的信息都在管理后台进行统一的管控,新增、删减,里面会涉及到策略配置、白名单配置、降级配置等。服务端SDK和客户端SDK的能力都是一一对应的。比如,在客户端进行请求加密,这条请求达到服务端之后,服务端会进行相应的解密。在客户端,对这条请求进行签名,服务端会对它进行验签。
在解密完成之后,会把它下发到具体的业务逻辑代码当中,进行业务逻辑的处理。完成这部分之后,在数据回到客户端之前,我们会对响应进行加密,客户端接收到response之后,对响应进行解密,最终来进行数据渲染的操作。
对用户来说,整个流程是透明的,未加密的操作体验和已经数据加密的操作体验并没有太大的差异。我们希望,金盾以安全官的角色植入到各业务线,赋予业务线具有“数据安全与风险控制的能力”。
上图是金盾整体架构设计图,包括模块划分和数据流向。由于金盾以类中间件的方式存在,且受制于各个业务线“现状”,“业务形态”及“业务方式”,因此归纳出金盾项目的输出应该具有以下特质:集成方式规约化、业务低耦无侵入、场景业务定制化、数据分析可视化。
为了赋能整个金盾项目,需要兼顾不同的业务场景。58同城是一个多业务场景的产品,所以我们考虑不同业务线的现状,包括业务形态和业务方式。首先,金盾项目通过SDK嵌入的方式来做多端的集成,包括客户端、安卓、iOS、web、H5端,以及整个服务后端。
接着,在金盾SDK上定义一套私有化协议,就无须关心业务方、业务特征,以及业务能力,通过储存的方式来采集信息。在客户端启动时,进行金盾SDK的初始化,它会自主信息采集,包括端上环境监控、硬件信息的采集。这部分信息的采集主要是用来生成设备指纹,进行整体的规约。
如果这部分发现采集异常情况,我们可以自主的进行二次采集,尽可能保证数据的完备性。由于要将SDK集成到业务方,我们分别在安卓端基于安卓的拦截器做应用层。
在iOS端,提供工具包在真正发起业务请求的时候,判断标记,是否需要做加密传输,调用金盾SDK提供的能力进行加密,包括传输完成之后收到的解密。在服务端,以金盾注解的方式提供能力。
不同的业务对安全的要求不同,核心业务既需要做整个风险的监控,又需要对风险进行拦截处理。部分低频业务只需要进行监控,不需要其他操作。为了更好的支持不同定制化的需求,我们需要把这部分能力的控制交付给业务方来做。
站在业务角度,希望看到整个业务系统到模块维度,或者接口维度,不同统计的报表。涉及到大家对数据可视化的需求,又有不同的维度指标,所以我们会对它进行不同的拆分,通过不同的看板来支持。
我们来看整个金盾架构图,金盾综合服务管理平台除了一些配置之外,还会涉及到数据分析、统计等一些信息,这里面的交互我们用到了存储的中间件。
整个项目涉及到的代码工程,包括SDK代码、Demo代码、测试代码等。SDK本身是用来提供一些能力,我们不能在没有进行完备的测试之前,就将SDK集成到业务APP当中,去进行测试,原因在于本身业务APP的逻辑很复杂,SDK的功能也很复杂,一旦出现问题,我们很难去界定到底是SDK导致的,还是APP导致的。
所以,我们在做交付之前都会做独立的SDK的Demo,将SDK的每一项能力原则化的通过安卓、iOS的活动去触发能力。有了独立的SDK的Demo之后,进行功能测试、专项测试,包括性能损耗的评估、Demo运行的稳定等等。
需要强调的是,SDK的Demo由谁来开发,无论是最早做Demo,还是SDK功能迭代了,Demo要做相应的升级,在这里推荐大家由自己对应的RD来做这件事。
原因在于,当RD开始去写Demo时,会对自己开发的功能做自测。接下来,等到SDK的Demo交互到我们手中之后,我们可以在上面做一些迭代性功能的开发,这样可以保证本身体测的质量比较高,同时,像接口性质的Demo,我们一般都是自己来做。
上图是我们整体的实现流程,安卓端所有的交互都是基于拦截器实现。在真正发起请求前,会经过金盾SDK,对数据进行加密后发送。在接受数据之后,进行解密,交给前端进行渲染。出于安全的考虑,具体的加密方法已经做了模化处理。
在iOS端,由于拦截器实现并不是很稳定,所以我们选择以工具的方法的形式提供能力。它的触发时机和安卓端相同,在发起请求时调用工具方法进行加密,拿到响应数据之后,调用工具方法进行解密。
如果加密功能出现问题,我们有一套降级的策略,分为全局降级和url降级两个维度。面向测试对象,在了解整个产品的设计架构之后,最终所有的实现都是基于代码。
大家强调测试先行,在开发定义好接口文档之后,向服务端就可以写一些接口维度测试的用例,测试的脚本。接口文档对我们来说很重要,包括无论是新增的接口,还是接口的迭代版本。
二、SDK全流程质量保障
整个测试流程包括需求风险评估、测试排期、用例设计、数据准备、性能损耗评估、影响分析、风险覆盖、发布决策八个阶段。
在需求风险评估阶段,除了关注整个功能的优先级,还评估需求的业务风险,设计测试用例对风险进行有效的覆盖,建立需求与测试用例的映射关系,根据测试时间和业务风险确定测试范围和优先级,根据风险覆盖率进行软件发布的决策。
如果想要很好的管控风险,首先我们要对它进行量化。业务风险是用来量化一个需求对业务产生负面影响的可能性(业务风险=使用频率✖失效危害)。风险绝对权重根据每个需求的使用频率和失效危害计算获取。
风险相对权重是指每个需求相对同一层级中其他需求的业务风险权重百分比(相对权重=需求权重/总权重)。风险贡献度是指每个需求占所有需求的风险贡献百分比。
上图是一个实际用例,在SDK3.0项目里有四个核心的功能,包括金盾后端新增token接口,金盾后端2.0 SDK的升级兼容,静态检测的能力,以及动态配置策略。基于整个需求之后,对它进行用户故事的拆解。
拆解完成之后,我们会基于使用场景来定义它的使用频率等级和危害等级,这部分更多是由人工来敲定的。通过买点统计决定是否要对一些使用频率等级和危害等级进行调整,得到绝对权重和相对权重,最终得到的风险贡献度。
在测试排期阶段,会进行整体优先级的定义。在高优先级时,测试的人力和时间都会进行充分的保障。同时,我们会提前梳理出业务方的接入流程,最终交付形式等,包括在用例设计之前,整个测试策略的制订。表格的形式无论是常用的Excel,还是脑图都可以。
在用例设计环节,重点关注可接受的测试覆盖率,我们尽量将风险覆盖到一个可控的范围,它可支撑发版。如果线上发现问题,我们可以很好、很快地进行定位和修复,这里面既要保证效果,也要保证效率。
上图是整个测试流程的用例设计,我们会对它进行分模块,或者按照需求来进行用例的划分。划分完成之后,每个用例本身会有用例的优先级,其中包括用例类型划分,这里面会记录变更的时间,后面每个测试都会从这些用例中进行筛选。
业务级动态策略配置提供给业务方的一种能力,业务方基于采样传输过来的27种业务算子,与14种计算算子进行组合,对请求流量进行标记。举个例子,某IP:127.10.0.1以1次/秒请求接口,标记该IP,给出具体的处理结果。
由于27个业务算子加上14个计算算子,结合2种流量类型,包括WEB流量和APP流量,一共有105种可能情况。对于多条件组合,如何处理?我们使用全组合,把所有的组合全部列出来,或者选取其中的两个因子做组合。
我们希望用很少的测试用例,覆盖更多的业务风险。对此,我们找到了线性组合方法,在整个测试的精准度上面,包括最终如果发现问题的根因分析,它可以做到高精准度且易分析。
在数据准备阶段,涉及到种子数据的选取与数据生成策略的应用。那么,种子数据从哪里来?我们对真实的线上数据进行脱敏处理之后,才可以使用。我们还可以根据业务需求,手工构造一些数据。
基于种子数据的特征或规则,扩展开源比较常用的Faker库,自定义我们自己的规则,然后再去生成Faker数据。它符合真实数据的特征,也避免了非真实数据的一些其他问题,可以很好的扩充测试数据的丰富度。
为什么会有损耗?里面涉及到加解密,动静态校验,会引入性能的损耗。损耗可承受的范围是什么?经过我们的实验数据显示,1%损耗为最佳;3-5%损耗为可接受;8%损耗为拒绝,需要进行对应的优化。
我们基于开源的压测引擎,结合自研的任务调度系统,做了一个分布式压测平台。在性能测试平台里,我们主要关注两个点,第一个点是压力引擎的选择。第二个点是调度系统。
上图是数据级加密解密的工作流程,客户端在冷启动的时候,会去请求服务端获取并保存本次的token(身份识别认证),接下来进行正常的业务请求,将业务的明文请求进行参数的采集加密,并发到后端,在后端进行明文请求的解密,给到具体的业务接口。
此外,我们还会对它进行前期压测计划的设定。整个压测计划包括我们需要关注的一些指标,qps、CPU、平均响应时间、fullGC触发频率、错误率等。基于这个错误指标,我们来构造整个的加压模型和降压模型。
测试影响分析在回归测试中的应用原则:将回归测试用例关联到SDK代码,选择与最新git push相关联的用例。根据检测到缺陷的可能性对回归用例进行排序,优先执行容易暴露缺陷的用例。
这部分的执行工具是基于HttpRunner的接口自动化测试用例集,提供多步骤、多用例串联,针对具体值的校验。对于大家,学习的成本较低,可以很快入门。
上图是风险覆盖率以及测试用例的执行情况。首先,我们本次新增的功能要百分之百执行,基于风险贡献度和执行覆盖率,最终计算得出风险的覆盖率。
有了以上的数据,就可以得到发布决策的结论,98%的业务风险已经被测试的覆盖并通过,没有执行失败的情况。同时有将近1.63的业务风险有测试用例但未执行,没有任何的业务风险,没有无用例覆盖的情况,那么我们认为这次测试的质量保证工作成功,可以对业务线进行交付。
三、风控评估和总结思考
服务端风控主要以接口监控为主,通过“系统级静态校验”、“业务级动态策略配置”和“数据级加密解密”执行在线实时标记与拦截。以“终端监测”+“风控监测”融合数据为基础,通过异常采集项的多维组合构建“高危”、“中危”和“低危”评估模型,并以此为准则与业务方进行相关沟通与异常排查。
针对一些中危或低危用户,我们会对它进行挑战验证码的发起,然后进行人工的二次渲染的挑战。我们会在相对短的时间里,变换不同的验证形态,从而进行升级或者降级处理,最终根据业务方需要及配置指导,实施“挑战”、“标记”
与“拦截”功能。
数据安全领域需要敬畏对手。针对新项目测试,我们应该怎样做?流程和工具都是为人服务的,不拘泥于此;更应注重项目前人积累,注重行业趋势方向;敢于尝试,敢于试错;知其然知其所以然:业务背景、技术细节。