如何在Redis缓存层拦截可能进入数据库的SQL注入载荷

作者:袖梨 2026-06-23
Redis不能直接拦截SQL注入,但可通过前置校验成为第一道过滤网:对缓存key做白名单校验、拒绝非法字符、空值缓存需严格控制、禁止以原始SQL为key、数据库查询必须用预处理语句。

Redis 本身不解析 SQL,也不执行 SQL 查询,所以它**不能直接拦截 SQL 注入载荷**。但你可以在缓存层设计前置校验逻辑,把明显非法的输入在抵达数据库前就拦下来——关键不是让 Redis “防注入”,而是让它成为第一道过滤网。

缓存 key 必须做输入白名单校验

常见错误是把原始 HTTP 参数直接拼进 key,比如:"user:" + user_id + ":profile"。如果 user_id123' OR '1'='1,key 变成 user:123' OR '1'='1:profile,虽然 Redis 不会因此执行命令,但后续业务可能误判该 key 合法,跳过校验直接拼 SQL。

  • 只允许数字型 ID:用正则 ^[0-9]{1,12}$ 或强转为 long/int 再构造 key
  • 对非数字字段(如邮箱、用户名)做格式校验,例如邮箱必须匹配 ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$
  • 拒绝含单引号、分号、注释符(--/*)、空格的 key,直接返回 400 或限流

空值缓存不能无差别写入

缓存穿透场景下,攻击者用大量不存在的 user_id 刷接口,如果你对每个都执行 SET user:abc:profile "" EX 60,等于帮对方把恶意请求固化进缓存,还浪费内存。

  • 只对明确“合法但暂无数据”的 ID 缓存空值,比如注册时查邮箱是否已存在
  • 对高频异常 key(如连续 5 次 user:-1user:select)直接拒绝,不写缓存、不查 DB
  • 空值 TTL 控制在 60–300 秒,避免长期占位;同时记录日志,监控含 SELECTUNIONOR 的 key 模式

避免把原始 SQL 当作 cache key 存储

如果你在 Redis 里看到大量形如 sql_cache:SELECT%20*%20FROM%20users%20WHERE%20name%3D'admin' 的 key,说明业务层正在用用户输入拼接完整 SQL 字符串再哈希——这等于把 SQL 注入 payload 直接送进缓存系统,风险极高。

  • 禁止以原始 SQL 或其 URL 编码形式作为 key;key 应基于结构化参数(如 user_id=123),而非查询语句
  • 所有数据库查询必须走预处理语句(如 MyBatis 的 #{}、JDBC 的 PreparedStatement),缓存层不参与 SQL 构造
  • 若需缓存查询结果,key 应由参数签名生成,例如 user_search:v1:md5("name=xxx&age=25"),且签名前先校验参数合法性
真正起作用的从来不是 Redis 的某个配置或命令,而是你在调用 get() 前那一行校验逻辑——它不复杂,但很容易被跳过。

相关文章

精彩推荐