0%

QA视角下的API安全测试-上篇

最近工作在一个跨国银行的项目上,整个项目是为客户构建一个面向终端用户的银行应用程序,包括Android、iOS、Web三前端及其配套的后端系统。我所在的团队负责其中的注册登录、会话管理、以及用户数据等和安全息息相关的部分。项目中,我们遇到了很多认证授权的具体实现及其测试需求,基于这样的背景,我觉得有必要对”以QA的视角、以API为对象、以安全为重点”的API安全测试进行一些整理总结,遂赘此文于斯。

安全测试向来都是质量工程师和安全工程师所共同关注的交叉地带,有时候甚至非常不幸的是混沌地带。对应用程序或系统而言,质量工程师关注的重点通常都是功能实现,安全作为非功能需求中的一环,虽然所有人都不会质疑其重要性,但落实到具体的保障手段上来说,对一般的质量工程师而言,还是缺乏相应的金刚钻。当然,和质量类似,安全也不是测试出来的,它需要全局性的、流程性的保障手段,所以,相较于单纯的测试,我们现在更注重SDL、BSI、NIST、CLASP这些基于流程、过程、以及全生命周期的综合性安全保障方案。即便如此,对QA而言,掌握基本的安全测试理念和技能,在日常测试工作中更有目的性和针对性的实施和安全相关的测试活动,还是非常有必要的。毕竟,对团队来说,大家还是期望在提交渗透测试之前能够有一些基本的安全信心。

在软件开发的过程中,和安全相关的实体是很多的,从传统的前端应用、后端服务,到基础设施、乃至业务逻辑本身都可能存在安全风险,我们这里将以QA的视角,单独聚焦后端API的安全测试问题。

API的类型与技术

对于QA来说,要想做好某项测试(无论是功能需求还是非功能需求),了解被测对象一定是第一步,对于API来说亦是如此。那么,什么是API呢?Application Programming Interface,即应用程序编程接口,其具体的描述,我就不去抄维基百科了,感兴趣的同学可以自行查阅。这里值得强调的是,有些同学可能会直接把API等价为API服务,即我们通常所说的”后端API服务”或者”后端API接口”,这是不确切的,API的范畴是远大于API服务的。

API的类型

软件技术发展至今,API可以被大致分为四种类型:类库型API、操作系统型API、远程应用型API、以及Web应用型API:

  • 类库型API,最为常见的一种API,我们平常广泛使用的各种编程语言中的预定义接口函数都是类库型API,比如NodeJS的内建模块提供的path.dirname、Python的图像处理库Pillow提供的ImageFile.Parser等等;
  • 操作系统型API,这类API通常都是和操作系统进行直接交互的接口,比如传统的Windows API和Linux标准库函数,以及Mobile开发中的Android和iOS库函数等;
  • 远程应用型API,这类API是为了使用相似的应用程序来完成类似的操作而创建的,它首先需要定义一套相同的规范,各个应用程序厂商再按照统一的规范完成自己的实现,从而达到一套API调用不同应用程序的目的。Java的JDBC就是远程应用程序型API的代表,它是一种规范,并由Sum公司提供了完整的接口,然后各个数据库厂商,比如Oracle、SQL Server、MySql等,再按照这一接口完成自己的实现,其中,MySql的JDBC实现就是MySQL Connector。当然,对广大QA同学来说,还有一个更加亲切的例子,那就是Selenium WebDriver。WebDriver也是一套规范,各家浏览器厂商基于这套规范完成了自己的WebDriver实现,比如Google提供的ChromeDriver,Mozilla提供的FirefoxDriver;
  • Web应用型API,好了,这才是大家最喜闻乐见的”后端API”或者”后端接口”。其特点也是显而易见的,即以Web服务的方式对外提供接口,其使用不局限于操作系统、平台、以及编程语言,广泛的应用于各种B/S、C/S系统中;

