0%

metinfo代码审计-文件学习

metinfo文件树

  • app 应用框架文件夹
    • system 应用框架系统文件
    • app 应用文件夹
    • yingyong1
    • yingyong2
    • so on
    • entrance.php 应用入口文件,指向框架入口

每个应用下一般有几个文件夹()
admin 应用的后台
web 应用的前台
include 公用自定义共有文件
plug 插件

route

从后台如后访问应用模块,后台模块不需要向前台一样建立文件才可以访问,直接通过后台通用入口即可访问。
后台通过入口地址:admin/index.php?n=应用名称&c=模块类名称&a=方法名称方法名称必须已do开头

文件路径命名化

PATH_WEB:./(网站根目录)
PATH_APP:./app/
PATH_SYS_CLASS:app/system/include/class/

文件走向

PATH_WEB/index.php ==> PATH_APP/system/entrance.php ==> PATH_SYS_CLASS/load.class.php
在entrance.php:94 行中有有load::module();

1
2
3
4
....
require_once PATH_SYS_CLASS.'load.class.php';

load::module();

文件函数走向

进入load.class.php文件
只有一个load类
module():113

1
2
3
4
5
6
7
8
9
public static function module($path = '', $modulename = '', $action = '') {
if (!$path) {
if (!$path) $path = PATH_OWN_FILE;
if (!$modulename) $modulename = M_CLASS;
if (!$action) $action = M_ACTION;
if (!$action) $action = 'doindex';
}
return self::_load_class($path, $modulename, $action);
}

在这个方法中有PATH_OWN_FILE这个重定向文件,此文件在entrance.php:41,57

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
if (!defined('M_TYPE')) {
if(file_exists(PATH_APP.'app/'.M_NAME.'/')&&M_NAME){
define('M_TYPE', 'app');
}else{
define('M_TYPE', 'system');
}
}
...
//当前文件夹地址
if(M_TYPE == 'system'){
if(M_MODULE == 'include'){
define ('PATH_OWN_FILE', PATH_APP.M_TYPE.'/'.M_MODULE.'/module/');
}else{
define ('PATH_OWN_FILE', PATH_APP.M_TYPE.'/'. M_NAME.'/'.M_MODULE.'/');
}
}else{
define ('PATH_OWN_FILE', PATH_APP.M_TYPE.'/'.M_NAME.'/'.M_MODULE.'/');
define ('PATH_APP_FILE', PATH_APP.M_TYPE.'/'.M_NAME.'/');
}

最后module()返回值为self::_load_class()_load_class(app/system/index/web,index,doindex):208

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
private static function _load_class($path, $classname, $action = '') {
$classname=str_replace('.class.php', '', $classname);
$is_myclass = 0;
if(!self::$mclass[$classname]){
if(file_exists($path.$classname.'.class.php')){
require_once $path.$classname.'.class.php';
} else {
echo str_replace(PATH_WEB, '', $path).$classname.'.class.php is not exists';
exit;
}
$myclass = "my_{$classname}";
if (file_exists($path.'myclass/'.$myclass.'.class.php')) {
$is_myclass = 1;
require_once $path.'myclass/'.$myclass.'.class.php';
}
}
if ($action) {
if (!class_exists($classname)) {
die($classname . ' ' . $action . ' class\'s file is not exists!!!');
}
if(self::$mclass[$classname]){
$newclass = self::$mclass[$classname];
}else{
if($is_myclass){
$newclass = new $myclass;
}else{
$newclass = new $classname;
}
self::$mclass[$classname] = $newclass;
}
if ($action!='new') {
if(substr($action, 0, 2) != 'do'){
die($action.' function no permission load!!!');
}
if(method_exists($newclass, $action)){
call_user_func(array($newclass, $action));
}else{
die($action.' function is not exists!!!');
}
}
return $newclass;
}
return true;
}

module()传入参数过后在211行验证中进入然后判断是否有app/system/index/web/index.class.php这个文件,
有则调用app/system/index/web/index.class.php

进入index.class.php文件第7行就是加载web类函数
在这会调用_load_class('app/system/include/class/', 'web', '');方法
于是会进入到app/system/include/class/web.class.php文件中
在此文件的26中

1
2
3
4
5
6
7
8
9
10
11
12
if(strpos($_SERVER['HTTP_REFERER'], 'pageset=1')!=false && strpos($_SERVER['HTTP_REFERER'], 'lang=')!=false){
preg_match('/lang=(\w+)/', $_SERVER['HTTP_REFERER'], $prev_lang);

if($prev_lang && $prev_lang[1] !=$_M['lang']){
$new_url="{$_M['url']['site_admin']}index.php?lang={$_M['lang']}&n=ui_set&pageset=1";
echo "<script>
parent.document.getElementById('page-iframe').setAttribute('data-dynamic','{$_M['url']['site']}index.php?lang={$_M['lang']}');
parent.window.location.href='{$new_url}';
</script>";
die;
}
}

在这里有一个url的传参点,进行语言的选择

1
2
load::sys_class('common.class.php');
load::sys_func('web');

这里会进行common.class.php类函数调用和web.func.php方法调用,然后就是几个类之间的相互调用。
app/app/system/include下的文件都是应用的公共类函数和方法函数,现在我们回到网页根目录,看看参数的传递。
在网页根目录下member/代表的是普通用户的参数传递,admin/代表的是管理员的参数传递,也就是后台,这两个文件夹中的参数传递差不多,就不过多细说,就在这里说一下几个传参点:

1
2
3
4
5
6
7
8
if(@$_GET['m'])$M_MODULE=$_GET['m'];
if(@!$_GET['n'])$_GET['n']="";
if(@!$_GET['c'])$_GET['c']="";
if(@!$_GET['a'])$_GET['a']="";
@define('M_NAME', $_GET['n']);
@define('M_MODULE', $M_MODULE);
@define('M_CLASS', $_GET['c']);
@define('M_ACTION', $_GET['a']);

1
?m=模板&c=类&a=方法&n=模块文件夹名称

在此过后都会包含../app/system/entrance.php文件进入应用程序的调用。

ending

在此,这个metinfo的代码路由走向大致弄清楚,下一步就是开始复现洞和挖洞了,共勉!!!祝我好运