防重放攻击

本文探讨了使用timestamp和nonce结合的方式防止重放攻击的有效方法。通过限制请求时效和确保请求唯一性,可在一定程度上保障系统的安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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

基于timestamp的方案

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

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

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

一般情况下,黑客从抓包重放请求耗时远远超过了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

其中

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

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

其中

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

如果在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。

验证流程

//判断stime参数是否有效
if( $now - $stime > 60){
    die("请求超时");
}
//判断nonce参数是否在“集合”已存在
if( in_array($nonce,$nonceArray) ){
    die("请求仅一次有效");
}
//验证数字签名    
if ( $sign != md5($uid.$token.$stime.$nonce) ){
    die("数字签名验证失败");
}
//判断是否需要清理nonce集合
if( $now - $nonceArray->lastModifyTime > 60 ){
    $nonceArray = null;
}
//记录本次请求的nonce参数
$nonceArray.push($nonce);


//开始处理合法的请求
转自:http://blog.youkuaiyun.com/koastal/article/details/53456696
<think>嗯,用户想了解如何进行防重放攻击的实验设计或者示例代码。首先,我需要理解防重放攻击的基本概念。重放攻击是指攻击者截获合法的数据包后,重新发送以欺骗系统。比如,截获一个登录请求的数据包,再次发送可能让系统误以为用户再次登录,从而执行非法操作。 接下来,用户需要实验设计方法和示例代码。我得先整理常见的防护手段。根据引用[1],防护方法包括token验证、时间戳、序列号和验证码。这些方法可以单独或组合使用。比如,时间戳验证数据包的新鲜度,token保证请求的唯一性。 实验设计的话,可能需要分步骤。首先是搭建基础环境,比如模拟客户端和服务器,然后设计攻击场景,比如重放登录请求。接着,实现防护机制,比如添加时间戳和token,最后测试防护效果。 示例代码部分,可能需要用Python模拟客户端和服务器。比如,客户端发送请求时带上时间戳和token,服务器验证这些参数是否有效。如果时间戳超过一定范围,或者token已经被使用过,就拒绝请求。 还要考虑如何模拟重放攻击。比如,使用工具如Burp Suite截获请求并重放,或者手动复制请求数据再次发送。然后在服务器端记录日志,观察是否有重放请求被拦截。 另外,引用[2]提到了binlog的重放,虽然主要是数据库层面的,但可能涉及到事务的顺序和唯一性,不过可能和这里的防重放攻击关联不大。引用[3]提到CAN帧格式,可能和车辆网络相关,但用户的问题更偏向于一般Web应用的防重放,所以可能暂时不需要深入这部分。 需要确保示例代码正确,比如在服务器端存储已使用的token,并设置有效时间窗口。同时,处理并发情况,比如使用线程安全的存储结构。可能还需要考虑时间同步问题,服务器和客户端的时间必须大致一致,否则时间戳验证会失败。 用户可能还想知道如何测试防护机制的有效性,比如发送正常请求后,再重放相同的请求,检查是否被拒绝。或者测试时间戳过期的情况,以及token重复使用的情况。 最后,生成相关问题,可能涉及其他防护方法、不同场景下的应用,或者性能优化等。比如,如何处理时间同步问题,或者在高并发下token存储的性能问题。</think>### 防重放攻击实验设计与实现方法 #### 一、防重放攻击原理 重放攻击(Replay Attack)指攻击者截获合法通信数据包后重新发送以欺骗系统[^1]。防护核心在于**验证数据唯一性**和**时效性**,常用方法包括: 1. **时间戳验证**:数据包需包含当前时间戳,服务器验证时间差是否在允许范围内(如±60秒) 2. **序列号/随机数**:每个请求包含唯一标识(如UUID),服务器记录已使用标识 3. **Token机制**:动态生成一次性令牌,引用[1]中提到的Token刷新机制可参考 #### 二、实验设计步骤 1. **基础环境搭建** - 模拟客户端-服务器架构(Python/Node.js/Java) - 使用Wireshark或Burp Suite进行流量截获 2. **攻击场景模拟** - 登录请求重放 - 支付订单重复提交 3. **防护机制实现** ```python # 服务端示例(Python Flask) from flask import Flask, request import time import hashlib app = Flask(__name__) used_tokens = set() # 存储已使用的Token @app.route('/transfer', methods=['POST']) def transfer(): timestamp = request.form.get('timestamp') token = request.form.get('token') # 时间戳验证(窗口60秒) if abs(time.time() - float(timestamp)) > 60: return "Invalid timestamp", 403 # Token唯一性验证 if token in used_tokens: return "Replay detected", 403 # 生成Token的哈希验证(客户端需用相同算法) expected_token = hashlib.sha256(f"{timestamp}{SECRET_KEY}".encode()).hexdigest() if token != expected_token: return "Invalid token", 403 used_tokens.add(token) # 执行转账逻辑 return "Success" if __name__ == '__main__': app.run() ``` #### 三、关键实现细节 1. **时间同步**:需保证客户端-服务器时间误差在允许范围内,可引入NTP协议 2. **Token生成算法**: $$token = HASH(时间戳 + 随机数 + 密钥)$$ 引用[2]中的事务处理思路可增强唯一性保证 3. **存储优化**:使用Redis存储已用Token并设置TTL,避免内存溢出 #### 四、测试验证方法 1. 正常请求返回200状态码 2. 重放相同数据包返回403错误 3. 修改时间戳/Token后请求被拒绝 4. 通过Wireshark验证加密传输有效性(如HTTPS)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值