当然,我们今天讨论的话题是API的安全测试,关注的重点是Web应用型的API(后文中简称Web API或API),但这并不表示其它类型的API就不存在安全问题。事实上,在服务端的安全事件中,Web API有时仅仅是安全测试或者攻防的前线,真正的致命漏洞也可能隐秘在其它类型的API当中。比如,我们在使用npm audit进行安全检查时,经常会发现一些有安全问题的包,这些包绝大多数都是类库型API,它们不被用来直接构建Web API,却着实可能对文件IO、数据库读写等敏感信息操作造成隐患。作为QA,通常情况下我们很少有契机、也缺乏足够的能力对特定类库型API进行安全方面的审查,其相关问题往往需要安全和领域专家去进行深入剖析。所以,关注和增强对Web API的安全测试,在入口处降低暴露安全问题的几率,才是我们QA力所能及且行之有效的安全保障之道。

Web API的技术特点

2000年以来,Web API得到了快速的发展,其技术形式和应用场景都非常的丰富,因此也被称为”现代API”。如果要对现代API进行归类划分,我们甚至可以从不同的维度来定义API。

基于技术实现的划分

多样的技术实现,是当代API最大的特点,当然,这里的技术指代的是技术规范,而非特定的编程语言。具体来说,如今的API可以按照技术实现进行以下划分:

  • SOAP API,以XML为数据载体、通过HTTP协议进行传输的服务接口,SOAP API在当代API中已经是很陈旧的技术了,但由于早期的使用量较大,如今在很多大型企业中还仍在沿用;
  • REST API,广泛使用HTTP协议加JSON的数据格式,是当下最主要的API技术形式;
  • GraphQL API, 使用Facebook提出的GraphQL查询语言构建服务接口,需要预定义Scheme且在服务端和客户端之间共享,尤其适用于树状结构的数据获取;
  • gRPC API,基于Google提出的gRPC框架构建服务接口,使用Protocol Buffers对传输数据进行序列化后进行远端方法调用,其特点是传输相同数据量时的速度快于其它类型的Web API;
  • 其它类型的API,除了SOAP、REST、GraphQL、gRPC这四种技术,当代API还有一些小众的技术在特定场景下持续使用,比如XML-RPC、JMS、WebSocket以及IoT设备单独使用的接口技术等等,其中,大家对使用JMS技术实现的产品可能更加耳熟能详一些,比如常见的Kafka、Rabbit MQ;

基于终端消费者身份的划分

构建API的目的一定是用于消费的(Consume),那么根据消费者的身份,又可以将Web API进行如下划分:

  • 公共API,API服务对企业外部开放,目前大多数的头部互联网企业都开放了自己的公共API,比如Google API、百度和腾讯的开放API等等。这些API的接口开放给公众使用,但数据本身毫无疑问属于企业,且都需要专属凭证才能进行访问;
  • 私有API,API服务仅对企业自身内部开放,通常被各种企业防火墙或者安全网关裹得严严实实,外部无法触及,我们常见的企业内部的微服务系统就都是由私有API构成的;
  • 混合API,顾名思义,兼顾外部公众访问和内部私有访问的API服务,比如,某企业的API服务本来都是私有API,为了给它的战略合作伙伴企业共享部分数据而开通的、可以被外部有限访问的API服务,就可能是混合API;

值得一提的是,还有一种与公共API、私有API、混合API非常类似的划分,即:外部API、内部API、共享API。

基于功能设计的划分

当把类似MVC这样的代码设计风格应用到复杂系统的设计中时,组成整个系统的API服务也就进行了相应的层级划分:

  • 系统层API,负责实际管控具体的系统内部资源,从传统的数据库、文件资源到传感器、执行机等物理器件都由系统层API操控;
  • 过程层API,根据预定义的逻辑进行真实场景下的业务处理,相当于系统的大脑核心;
  • 表现层API,主要负责给前端应用程序提供数据和操作接口,我们常说的BFF就属于表现层API;

