摘要 / 前言:
SQL 注入不仅仅存在于 URL 参数(GET)或 表单数据(POST)中。任何客户端发送给服务器并被后端数据库处理的数据,都可能成为注入点。HTTP Header(请求头)中的 User-Agent、Referer、Cookie 等字段,经常被用于记录日志或进行身份验证,如果处理不当,同样会导致 SQL 注入。本关演示了通过修改 HTTP 请求头进行的注入攻击。
一、漏洞分析与探测
登录后,页面提示“你的信息已经被记录了”,并显示了 IP、User-Agent、Port 等信息。
1. 抓包分析
使用 Burp Suite 抓取请求包。我们看到请求头中包含标准字段以及 Cookie。
- 请求头字段:
User-Agent,Accept,Referer等。 - Cookie 字段:
ant[uname]=admin,ant[pw]=...。
2. 注入点尝试
- 尝试 User-Agent/Accept: 修改这些字段,发现页面回显了修改后的内容。根据源码逻辑,这些内容是被
INSERT进了数据库。如果构造报错注入 Payload,这里也是可以成功的(属于 Insert 注入)。 - 尝试 Cookie: 发现 Cookie 中明文传输了用户名
ant[uname]=admin。- 尝试修改为
ant[uname]=admin',页面出现报错或异常。 - 这说明后端在验证 Cookie 时,直接将
uname带入了 SQL 查询(可能是SELECT * FROM users WHERE username = '$cookie_uname')。
- 尝试修改为
二、注入利用 (Cookie 注入)
既然 Cookie 中的 uname 会引发报错,我们直接在 Cookie 位置构造报错注入 Payload。
- Payload:
ant[uname]=admin' and updatexml(1,concat(0x7e,database(),0x7e),1)#(注意:在 Burp Repeater 中,Cookie 的值通常不需要像 URL 那样严格进行 URL 编码,但也视具体后端处理而定。直接输入字符通常有效。) - 结果分析:
如截图所示,页面返回了 MySQL 报错信息:XPATH syntax error: ‘~pikachu’ 成功爆出了数据库名为pikachu。后续爆表、爆数据的操作与之前的报错注入完全一致,只需替换database()为相应的 SQL 查询语句即可。

三、源码深度分析
本关代码展示了 HTTP Header 注入的两个典型场景。
1. 场景一:Cookie 验证漏洞
代码开头调用了 check_sqli_login($link):
$is_login_id=check_sqli_login($link); // 检查登录状态
if(!$is_login_id){header("location:sqli_header_login.php"); }
function check_sqli_login($link){if(isset($_COOKIE['ant']['uname']) && isset($_COOKIE['ant']['pw'])){
// 这里如果不对获取的 cookie 进行转义,则会存在 SQL 注入漏洞,也会导致验证被绕过
//$username=escape($link, $_COOKIE['ant']['username']);
//$password=escape($link, $_COOKIE['ant']['password']);
$username=$_COOKIE['ant']['uname'];
$password=$_COOKIE['ant']['pw'];
$query="select * from users where username='$username'and sha1(password)='$password'";
$result=execute($link,$query);
if(mysqli_num_rows($result)==1){$data=mysqli_fetch_assoc($result);
return $data['id'];
}else{return false;}
}else{return false;}
}
check_sqli_login 函数内部从 Cookie 中获取 ant[uname],然后 未经过滤直接拼接 到了 SELECT 查询语句中进行身份核验。这就是为什么在 Cookie 处能成功注入的原因。
2. 场景二:日志记录漏洞 (Insert 注入)
提供的源码片段展示了将 Header 信息写入数据库的过程:
// 直接获取前端过来的头信息, 没做任何处理
$remoteipadd=$_SERVER['REMOTE_ADDR'];
$useragent=$_SERVER['HTTP_USER_AGENT'];
$httpaccept=$_SERVER['HTTP_ACCEPT'];
// 把 http 的头信息存到数据库里面去了
$query="insert httpinfo(userid,ipaddress,useragent,httpaccept,remoteport) values('$is_login_id','$remoteipadd','$useragent','$httpaccept','$remoteport')";
$result=execute($link, $query);

分析:
这段代码存在典型的 Insert 注入 。
如果我们修改 User-Agent 为:Firefox'or updatexml(1,concat(0x7e,database()),0) or'
后端 SQL 就会变成:insert ... values(..., 'Firefox' or updatexml(...) or '', ...)
后续爆表、爆数据的操作与之前的报错注入完全一致,只需替换 database() 为相应的 SQL 查询语句即可。

四、总结与防御
Header 注入的特点:
- 隐蔽性强: 普通用户看不到 HTTP 头,容易被开发者忽略。
- 高发区:
- Cookie: 身份验证、购物车、偏好设置。
- User-Agent/Referer: 流量统计系统、访问日志记录系统。
- X-Forwarded-For: 获取 IP 进行地理位置查询或防刷系统。
防御措施:
无论数据来自哪里(URL、表单、还是 HTTP 头),在进入数据库之前都必须被视为“不可信数据”。
- 使用预编译语句(Prepared Statements): 彻底杜绝拼接 SQL。
- 严格的数据类型验证: 例如 IP 地址和 Port 应该验证格式,而不是直接存入。