在最近的一次项目中,测试了大量的API接口,发现接口安全的重点和常规Web系统的要求还是有很多区别的,这篇文章不分享如何测试接口,因为测试方法就和常规测试技术方式一样,所以本文主要目的在于经过上次项目后,笔者查询了一些接口API安全相关的资料,再结合自己金融行业系统的安全测试的经验,很浅显的对API相关知识做一些梳理介绍,然后分享如何做好接口安全,如果让自己来做接口安全设计,需要从哪些角度出发。
0x 01 API接口类型介绍
1.1 接口类型按照调用方式分为应用程序服务端对API调用与应用程序客户端(如:APP、浏览器)对API调用方式两种,可以将第一种简单理解成Server->API Server的通信,第二种理解成Client-> API Server的通信。
对于应用程序服务端对API调用,主要包含两种实现形式:
——应用程序服务端直接调用API(如REST、SOAP协议)。
——应用程序服务端使用API服务提供商提供的服务端SDK,间接访问API。
其中,服务端SDK主要实现API服务提供商通用接入算法的封装,为降低应用方接入开发难度,一般此类SDK不包含业务逻辑。
对于应用程序客户端对API调用方式,主要包含两种实现形式:
——客户端应用软件直接调用API。
——客户端应用软件使用API服务提供商提供的移动终端应用SDK,间接访问API。
1.2 接口类型按照使用范围可分为内部API、企业定制API 与外部API
内部API(Private APIs):指企业内部信息系统间的API,它促进了业务系统之间的信息互通,仅供企业内部开发者使用;
企业定制API(Partner APIs):指企业与特定的合作伙伴之间进行定制集成,目标是支持特定的业务流程或产品的API,有时甚至约定使用专有网络进行通信,比如银行“银企直联”模式属于此类范畴。
外部API(Public APIs):指API提供商广泛地面向应用方提供标准接口,供外部合作伙伴使用的API,较前两类API 更深入、更广泛地面向外部合作者提供服务。在安全测试中,我们接触最多的应该就是外部API。
0x 02 API接口安全级别
通过划分接口安全级别,根据接口不同的安全级别可采取不同的安全防护手段,根据金融行业对接口安全级别的划分原则,推广到其他行业接口安全级别,大致将接口安全级别分为两大类:
A2类接口:涉及资金交易与个人信息、账户信息的查询、删除、变更的相关的接口,这类接口应实施高等级的安全保护;
A1类接口:涉及相关产品介绍和服务信息查询类接口,这类接口不涉及资金交易和个人信息、账户信息,可采取通用等级的安全保护,示意图如下:
0x03 接口安全设计
3.1 涉及变量
App_ID:应用唯一标识, 是你的应用id,通过在API提供的开发者平台申请获取,或由API服务提供方主动下发;
App_Secret:通过在API提供的开发者平台申请获取,或由API服务提供方主动下发;App_ID与AppSecret在数据库中存在关联,App_ID和 app_secret 是成对出现的,AppSecret需要严格保密的,只需一次下载,不会在网络网络中进行传输,且需要定时更新;
数字证书:可向专业的CA机构申请,用于A2级别接口的双向认证、抗抵赖。
3.2 接口安全要点
3.2.1 认证和鉴权;
接口认证的目的是防止接口被任意应用调用,正常情况下,接口应只允许被授权过的应用调用,通过API服务提供方下发的App_ID与AppSecret、数字证书、公私钥对组合可识别应用身份,认证之后,需要根据App_ID开放不同接口给应用,完成鉴权,接口认证组合要素如下:
——App_ID、App_Secret。
——App_ID、数字证书。
——App_ID、公私钥对。
——上述三种方案的组合。
对于A2级别接口、应用方身份认证时,应使用包含数字证书或公私钥对的方式进行双向身份认证。
3.2.2 加密和签名
在接口调用数据传输中,对传输数据加密防止数据被窃听,针对A1级别安全接口,使用AppSecret签名防止数据被篡改,使用对称算法加密防止数据被中间人攻击,针对A2级别的接口安全,应使用数字证书进行签名完成双向认证,使用非对称加密算法加密防止数据被中间人攻击;
假设需要传递的业务参数是Request_Parameter=xx,则在请求中,还需要附带上App_ID,URL、以及防重放攻击的timestamp和nonce值,所以A1接口和 API Server的交互的步骤如下:
客户端:
str=”URL=xx&App_ID=xx&Request_Parameter=xx&timestamp=xx&nonce=xx”
计算签名值sign= HMAC(sort(str), AppSecret);
对数据包进行加密,可选择部分加密或者整包加密:Cipher_str=AES_Encrypt(str+sign)
向API服务提供商传输数据内容Cipher_str;
服务端:
消息解密str+sign=AES_Decrypt(Cipher_str);
服务端接收到请求后,根据timestamp和nonce判断请求是否为重放消息;
常规漏洞防护检测;
根据App_ID在数据库中查询对应的AppSecret,然后按照约定的签名算法进行签名,和上送签名sign进行比对,完成验签;
根据验签结果决定是否接收或拒绝请求,有些API可能会返回一个access_token,后续都使用access_token对API Sever进行访问,比如微信;
A1接口请求交互示意图如下:
A2接口和 API Server的交互的步骤如下:
客户端:
str=”URL=xx&App_ID=xx&Request_Parameter=xx&timestamp=xx&nonce=xx”
计算签名值sign= HMAC(sort(str)),再用数字证书对sign进行签名:new_sign=数字证书签名(sign);
使用API Sever公钥对数据包进行加密,可选择部分加密或者整包加密:Cipher=ServerPublicKey(str+new_sign)
向API服务提供商传输数据内容Cipher;
服务端:
API Sever私钥消息解密str+ new_sign =ServerPraviteKey(Cipher) ;
服务端接收到请求后,根据timestamp和nonce判断请求是否为重放消息;
常规漏洞防护检测;
使用应用程序公钥对new_sign验签,完成双向认证、抗抵赖检测;
根据验签结果决定是否接收或拒绝请求;
A2接口请求交互示意图如下:
3.2.3 常规漏洞防护
在API服务提供商接收到API数据请求后,完成解密之后,需要进行常规漏洞防护检测,比如sql注入、xss、RCE等等,这里不再赘述,可以通过开发框架中的提供好的函数或者开源的安全开发SDK完成。
3.2.4 数据合法性校验
数据合法性校验是每个系统都会有的校验、处理机制,只有在数据是合法的情况下才会进行数据处理,每个系统都有自己的验证规则,当然也可能有一些常规性的规则,比如参数的长度、参数的类型,参数的业务场景合法性等。
3.2.5 API限流
由于API接口所承载的业务不同,API接口被调用的频率也会不同,通过分析和监测API接口被访问和调用的频率来确保API接口未被攻击者攻击以及数据被泄漏,一般来说被攻击的API接口与正常接口调用情况在频率和调用总数上面都会出现较为明显的差异,因此通过统计API接口被访问的情况,进行限流等方式可以防护API出现被攻击者攻击甚至是拒绝服务的情况。