好了,对API的基础内容我们就先聊到这里。也许有同学会好奇为什么要在讲安全测试之前”废话”这么多API基础,那是因为在对API进行有目的的安全测试之前,我们首先要做的一定是对目标API进行尽可能完备的拿捏,这就包括识别被测API的实现技术、了解API在整个系统当中的功能、位置、及其消费对象。这些信息往往可以通过查阅系统架构图、业务时序图、网络拓扑图、或者直接向TL、架构师询问来获取。唯有准确和清晰地掌握了这些信息,才能在测试开始前帮我们明确安全测试的方式方向,以及制定相应的测试计划。要知道,QA毕竟不是安全专家,绝大多数都不具备横向多领域、纵向深层次的安全缺陷定位能力,在面对项目的安全测试需求时,往往需要现学现卖、边了解边测试,那么这个时候,正确的学习和了解方向就是非常重要的。举个例子,REST API和SOAP API的安全规范是完全不同的,前者可能主要使用OAuth、OpenID Connect,而后者主要使用WS-*协议栈,如果在准备工作中混淆了,就会浪费大把的时间。再比如,同样技术栈的两个API,一个是外部API、一个是内部API,它们面对的安全风险是完全不同的,有些外部API可能需要多重认证,而有些内部API甚至可以裸奔,那么对它们的安全测试需求也就完全不同,这就需要更加针对性的去计划开展测试。

QA理解API

常见的API安全测试切点

我们前面说过,安全问题是一个系统性的、工程性的问题,对整个被测系统的安全保障需要贯穿整个软件开发周期,不是一两次测试活动就能一蹴而就的。而当真正落实到具体执行的安全测试活动上来时,大家最快联想到的应该都是渗透测试。的确,作为安全保障工作中非常重要的一环,渗透测试的地位举足轻重。但遗憾的是,对于大众QA来说,基本都不具备开展渗透测试的知识储备和技术能力,所以渗透测试一般都由专门的安全专家来操刀。而且在很多项目上,客户基于对客观性的考量,可能会更加倾向于引入第三方的专业安全团队来开展渗透测试。所以,对大多数的QA同学来说,渗透测试一般不作为我们开展安全测试的方向。

当然,这并不表示QA不需要去学习渗透测试,相反的,我个人非常鼓励对渗透测试感兴趣的QA同学去深入学习和实践渗透测试。

那撇开渗透测试,QA还能如何开展有目的的安全测试呢?在QA的测试工具箱中,有一种可谓万金油的测试技术叫做”基于经验的测试”,其常用的技术手段包括:错误推测、探索性测试、基于检查表的测试。只要对这些测试技术和思路方法加以活用,我们就能规划出一些QA力所能及的安全测试套装:

  • 风险推测,功能性的错误推荐技术提示我们可以通过对比被测应用的既往行为,或者其它类似应用的失效表现来预估被测应用可能出现的错误,类似的,我们同样可以参考其他API在类似接口上出现过的安全问题来预估当前被测API可能存在的安全缺陷,这其实和威胁建模有许多相似之处。错误推测技术的一个系统化方法是创建一个可能的缺陷列表,我们也可以类似的给被测API创建一个可能的安全问题列表,从而进行逐项校验;
  • 探索性测试,将探索性测试的思路应用到安全测试中,对QA来说是非常有益的。我们说过,QA通常缺乏开展渗透测试的能力,具体的表现就是QA开展的安全测试活动会显得随意而缺乏目的性。比如,QA可能会对SQL注入”情有独钟”,对所有API输入见一个查一个,但却并不清楚自己到底想通过注入来达到什么目的。而使用探索性测试中的漫游测试思路,比如卖点测试法、破坏测试法等,就能帮助QA更好的组织安全测试的方向;
  • 基于检查表的测试,检查表是QA开展安全测试最有利的武器。在缺乏独立开展全面、深度的安全测试能力的情况下,通过检查表来规划和罗列尽量多的测试点,既能降低对QA个体知识储备的依赖,又能确保对必要检查项目的覆盖。安全测试的检查表既包括常见安全问题的测试点,比如对不受认证保护的API接口的排查,也包括对被测API安全配置的检查点,比如在生产环境不允许开启Swagger UI功能;

