Burp Token重放攻击防护:从原理到实战的防御方案

1次阅读
没有评论

共计 2463 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

一、Token 重放攻击的危害:电商支付场景案例

去年我们系统遭遇了一次典型的 Token 重放攻击。攻击者通过 Burp Suite 截获用户支付请求后,在 10 分钟内重复发送了 37 次相同订单的支付 Token,导致用户被重复扣款。由于原始设计仅验证 Token 有效性而未检测重复使用,攻击者成功绕过系统验证。

Burp Token 重放攻击防护:从原理到实战的防御方案

这个案例暴露出三个关键问题:

  1. 身份认证 Token 缺乏时效性控制
  2. 服务端未记录已处理的请求标识
  3. 关键业务操作未做二次确认

二、三大防御方案原理对比

1. 时间戳窗口验证

  • 原理:在 Token 中嵌入时间戳,服务端验证请求时间与服务器时间的偏差
  • 优点:实现简单,无存储开销
  • 缺点:依赖时钟同步,无法防御窗口期内的重放

2. Nonce 缓存机制

  • 原理:每个请求携带唯一随机数 (Nonce),服务端缓存已使用的 Nonce
  • 优点:完全防止重复请求
  • 缺点:需要持久化存储,集群环境下需共享缓存

3. 签名验证机制

  • 原理:用密钥对请求参数生成签名,服务端验证签名一致性
  • 优点:可防篡改,无需存储状态
  • 缺点:计算开销较大,密钥管理复杂

三、Spring Boot 整合防御方案实现

1. 基于 HMAC 的签名验证

/**
 * 生成 HMAC-SHA256 签名
 * @param secret 密钥
 * @param params 请求参数 Map
 * @return Base64 编码的签名
 */
public static String generateSignature(String secret, Map<String, String> params) {StringJoiner sj = new StringJoiner("&");
    params.entrySet().stream()
        .sorted(Map.Entry.comparingByKey())
        .forEach(e -> sj.add(e.getKey() + "=" + e.getValue()));

    Mac sha256 = Mac.getInstance("HmacSHA256");
    sha256.init(new SecretKeySpec(secret.getBytes(), "HmacSHA256"));
    return Base64.getEncoder().encodeToString(sha256.doFinal(sj.toString().getBytes())
    );
}

2. Redis Nonce 校验器实现

@Repository
public class NonceRepository {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 检查并记录 Nonce
     * @param nonce 随机字符串
     * @param expireSeconds 过期时间 (秒)
     * @return true 表示首次提交
     */
    public boolean checkAndSet(String nonce, long expireSeconds) {Boolean result = redisTemplate.opsForValue()
            .setIfAbsent("nonce:" + nonce, "1", expireSeconds, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(result);
    }
}

3. 时间漂移补偿逻辑

// 在拦截器中处理时间戳验证
if (Math.abs(System.currentTimeMillis() - requestTimestamp) > TIME_TOLERANCE) {
    // 记录时间偏差值用于后续补偿
    timeOffsetService.recordOffset(deviceId, requestTimestamp);
    throw new InvalidTimestampException();}

// 时间补偿服务
public class TimeOffsetService {private final Map<String, Long> deviceOffsets = new ConcurrentHashMap<>();

    public long getCompensatedTime(String deviceId) {return System.currentTimeMillis() + 
            deviceOffsets.getOrDefault(deviceId, 0L);
    }
}

四、性能优化与安全增强

性能优化方案

  1. Redis 集群部署 :
  2. 采用 CRC16 分片算法
  3. 每个分片配置 1 主 2 从
  4. 使用 Redisson 客户端连接

  5. 签名计算优化 :

  6. 测试数据:单核 CPU 1000 次 HMAC-SHA256 计算耗时约 23ms
  7. 建议:对高频接口采用请求合并签名

安全增强措施

  1. 密钥轮换策略 :
  2. 每日自动生成新密钥
  3. 保留前两日密钥用于过渡期验证
  4. 使用 AWS KMS 或 HashiCorp Vault 管理

  5. 防时序攻击比较 :

// 使用 MessageDigest.isEqual 替代普通 equals
public static boolean safeEquals(String a, String b) {
    return MessageDigest.isEqual(a.getBytes(StandardCharsets.UTF_8),
        b.getBytes(StandardCharsets.UTF_8)
    );
}

五、实战验证练习

1. 使用 Burp Suite 重现攻击

  1. 配置 Burp 拦截电商平台支付请求
  2. 修改金额参数后重放请求
  3. 观察服务端响应变化

2. Wireshark 抓包验证

  1. 过滤 HTTP 流量:http.request.method == "POST"
  2. 对比正常请求与重放请求的签名参数
  3. 验证 Nonce 重复时的 403 响应码

总结与建议

通过组合时间戳、Nonce 和签名验证,我们构建了立体防御体系。在实际项目中建议:

  1. 对关键业务接口启用三重验证
  2. 普通 API 至少使用时间戳 +Nonce
  3. 定期进行安全审计和渗透测试
  4. 监控异常重放请求并告警

这套方案在我们生产环境部署后,成功拦截了日均 300+ 次的重放攻击尝试,CPU 负载增加仅 2.1%,内存消耗增长可控。希望本文方案对您构建安全 API 有所帮助。

正文完
 0
评论(没有评论)