位置:首页 > SQL > 如何修复 Cookie 参数中的 SQL 注入漏洞

如何修复 Cookie 参数中的 SQL 注入漏洞

时间:2026-08-23  |  作者:白桃企划师  |  阅读:0

目录

  1. PHP 中最先要修的:$_COOKIE 直接拼接 SQL
  2. 为什么只过滤单引号挡不住攻击
  3. ASP/ASP.NET 里 Request("xxx") 的隐患怎么处理
  4. 测试时最容易漏掉的 Cookie 注入点

前言

Cookie 注入和表单注入本质上是同一类问题,但它更容易藏在登录态、中间件和日志链路里,被开发在排查时漏掉。本文从 PHP 直接拼接 SQL、ASP/ASP.NET 参数读取隐患,到测试阶段的数据流审计方法逐段拆解,帮助你判断一段修复代码到底是真正隔离了数据与 SQL,还是只是做了表面过滤。

Cookie 注入常被误判为“边角问题”,原因是很多项目并不会在业务代码里直写 $_COOKIE,但中间件、登录态、埋点和日志链路都可能把 Cookie 值带进数据库查询。要真正修好这类漏洞,关键不在于补几个替换规则,而在于确认数据进入 SQL 之前是否完成了类型约束、白名单校验或参数化处理。

下面按最常见的代码入口来拆解:先看 PHP 中最危险的直接拼接写法,再说明为什么“只过滤单引号”靠不住,接着处理 ASP/ASP.NET 里 Request("xxx") 的历史隐患,最后补上测试阶段最容易漏掉的间接注入点,方便你据此做代码修复和排查复核。

大多数 Cookie 注入漏洞,根源都很直接:Cookie 参数未过滤、未类型转换、未参数化,就被拼进了 SQL 语句。

Cookie 参数进入 SQL 前的三种可靠处理路径:整数强转、PDO 预处理、有限值白名单校验。
Cookie 参数修复三种正确路径按参数类型选择修复方式,比统一做字符串过滤更可靠。

典型危险写法如下:

$id = $_COOKIE['id'];
$sql = "SELECT * FROM users WHERE id = $id";

这里的问题不在于变量来自 Cookie,而在于它作为不可信输入,直接参与了 SQL 字符串构造。只要保留这种拼接方式,攻击者就有机会改写查询逻辑。

整数参数:强制转整后再判断范围

如果参数本来就应该是整数,最直接的修复方式就是用 (int)intval() 强制转换,并继续校验合法范围。

$id = (int)$_COOKIE['id'];
if ($id <= 0) die();

这种写法适用于 ID、页码、状态编号等天然整数型字段。重点是先收窄类型,再决定是否允许进入查询。

字符串参数:改用 PDO 预处理

如果 Cookie 对应的是用户名、标识符、搜索词等字符串,不能再依赖拼接,更不要使用已经废弃的 mysql_real_escape_string。应改成预处理语句,让数据和 SQL 结构分离。

$stmt = $pdo->prepare("SELECT * FROM users WHERE name = ?");
$stmt->execute([$_COOKIE['name']]);

这类改法的核心不是“转义得更严格”,而是让数据库驱动明确区分语句模板和参数值。

有限取值参数:直接做白名单校验

如果参数只允许少量固定值,例如角色、状态码、类型标识,那么最稳妥的办法通常不是模糊过滤,而是直接比对白名单。

in_array($_COOKIE['role'], ['admin', 'user', 'guest'])

只要业务规则天然有限定,就优先把输入限制在可枚举集合里。这比依赖字符过滤更清晰,也更容易审计。

Cookie 参数进入 SQL 前的三种可靠处理路径:整数强转、PDO 预处理、有限值白名单校验。
信息图:按参数类型选择修复方式,比统一做字符串过滤更可靠。

为什么只过滤单引号挡不住攻击

不少旧项目会尝试对 $_COOKIE 做简单替换,例如:

单引号过滤失效的原因对比图,展示无引号注入、UNION 注入和编码绕过。
只过滤单引号为何不够问题不在单引号本身,而在于不可信输入仍能参与 SQL 结构拼接。
str_replace("'", "''", $val)

或者用正则删除引号字符。这类做法看起来像是在“防注入”,实际上远远不够。