常见的API安全漏洞

要将基于经验的测试应用到安全测试中去,一个必须面对的问题就是哪里去找这些”经验”。QA毕竟不是安全专员,在安全问题方面获取的信息和积累的经验通常是非常有限的。但幸运的是,相较于质量问题的千繁万种,安全问题的类型与实例都有较清晰的归纳与分类,最重要的是有CWE、NVD这样统一的安全漏洞数据库,帮我们收录了每年发生的重要安全漏洞,也有OWASP这样的全球性的安全组织,帮我们归类和梳理众多的安全问题。所以,从OWASP学习安全知识,从CWE、NVD查询真实的安全漏洞,是QA快速刷经验的重要途径。

说到OWASP,就不得不提OWASP Top 10,作为众多Web安全问题的”风向标杆”,Top 10向来是安全专员最关注的指导信息之一。OWASP Top 10面向整个Web领域,将Web前端应用、后端服务、以及服务器的安全问题都囊括其中。而对于我们今天讨论的API安全测试,OWASP在2019年底正式发布了OWASP API Security Top 10,顾名思义,就是聚焦API安全问题的Top 10。QA可以对这些常见的安全问题进行快速理解,然后在自己的项目中因地制宜的实施有针对性的测试活动。这篇文章后面的类容,就以OWASP API Security Top 10中的问题为对象,介绍我们QA力所能及的安全保障手段。

owasp-api_security_top10

API1-失效的对象级授权

正常情况下,调用者通过登录认证后仅能访问自己被授权访问的资源,而授权验证失效的API允许调用者在通过登录认证后访问不属于它自己的资源。比如,调用者在登录后,可以访问/client/ID001/profile的资源,其中ID001是调用者自己的用户ID,而通过更换用户ID,调用者能够访问其他用户的资源/client/ID003/profile

QA可以采取的安全保障工作

  • 对于所有的资源访问接口,通过更换查询参数,特别是用于身份识别的参数,来测试授权实现的正确性和完整性;
  • 可自动化测试案例;

API2-失效的用户认证

API在身份认证的实现上存在缺陷或干脆就没有身份认证,将导致攻击者可以随意获取数据。比如API的身份认证允许使用弱密码,或者无锁定机制而被暴力破解,又或者没有设置或验证AccessToken的过期时间等等;

QA可以采取的安全保障工作

  • 如果我们自己的团队负责实施了API的认证实现,那么QA一定要对认证流程了然于心,清楚认证流程时序图上的每一个步骤;
  • 向开发人员询问API采用的是哪种认证方式,确保团队使用的是业界标准的认证方式,而不是自己造轮子。尽可能的学习了解对应的认证方式,以确保团队正确地使用了该认证方式,比如对基于AccessToken的认证方式要正确设置和校验过期时间等;
  • 测试验证API的登录接口、忘记密码接口、以及重置密码接口都实施了访问控制策略,以防御暴力破解、撞库、密码喷洒等攻击;
  • 结合业务需求禁止弱密码的使用;
  • 确保API Keys不被单独用于用户认证;

API3-过度的数据暴露

API在响应客户端请求时,返回了超出请求需要的数据,特别是敏感数据。比如查询用户基本信息时返回了用户身份证号、密码,又或者查询用户订单信息时返回了用户账号信息等;

QA可以采取的安全保障工作

  • 测试验证所有的API都仅仅返回业务需要的数据,无用的数据绝不返回,特别是敏感数据;

API4-缺乏资源和速率控制

API在设计时没有对资源与速率做访问限制,比如允许客户端超高频的访问资源,或者对文件上传的接口不设大小限制,最终导致DoS和暴力攻击;

QA可以采取的安全保障工作

  • 和团队一起确认API在功能层面或者网络层面有相应的访问速率控制策略且实施到位;
  • 使用大文件测试文件上传接口,验证其对API功能和性能的影响;
  • 对API请求中涉及资源获取的参数进行破坏测试,比如使用很大的值测试分页查询中的size/api/users?page=1&size=999999999

