基于timestamp和nonce的防重放攻击

电玩女神 2022-02-26 02:12 243阅读 0赞

以前总是通过timestamp来防止重放攻击,但是这样并不能保证每次请求都是一次性的。今天看到了一篇文章介绍的通过nonce(Number used once)来保证一次有效,感觉两者结合一下,就能达到一个非常好的效果了。

  1. 重放攻击是计算机世界黑客常用的攻击方式之一,所谓重放攻击就是攻击者发送一个目的主机已接收过的包,来达到欺骗系统的目的,主要用于身份认证过程。

  首先要明确一个事情,重放攻击是二次请求,黑客通过抓包获取到了请求的HTTP报文,然后黑客自己编写了一个类似的HTTP请求,发送给服务器。也就是说服务器处理了两个请求,先处理了正常的HTTP请求,然后又处理了黑客发送的篡改过的HTTP请求。

基于timestamp的方案

  每次HTTP请求,都需要加上timestamp参数,然后把timestamp和其他参数一起进行数字签名。因为一次正常的HTTP请求,从发出到达服务器一般都不会超过60s,所以服务器收到HTTP请求之后,首先判断时间戳参数与当前时间相比较,是否超过了60s,如果超过了则认为是非法的请求。

假如黑客通过抓包得到了我们的请求url: http://koastal.site/index/Info?uid=ZX07&stime=1480862753&sign=80b886d71449cb33355d017893720666

  1. $sign=md5($uid.$token.$stime);
  2. // 服务器通过uid从数据库中可读出token

 一般情况下,黑客从抓包重放请求耗时远远超过了60s,所以此时请求中的stime参数已经失效了。
如果黑客修改stime参数为当前的时间戳,则sign参数对应的数字签名就会失效,因为黑客不知道token值,没有办法生成新的数字签名。

但这种方式的漏洞也是显而易见的,如果在60s之后进行重放攻击,那就没办法了,所以这种方式不能保证请求仅一次有效。

基于nonce的方案

  nonce的意思是仅一次有效的随机字符串,要求每次请求时,该参数要保证不同,所以该参数一般与时间戳有关,我们这里为了方便起见,直接使用时间戳的16进制,实际使用时可以加上客户端的ip地址,mac地址等信息做个哈希之后,作为nonce参数。
我们将每次请求的nonce参数存储到一个“集合”中,可以json格式存储到数据库或缓存中。
每次处理HTTP请求时,首先判断该请求的nonce参数是否在该“集合”中,如果存在则认为是非法请求。

  假如黑客通过抓包得到了我们的请求url: http://koastal.site/index/Info?uid=ZX07&nonce=58442c21&sign=80b886d71449cb33355d017893720666

其中:

  1. $sign=md5($uid.$token.$stime);
  2. // 服务器通过uid从数据库中可读出token
  3. nonce参数在首次请求时,已经被存储到了服务器上的“集合”中,再次发送请求会被识别并拒绝。

  nonce参数作为数字签名的一部分,是无法篡改的,因为黑客不清楚token,所以不能生成新的sign。

  这种方式也有很大的问题,那就是存储nonce参数的“集合”会越来越大,验证nonce是否存在“集合”中的耗时会越来越长。我们不能让nonce“集合”无限大,所以需要定期清理该“集合”,但是一旦该“集合”被清理,我们就无法验证被清理了的nonce参数了。也就是说,假设该“集合”平均1天清理一次的话,我们抓取到的该url,虽然当时无法进行重放攻击,但是我们还是可以每隔一天进行一次重放攻击的。而且存储24小时内,所有请求的“nonce”参数,也是一笔不小的开销。

基于timestamp和nonce的方案

那我们如果同时使用timestamp和nonce参数呢?
nonce的一次性可以解决timestamp参数60s的问题,timestamp可以解决nonce参数“集合”越来越大的问题。

我们在timestamp方案的基础上,加上nonce参数,因为timstamp参数对于超过60s的请求,都认为非法请求,所以我们只需要存储60s的nonce参数的“集合”即可。

假如黑客通过抓包得到了我们的请求url: http://koastal.site/index/Info?uid=ZX07&stime=1480862753&nonce=58442c21&sign=80b886d71449cb33355d017893720666

其中:

  1. $sign=md5($uid.$token.$stime);
  2. // 服务器通过uid从数据库中可读出token

  如果在60s内,重放该HTTP请求,因为nonce参数已经在首次请求的时候被记录在服务器的nonce参数“集合”中,所以会被判断为非法请求。超过60s之后,stime参数就会失效,此时因为黑客不清楚token的值,所以无法重新生成签名。

综上,我们认为一次正常的HTTP请求发送不会超过60s,在60s之内的重放攻击可以由nonce参数保证,超过60s的重放攻击可以由stime参数保证。

因为nonce参数只会在60s之内起作用,所以只需要保存60s之内的nonce参数即可。

我们并不一定要每个60s去清理该nonce参数的集合,只需要在新的nonce到来时,判断nonce集合最后一次修改时间,超过60s的话,就清空该集合,存放新的nonce参数集合。其实nonce参数集合可以存放的时间更久一些,但是最少是60s。

验证流程:

  1. //判断stime参数是否有效
  2. if( $now - $stime > 60){
  3. die("请求超时");
  4. }
  5. //判断nonce参数是否在“集合”已存在
  6. if( in_array($nonce,$nonceArray) ){
  7. die("请求仅一次有效");
  8. }
  9. //验证数字签名
  10. if ( $sign != md5($uid.$token.$stime.$nonce) ){
  11. die("数字签名验证失败");
  12. }
  13. //判断是否需要清理nonce集合
  14. if( $now - $nonceArray->lastModifyTime > 60 ){
  15. $nonceArray = null;
  16. }
  17. //记录本次请求的nonce参数
  18. $nonceArray.push($nonce);
  19. //开始处理合法的请求

发表评论

表情:
评论列表 (有 0 条评论,243人围观)

还没有评论,来说两句吧...

相关阅读

    相关 API设计中攻击

    HTTPS数据加密是否可以防止重放攻击? 否,加密可以有效防止明文数据被监听,但是却防止不了重放攻击。 防重放机制 我们在设计接口的时候,最怕一个接口被用户截取用于重

    相关 API接口

    我们在设计API接口时,最怕的莫过于同一个接口给用户截获重放提交,那什么是重放提交:对同一个请求发送多次到后台,对系统产生异常影响。 应对的策略有: 1使用时间戳time

    相关 攻击--初识

    开发问一个关于重放攻击的概念,说实话真没听到过这个名称,查了一下貌似有点像DDos攻击,下面转载的关于重放攻击的具体细节描述:   重放攻击的概念 根据百科的解释

    相关 攻击与中间人攻击

    重放攻击与中间人攻击 大概有多半年没有更新博客了吧,本来还想保持最起码一月一更的 ,但是考研复习后面越来越紧张,一直到今天,最后一科专业课考完,绷了一年的紧张的神经,终

    相关 攻击以及防御手段

    今天讨论在不使用HTTPS的情况下如何保证文本传输的安全性问题上被授课了 什么是重放攻击? 入侵者从网络上截取主机A发送给主机B的报文,并把由A加密的报文发送给B,

    相关 区块链 攻击 简介

    什么是重放攻击 当网络进行硬分叉之后,区块链发生永久性分歧并产生两条历史交易、地址、私钥以及余额等完全对应的链。理论上UTXO在两条链上都可被确认以及识别,从而让不法之徒