应用接口的安全方案设计
文章目录
鉴于当前日益严峻的行业竞争和用户的安全忧虑,我司近期上线了对全接口的安全监控,以下记录了方案设计过程中的一些想法。
HTTPS安全吗?
HTTPS可以在一定程度上隐藏接口调用的路径和参数,但是如果使用不当,依然会暴露在MIM攻击下,现在流行的网络调试工具都可以支持MIM。如Charles:
Surge:
在MIM攻击下,通过HTTPS的请求依旧一览无余。所以我们需要一个更为可靠的接口加密方案,来抵御爬虫等针对接口的攻击。
案例分析
先来看看当前市面上一个比较成熟的产品的接口机密方案。
可以看到所有的接口请求都带着一个key
字段,这个字段用于验证这个请求是否合法,无论是修改 key
字段或者param
中携带的请求参数,都会返回签名认证失败
的提示。
我们通过反编译部分代码后了解到,这个方案通过给明文参数添加一个混淆值之后执行一个单向hash算法sha1
获取一个用于校验的字段key。
这个方案安全吗?
单向hash的缺点就在于不可逆(排除碰撞的可能),由于http是无状态的,计算单向hash传入的参数都需要显式传递给后端,或者取前后端预先约定好的一个值,这就意味着,如果计算单向hash的算法暴露了,只需要根据算法计算对应的hash值,就可以很容易的构造出一个合法的请求。 而且,如果方案暴露,所有接口都无一幸免,因为参数都是明文,对于所有请求加密都形同虚设。 在反编译技术已经非常非常成熟的今天,这个算法的暴露基本是时间问题。 具体反编译和分析过程在下一篇博文中介绍。
我们的方案设计
如图所示:
这里就不详叙AES和RSA的相关细节。 大致可以认为,AES是一种对称加密算法,RSA是一种非对称加密算法,仅仅通过密文来试图解密明文都是不可能的(密钥长度足够)。 读懂了这张图,就基本能明白这个方案的设计。补充几点设计的细节:
为什么不采用案例中的方案
案例中的参数以明文的方式传输,如果hash值的计算算法被通过反编译暴露,所有接口都同时受到威胁。 这个方案可以在加密方案暴露之后,通过保护明文请求参数提高接口的安全。
为什么不直接对请求参数采用非对称加密
对称加密和非对称加密在计算消耗上存在显著的差距,具体可以参见:AES和RSA加密算法调研 如果所有接口都采用非对称加密,对客户端和服务器端都会带来巨大的计算压力,从而严重影响用户体验。
AES密钥的生成技巧
- AES可以由客户端在每次请求的时候生成,确保每个请求生成的AES密钥的唯一性,后台通过校验AES密钥的唯一性可以监控到爬虫的重放攻击。为了监控AES密钥的唯一性,后台存放和查询的压力会逐渐提升,所以可以通过存放在redis的方式,并通过ttl来控制记录的存活时间。
- 如上一条所述后台记录的AES密钥是有一定存活时间的,意味着超过这个存活时间,就无法监控到重放攻击,所以可以在AES密钥中携带时间信息,如果后台监控到当前时间和AES密钥中携带的时间超过了后台记录的存活时间,也可以记录为可疑请求。
是否安全?
如果要破解这个方案,需要同时满足以下条件:
- 通过反编译或者其他方式获取了RSA的加密公钥
- 通过反编译或者其他方式获取了AES密钥的生成规则
- 通过反编译或者其他方式获取了请求参数的结构
同时满足着三个条件是有可能的,但是不同于上文中介绍的案例,在接口重放成本上是有很显著的差距的,如果配合后台监控得当,基本可以把恶意用户及时禁用。 如果客户端配合得当,通过代码混淆等方式增加反编译的难度,保护加密公钥,就能很大程度拦住恶意用户。
服务端如何无痛的接入当前的应用
想必所有接触过spring的用户脑袋里面都冒出了三个字:AOP
。
没错,这个方案通过AOP
可以做到很好的无痛接入,将切点定义在所有需要加密的请求方法,将解密逻辑存放在对应的Advise
中即可。主要有以下注意的地方:
确保这个切面具有最高的优先级
除了这个切面,系统中还存在很多业务相关的切面,比如校验登录,记录日志等,都需要明文的请求参数,所以我们要确保这个切面具有最高的优先级。
如果通过@Aspect
注解来定义切面,有一个对应的注解@Order
可以用于定义切面的优先级,值越小意味着优先级越高,在触发的时候会越早被执行。
兼容spring的表单校验
如果在接口方法参数中带了@Valid
注解,spring会对对应的表单参数执行校验,校验结果存放在接口方法的Errors
或者BindingResult
中,因为加密之后,这个校验是肯定不会通过的(因为明文参数字段的值都为空),所以需要在Advise
方法中重新执行校验:
|
|
或者:
|
|
这个validator
在spirng容器中定义,注入到当前Aspect
。
|
|
文章作者 run
上次更新 2016-09-23