API5-失效的功能级授权

API在设计实现时,对管理类接口妄想通过隐藏来规避风险而未做认证管理。比如,客户端可以使用GET请求访问/API/shop/customer/ID001来获取用户ID001的数据,攻击者可以通过猜测,使用POST请求访问/API/shop/customer来尝试创建非法数据(这些都是标准的REST接口定义风格,非常容易猜测),如果/API/shop/customer正好是一个只有管理员才知道的方法且没做认证管理,就可能允许攻击的成功。再比如,看到/api/users/xxx这样的接口,很容易就能联想到/api/admins/xxx这样的接口,后者如果不做认证管理,就可能出现风险;

QA可以采取的安全保障工作

  • 测试验证所有的管理控制接口都实施了相应的认证控制策略,且认证策略都基于特定的角色权限控制;
  • 如果团队是基于既有的认证授权服务进行的定制开发,比如基于Keycloak、Forgerock进行开发,那么一定要校验原始服务的各种默认管理接口,确保没有在高环境上开启不必要的接口;

API6-批量分配

通过API接口创建或修改数据时,很多时候会使用对象及其属性,如果对这些接口的对象属性缺少过滤,就会导致数据被篡改。比如,我们经常会使用POST或者PUT请求来创建或者修改数据,当修改的数据以对象属性的方式存在时,比如user.name、user.age等,我们正常请求的payload应该是{“user”: { “name”: “customer”, “age”: 18 }},而攻击者可能添加额外的属性来发起请求,比如{“user”: { “name”: “customer”, “age”: 18, “is_admin”: 1 }},如果API没有对这些属性进行过滤就有可能造成数据篡改;

QA可以采取的安全保障工作

  • 测试验证所有使用对象数据作为payload的接口,比如,先使用GET请求获取较完整的有效对象属性,再对POST或PUT等请求的payload赋值额外的有效属性来进行测试;
  • 可以自动化测试案例

API7-安全性配置错误

API本身也是应用程序,部署在特定的服务器或者云端,期间就会有一些与安全相关的应用级或系统级配置项,这些配置项如果配置不当就可能造成安全事故。比如禁用或者错误的配置了TLS,或者在生产环境开启了Swagger UI、辅助测试接口等本来只应该在开发测试环境开启的功能,又或者配置不当将服务内部在遇到异常情况时的错误堆栈信息在接口处进行了返回;

QA可以采取的安全保障工作

  • 和团队一起校验API的相关安全配置有被正确设置;
  • 如果在低环境应用了辅助开发测试的接口或功能,一定要在高环境(预生产环境、生产环境)测试验证这些接口或功能是关闭或移除的;
  • 测试验证API在遇到内部异常时不会返回错误堆栈信息等多余信息,包括来自依赖服务的错误信息;
  • 测试验证没有开启多余的HTTP方法,比如对一个有效的GET请求,在相同接口上使用HEAD、POST、PUT、DELETE等不应该响应的HTTP方法进行测试;
  • 对于响应来自浏览器端请求的API,测试验证正确配置了CORS规则;

API8-注入

老少咸宜、人见人爱的注入,但凡API在实现上对接受到的数据缺乏相应的校验和过滤,就能被攻击者炸出翔来。常见的注入对象包括SQL/NoSQL/LDAP的查询语句、系统命令行参数、XML解析、以及ORM/ODM。API6-批量分配中的漏洞就常常是和注入相结合来进行攻击的,比如一个接受上传视频的服务,它在创建视频时的API可能是/api/videos/new,接受的payload中包含{ …, “mp4_conversion_params”: “-v codec h264”, … },如果API对参数缺乏校验,攻击者可能以{ …, “mp4_conversion_params”: “-v codec h264 && rm -rf /“, … } 的方式发起攻击;

