1.什么是重放攻击?我们在开发接口的时候通常会考虑接口的安全性。比如我们通常要求请求的url携带一个经过算法加密后的签名发送给服务器进行验证,如果验证通过,则证明该请求是合法的。比如下面的url:http://wokao66.com/in.json?uid=7&sign=xxxxx其中sign常用的加密算法是MD5,MD5算法是不可逆算法,也就是说不能解密加密后。这通常需要通信双方约定一个私钥appSecret。这个私钥是约定好的,不能在网络上传输。但是仅仅这种加密是不够的。比如我是黑客,抓取了你当前执行成功的请求信息。我们假设它是request-1。既然你已经成功执行了,也就是说,你这个请求的所有参数都是合法的,那么作为一个黑客,我想能不能把你的request-1的请求数据重新打包成另一个请求request-2,然后去request界面,如果此时系统没有处理,那么系统肯定认为request-2是合法的,肯定会放行,但是至于业务成功与否,那就是另一个问题。如果在执行业务Operation之前需要一个比较耗时的数据库,那么大量的request-2,request-3势必导致服务器瘫痪。姜子,语言可能比较难懂,我先画个图:首先,正常的请求系统会要求验证,当你的合法请求被黑客截获后,黑客会重复发送合法请求,所以从而达到欺骗系统的目的!这种重用合法请求的攻击称为重放。2.如何防止重放攻击?重放攻击的原理其实很简单。无非是系统不检查合法请求的唯一性。这意味着什么?也就是说系统要知道你的第一个合法请求request-1不能重复,必须保证每个请求的唯一性。那么如何防止重放攻击呢?参考网上的解决方案,大概有以下两种方法:1、使用时间戳的方法,首先我们认为从发出HTTP请求到到达服务器的时间不会超过60s。当你发送一个请求时必须携带一个timestamp时间戳,假设值为10,当请求到达服务器时,服务器会取出当前时间,假设t2=80,显然t2-timestamp>60s,那么服务器认为请求非法。在数字之外,这个时间戳需要加上MD5加密签名,否则黑客修改时间戳t2=20,就白费功夫了。为什么这行得通?首先,黑客从抓包到发起请求,通常需要60秒以上的时间。另外,我们也不用担心黑客修改timestamp时间戳,因为如果修改了timestamp,对应的签名就会失效,因为MD5是不可逆的。如果要伪造MD5,就必须知道双方约定的密钥appSecret。缺点:如果黑客在60s内发起攻击,那我们就束手无策了。2.使用时间戳+随机数nonce上面说到时间戳有缺点,那么我们加上一个随机数nonce,每次请求成功,服务器都会保存当前请求成功的随机数nonce,比如保存在redis和database,当请求再次进入服务器时,首先验证时间戳是否有效。如果有效,则判断携带的随机数nonce是否已经存在于缓存或数据库中。如果存在,则该请求被认为是非法的。但是你会发现,如果系统请求很多,存储nonce的缓存或者数据库必然会越来越大,那么我们只需要保存服务器当前时间60秒内的nonce值即可。缺点:你必须保证随机数nonce是绝对唯一的3.Record-basedscheme什么是record-based验证方法?也就是说,我现在不需要随机数。我利用MD5加密的唯一性,利用多维(多字段)将每次请求的记录保存到数据库中。每个请求首先检查签名记录是否存在。如果存在,则认为该请求不合法,不存在,将MD5签名与其他参数一起保存在数据库中。当然也可以结合时间戳只保存60s以内的数据。第三点,没有考虑随机数机制,同时可以针对自身业务有不同的扩展,或者增加业务参数,方便运维监控。所有上述解决方案都有缺点。其中一个致命的缺点是服务器的时间和客户端的时间存在时间差。当然你也可以通过验证时间戳来解决这个问题。谢谢阅读。
