### 0x00
MetInfo是一个比较的企业建站软件,用户众多。在去年的时候,曾爆出过几个漏洞,有XXE,SQL注入,任意文件读取等,详情见以下链接。印象比较深刻的是两个SQL注入漏洞,一个位于message.calss.php,一个位于feedback.class.php。漏洞都位于前台。只不过第二个洞比较苛刻,每注入一次需要输入一次验证码,利用起来貌似很鸡肋。最近看了一次metinfo,找到一个利用SQL注入写入shell的简便方法,不需要脱裤。
* https://nosec.org/home/detail/1889.html
* https://nosec.org/home/detail/1740.html
### 0x01
首先看app/system/include/class/web.class.php文件,在web类的析构函数中,先读取了缓冲区的数据(在加载基础配置文件的时候进行的ob_start(),打开的缓冲区),经过一系列替换操作(几乎无影响)之后赋值给了$output变量,这里缓冲区数据可以理解为打开缓冲区以后调用echo方法输出的数据。

接着调用replace_attr方法进行了标签处理,这里也没太大影响。

最后进入重点,如果提交的参数metinfonow和$_M['config']['met_member_force']的值相同,则调用file_put_contents函数把上述过程中缓冲区读取的内容写入到$_M['form']['html_filename']文件。这里$_M['form']数组中的内容是$_GET,$_POST,$_COOKIE参数的集合。具体代码就不贴了。也就是说,这里文件名可控,不管改成php,phtm,php5都可以。

但是前提是必须知道$_M['config']['met_member_force'],通过分析,这个变量位于met_config表中id=45的位置。在install/index.php中,met_member_force是取得a-z的7位随机数。这里看了下,没有存在伪随机数漏洞,很可惜。

所以这里可以利用SQL注入,直接注入met_config表中id=45对应的值,来获取met_member_force。如果只注入一条数据,效率就会快很多。
### 0x02
既然文件名可控,接下来看看文件内容是否可控,分析下web类的子类。在这里我找到一个doupfile方法,位于app/system/include/module/uploadify.class.php文件中。

看最后一行代码,echo jsonencode($back),这里$back变量通过json格式化进入了缓冲区,往上走,看下$back是否可控。在这一行:$back = $this->upload($_M['form']['formname']);这里调用upload方法,将上传文件的参数名传了进去,跟进upload方法。

在upload方法中,把上传文件的属性都赋值给了$filear数组。接着往下看。

可以看到,检测文件后缀的时候,调用了getext方法,这里以“.”对文件名进行分割,取了数组的最后一位。如果上传文件名里没有“.”,那么分割后数组中只有一个元素。也就是说,上传不含“.”的文件名,getext取得的扩展名就是上传的文件名。

接着看文件后缀名检测,如果文件名的后缀不在白名单中(这里白名单固定),会把文件扩展名拼接{$_M['word']['upfileTip3']}传入error方法中。

跟进error方法,把传入的参数赋值给了$back['errorcode'],说明echo jsonencode($back)的内容是可控的。

到这里基本就结束了,文件名和文件内容都可控,接下来构造payload。
### 0x03
构造payload如下:

查看根目录

查看1.php文件内容,并访问

成功写入代码

暂无评论