原因很简单:SQL 注入并不一定依赖单引号。下面两类输入都可以在没有引号的情况下改变查询语义:

id=1 OR 1=1
id=1 UNION SELECT 1,2,3

更进一步,MySQL 还支持多种绕过方式,例如反引号、十六进制编码 0x61646d696e,以及宽字节截断等技巧。也就是说,只要应用仍在拼接 SQL,攻击面就没有真正消失。

这里要区分两件事:

  • 过滤只能算防御下限,适合做格式收敛或异常拦截;
  • 修复注入的可靠方案,仍然是强类型转换、白名单约束或预处理语句。

判断一段修复是否有效,可以直接看一个标准:输入值是否还有机会影响 SQL 结构。如果答案是“有”,那就还没修到位。

单引号过滤失效的原因对比图,展示无引号注入、UNION 注入和编码绕过。
信息图:问题不在单引号本身,而在于不可信输入仍能参与 SQL 结构拼接。

ASP/ASP.NET 里 Request("xxx") 的隐患怎么处理

在 ASP 经典环境里,Request("id") 默认会按 QueryString → Form → Cookies → ServerVariables 的顺序取值。这个行为很容易让 Cookie 覆盖原本预期的参数来源,从而绕过前端或上层校验。

这不是一个细节问题,而是老代码里常见的设计隐患。

第一步:显式指定参数来源

所有读取请求参数的地方,都应改成明确集合名,避免无集合名调用:

对应地,应禁止继续使用无集合名的 Request("id")

如果业务确实需要从 Cookie 读取值,应显式写为 Request.Cookies("id"),并在取值后立刻做数值或格式校验,例如 IsNumeric() 或正则验证。

这里的重点是:不要把“从哪儿取值”和“值是否可信”混成一件事。来源必须显式,校验必须紧跟。

第三步:同步收缩 IIS 攻击面

除了代码层修复,还可以在 IIS 全局或应用层配置中禁用 EnableParentPaths 和不安全的脚本映射,尽量减少旁路利用空间。

这一步不能代替参数修复,但对老系统来说,属于值得一起做的收口动作。

实际排查里,最常见的误区是“代码里没看到 $_COOKIE,所以应该没问题”。但很多漏洞并不出现在显式读取 Cookie 的那一行,而是藏在后续数据流里。

Cookie 注入排查路径图,展示从请求头到中间件、日志模块、代理层再到 SQL 的数据流。
Cookie 注入的隐藏数据流排查图审计重点应放在数据流,而不是只搜显式的 Cookie 读取代码。

登录态和中间件里的 session_id

例如登录态校验中间件会自动解析 session_id,然后去数据库查会话。如果这个 session_id 来自 Cookie,且没有校验长度或格式,那么注入点就已经成立,即使业务层从未直接操作 $_COOKIE

埋点、日志和风控链路里的间接入库

另一个高频位置是前端埋点 SDK 上传的 uiddevice_id,被后端日志模块或风控接口直接拼进审计 SQL。这里的代码往往不在核心业务目录里,审计时很容易被忽略。

代理透传与头部混淆问题

还有一类风险来自基础设施链路:CDN 或 WAF 透传原始 Cookie,而业务代码又误把 X-Forwarded-For 头里的伪造 Cookie 当成真实值使用,最终把伪造数据送进查询。

这类问题通常不是单点 bug,而是多个模块之间对“谁才是可信来源”没有统一约定。

排查时该怎么扫全

真正有效的排查方式,不是只搜索有没有 $_COOKIE,而是沿着数据流去看:请求头里的每个 Cookie: 字段,最终有没有进入 SQL 构造。

更实用的做法是:

  • 先抓包,列出所有请求头中的 Cookie: 键名;
  • 再逆向追踪这些键名在代码里的使用位置;
  • 最后确认它们是否参与了查询语句,以及中间是否完成了类型校验、白名单校验或参数化处理。

归根结底,排查目标不是“项目里有没有读 Cookie”,而是“有没有未经清洗的数据流进了查询语句”。

Cookie 注入排查路径图,展示从请求头到中间件、日志模块、代理层再到 SQL 的数据流。
信息图:审计重点应放在数据流,而不是只搜显式的 Cookie 读取代码。

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多