Pikachu靶场通关笔记(24) — SQL Inject (HTTP Header注入)

25次阅读
没有评论

摘要 / 前言:
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 查询语句即可。
Pikachu 靶场通关笔记(24) — SQL Inject (HTTP Header 注入)

三、源码深度分析

本关代码展示了 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);
Pikachu 靶场通关笔记(24) — SQL Inject (HTTP Header 注入)

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

Pikachu 靶场通关笔记(24) — SQL Inject (HTTP Header 注入)

四、总结与防御

Header 注入的特点:

  • 隐蔽性强: 普通用户看不到 HTTP 头,容易被开发者忽略。
  • 高发区:
    • Cookie: 身份验证、购物车、偏好设置。
    • User-Agent/Referer: 流量统计系统、访问日志记录系统。
    • X-Forwarded-For: 获取 IP 进行地理位置查询或防刷系统。

防御措施:
无论数据来自哪里(URL、表单、还是 HTTP 头),在进入数据库之前都必须被视为“不可信数据”。

  1. 使用预编译语句(Prepared Statements): 彻底杜绝拼接 SQL。
  2. 严格的数据类型验证: 例如 IP 地址和 Port 应该验证格式,而不是直接存入。
正文完
 0
评论(没有评论)