缓存穿透和密码学防御思路

一、什么是缓存穿透 通常为了提升系统和并发能力和响应速度,会在并发能力较弱或响应时间较长的数据源上加一层缓存。在比较简单的系统中,这个数据源最常见的是mysql等数据库,而在更复杂的系...

一、什么是缓存穿透

通常为了提升系统和并发能力和响应速度,会在并发能力较弱或响应时间较长的数据源上加一层缓存。在比较简单的系统中,这个数据源最常见的是mysql等数据库,而在更复杂的系统中,除了数据库,很有可能是远程系统提供的服务。如果查询一个已经存在的数据,如果缓存中已经存在,则直接返回缓存中数据,如果缓存中不存在,会进一步去下面的数据源查,查到后会把数据写入缓存,并返回数据。下次再次查相同的数据时,就会命中缓存。但是如果查询一个不存在的数据,那么最终一定会查到下面的并发能力较差数据源,这就是缓存穿透。一个带有缓存的系统中,是允许少量的缓存穿透的,但是如果有大量的请求都穿透到后面的数据源,严重的话,会导致后面的数据源挂掉或者应用本身挂掉。

二、什么是缓存穿透攻击

攻击者构造一定量(这个往往比系统正常情况能承受的并发量小1到几个数量级)系统中不存在数据的查询,导致大量请求发生缓存穿透,从而引起系统慢甚至崩溃。举个容易理解的例子,电商网站的商品详情页通常会在URL上带上一个参数:商品ID,系统就是根据商品ID查询需要展示的商品数据,一般的系统的设计者基本都会使用缓存来增加其并发能力。对于没有做缓存穿透防御的系统,恶意攻击者只要把URL上的商品ID参数改成一个不存在的值,就可以实现缓存穿透,如果同时构造一定量的这种请求,就可以达到使目标系统拒绝服务的效果。

三、如何防御缓存穿透

通常的防御手段有:

1.如果后端数据源不存在数据,则在缓存中缓存一个空值

这种方案局限性很大,通常用来应对正常业务请求,而不能防御外部攻击。因为只要攻击者构造的攻击请求是不重复的,那么这个缓存就不会起到作用。

2.布隆过滤器(Bloom Filter)

这里简要介绍一下布隆过滤器。布隆过滤器由一个长度为m的位数组(bit array)与k个哈希函数组成的数据结构。当一个米素加入集~合时,通过k个哈希函数将这个米素映射成这个位数组中的k个位置,把它们置为1。检索时,我们只要看这些位置是不是都是1,如果都是1,则可以大致认为这个米素存在(有一定的错误率),如果这些位置中至少有一个0,那么这个米素一定不存在。所以,通过布隆过滤器检测不存在的米素,就不需要到下层数据源进行查询了,如此就解决了缓存穿透攻击问题。
但是,布隆过滤器也存在一些问题:
米素只能往里加,不能删除,随着删除的数据越来越多,布隆过滤器的效果就会越来越差。判断米素是否存在的错误率会越来越高,从而缓存穿透的比例也会越来越高。所以,需要定期重新构建布隆过滤器,架构会变得很复杂。
对于集群环境来说,布隆过滤器的位数组通常放在一些分布式缓存中(如Redis),会有一些额外的远程访问开销。

四、如何使用密码学方法防止缓存攻击

前面提到攻击者需要构造请求来请求系统中不存在的数据来执行攻击,最直接的防御思路就是我们能不能对参数格式做些过滤呢,如果过滤掉了,就不会存在问题了。然而,通常的过滤很容易被绕过,比如商品ID是整数,我们可以过滤负数,但是对于正数就没法过滤。
那么我们有没有可能做到让攻击者构造的请求都过滤掉呢?答案是能,密码学可以很方便地达到这个效果。密码学中大致有三种方案可以防止数据被构造或窜改:MAC(消息认证码,平时使用多以HMAC为主),对称加密(使用AEAD效果更好),非对称(私钥加密或签名)
下面以HMAC为例来看如何实现这种方案,

其中,K为密钥,m为消息,H为构造HMAC所使用的哈希函数

K’的值分三种情况:

K和长度小于Hash算法的块长度:K‘为K的右侧补0至Hash算法的块长度
K的长度与Hash算法的块长度相等:K’=K
K的长度大于Hash算法的块长度:K‘=H(K)

HMAC的输入只有一个消息体和一个密钥

还是以商品详情页为例,假设原先的请求参数为id=1000000,那么我们可以在这个id上附带一个HMAC值,变成类似id=1000000_49a7d46d5bdf38ee4b29ce3ab6e790977c24e78e8f1a788f40a548769ca8906a的形式。在服务端接收到请求时,需要校验后面的HMAC值。至于为什么要把HMAC值附加在原先的id后,是为了方便系统能够方便构造RESTFUL风格或伪静态的URL,当HMAC值也可以作为了一个独立的参数。这里只要HMAC的密码是保密的,只有验证方和生成方能拿到这个密钥,那么攻击者就不能构造合法的请求来绕过检测。
加密与非对称的实现大同小异,都要求服务端保管好自己的密钥(私钥),使用非对称算法还有个好处,如果是分布式系统的话,只需要在生成URL的应用上保管好自己的私钥,可以把公钥随意分发给各个验证方。

使用此方案,好处显而易见,可以把弥补布隆过滤器的缺点。但同时也存在着一些缺点:对于已经生成的URL,如果原始数据被删除,那么这个URL的请求会被放过去。所以具体选择什么方案,还需要根据具体的业务场景来,有时候可能需要几个方案相互组合来达到防御效果。

本文作者:一乐@涂鸦智能安全实验室

漏洞悬赏计划:涂鸦智能安全响应中心(https://src.tuya.com)欢迎白帽子来探索。

招聘内推计划:涵盖安全开发、安全测试、代码审计、安全合规等所有方面的岗位,简历投递sec@tuya.com,请注明来源。

  • 发表于 2021-04-15 17:44
  • 阅读 ( 237 )
  • 分类:互联网

0 条评论

请先 登录 后评论
ICIAC
ICIAC

696 篇文章

你可能感兴趣的文章

相关问题