QA可以采取的安全保障工作

  • 测试验证所有可能用于数据存储、数据查询、命令执行的输入内容,包括URL的pathParameter、query、以及payload中的数据;
  • 对于注入的防御,一定不能依赖于前端应用,API侧必须完整实施所有的防注入策略。这一点QA必须要和团队达成一致且确保实施落实;

API9-资产管理不当

资产管理不当不属于可被直接利用的漏洞,但它却是其他漏洞或风险发生的温床。最常见的问题是在生产环境上运行多个版本的API,新版本的API虽然有较完整的安全保障措施,但对老版本的API却缺乏保护。比如,对API的访问速率通常都是在网关处控制的,当更新API版本时,在网关处更新了控制规则地址为/api/v2/booking,但却遗漏了老版本/api/v1/booking,而老版本的API又没有被关闭访问,就可能造成服务遭受DoS攻击。除此之外,API版本自身管理混乱、缺少必要的文档或文档长期不更新造成API维护困难、以及更新依赖服务版本不及时等等,都可能为其它安全隐患埋下伏笔;

QA可以采取的安全保障工作

  • 关注老版本API的生命周期,当最新版本API有安全相关的变动时,和团队一起评估对老版本API的影响;
  • 鼓励团队完成必要的API文档规建与更新;

API10-日志记录和监控不足

对API缺乏监控和日志管理,或者日志等级设计不合理、日志信息收集不全等,都可能导致在系统遭受攻击时,无法在第一时间掌握状况,从而错失采取防御措施的最佳时机,又或者在遭受攻击过后,无法统计和整理遭受破坏或损失的具体数据;

QA可以采取的安全保障工作

  • 提醒且确保团队对生产环境的日志和监控系统进行在线功能验证;
  • 测试验证日志系统收集的数据包含足够的信息,比如接口的调用者、请求发生的时间戳、日志的操作者、操作详情、操作对象、操作结果等;
  • 检查日志系统收集的数据不包括一些特殊信息,比如API的源代码片段、各种Token、用户的个人敏感信息、认证密码、加解密的密钥、以及数据库的链接字符串等;
  • QA或者开发团队有时并没有权限直接访问生产环境的日志与监控系统,这时可以请求客户的相关人员代为做相应的测试与检查;

小结

作为上篇的小结,我想再提一下,QA在API安全方面,虽然不具备安全专家那样的精湛技能和丰富经验,但也有一些QA独有的优势:

  • 可以更早的触及和发现隐患,安全专家或安全团队介入项目交付的时期通常都比较滞后,如果把期望都压在最后的渗透测试上,对交付的风险是比较大的。相对的,QA全程参与项目交付,能够更早的触及和发现隐患,降低风险发生的几率与修复隐患的成本,这和我们平常讲的测试左移是同样的道理;
  • 发现复杂场景下的安全隐患,第三方安全团队对API服务的安全测试或者审计通常都是基于模式或者经验来进行的,比如我们说的OWASP Top 10就是最典型的”经验之谈”,而有些具体项目下的安全隐患可能隐蔽在复杂的业务交互场景下,安全专员由于缺少相关的详细上下文,可能根本触及不到这样的隐患,又或者一些短期、临时上线的功能场景,可能压根儿就不会经过安全团队的把关,那么针对这样的场景,QA毫无疑问是最有机会发现问题的角色;
  • 安全测试的自动化,功能测试中,”发现缺陷 -> 修复缺陷 -> 添加相应的自动化回归测试”是非常常见的做法,这个套路在安全测试、特别是API的安全测试中也同样适用。安全专家是不会帮咋们写自动化测试的,但QA通常会非常乐于;

所以,发挥QA的角色优势,频繁的、碎片化的、有目的的开展安全保障工作,能够最大限度的提升API的安全性。

最后,附上一些常用的安全方面的查询和学习网站:
CVEhttps://cve.mitre.org
NVDhttps://nvd.nist.gov
CNNVDhttps://www.cnnvd.org.cn/home/childHome
OWASPhttps://owasp.org
OWASP Cheat Sheet: https://cheatsheetseries.owasp.org/

security_resource