Gotenberg PDF メタデータ RCE、野外で悪用中(CVE-2026-42589)
PDF メタデータキー内の改行が、認証なしの Gotenberg 8.31.0 未満で Perl コードを実行。7 つの攻撃グループが悪用中。
要点
- Gotenberg 8.31.0 未満の欠陥により、未認証の攻撃者が PDF メタデータのエンドポイントを通じて OS コマンドを実行できます。JSON メタデータキー内の改行が ExifTool の入力を新しい引数行に分割し、注入された
-ifフラグが Perl 式を評価します。 - Gotenberg は Docker ベースの PDF 変換 API で、Docker Hub のプル数は 1 億 100 万を超えます。ポート 3000 に到達できる 8.31.0 未満のインスタンスはすべて露出します。エンドポイントに認証がないためです。
- VulnCheck は 30 日間に 128 個の送信元 IP から 1,358 件の悪用イベントを記録し、少なくとも 7 つの攻撃グループを識別しました。GitHub アドバイザリは Critical CVSS v3.1 9.8 を付け、2026-10-30 時点で CISA の KEV カタログには載っていません。
- Gotenberg 8.31.0 以降へ更新し、コンテナを作り直してください。修正は 2026 年 4 月から公開されています。8.31.0 が他に何を変えるかは「修正方法」を、VulnCheck の指標は「侵害されたか確認するには」を参照してください。
影響を受けるか?
以下すべてが成り立つとき、影響を受けます。
- インスタンスが 2026-04-17 に公開された Gotenberg 8.31.0 未満を実行していること。
- API ポート(既定 3000)が攻撃者から到達可能であること。GitHub アドバイザリはこれが内部およびクラウド環境で一般的だと述べています。
/forms/pdfengines/metadata/writeエンドポイントが有効であること。pdfengines モジュールの一部であり、認証はありません。
| ブランチ | 影響バージョン | 修正バージョン |
|---|---|---|
| CVE-2026-42589 レコード(cve.org) | 8.31.0 未満 | 8.31.0(2026-04-17) |
脆弱性が報告された 2026 年 4 月初旬、Docker Hub の gotenberg/gotenberg:8 タグは 8.29.1 を指していたため、当時メジャータグを引いていたインスタンスは露出していました。
最後に引いたイメージではなく、実際に動いているものを確認してください。
# Running instance: the API reports its own version
curl -s http://your-gotenberg-host:3000/version
# Container: which image the running container uses
docker inspect <container> --format '{{.Config.Image}}'
# Image tag pinned in the deployment file
grep -R "gotenberg/gotenberg:" docker-compose.yml k8s/ 2>/dev/null
修正方法
- イメージ参照を 8.31.0 以降、たとえば
gotenberg/gotenberg:8.31.0または現在の8タグに切り替えます。 - イメージを引くだけでなくコンテナを作り直します。
docker compose up -d --force-recreate gotenberg、または Kubernetes の相当するロールアウトです。 curl -s http://your-gotenberg-host:3000/versionで結果を確認します。- ポート 3000 を必要な呼び出し元だけに制限します。エンドポイントは認証を要求したことがなく、ネットワーク配置が長続きする対策です。
マイナーバージョンを飛ぶ前に、8.31.0 が他に何を変えるか把握してください。このリリースは、出力 URL についてループバックや RFC1918 などの非公開アドレスを拒否して強化し、--webhook-deny-list に内部範囲を遮断する既定値を与え、thecodingmachine/gotenberg イメージの公開をやめます。内部アセットの取得や内部 Webhook の呼び出しを行うワークフローは、更新後にフラグの調整が要る場合があります。
メタデータ欠陥そのものに対する設定の回避策は存在しません。脆弱なコード経路はどのオプションよりも先に実行されます。
根本原因は何か?
Gotenberg は制御文字を拒否せずに、呼び出し元が渡す PDF メタデータキーを ExifTool へ渡します。そのためキー内の改行が、行ベースの ExifTool stdin プロトコルを攻撃者が選んだ引数行へ分割します。
Gotenberg はヘッドレス Chromium と LibreOffice で文書を PDF へ変換します。pdfengines モジュールは /forms/pdfengines/metadata/write を公開し、PDF ファイルと JSON メタデータオブジェクトを受け付けます。ハンドラは各キーと値を go-exiftool ライブラリ経由で ExifTool へ渡します。
go-exiftool は各組を ExifTool の stdin に 1 行で書き込みます。
fmt.Fprintln(e.stdin, "-"+k+"="+str)
fmt.Fprintln は書き込みごとに改行を追記します。呼び出し元の JSON キー自体に \n が含まれると、Go の json.Unmarshal はそれを map キー内のリテラル改行として保持し、書き込みが複数行へ分割されます。ExifTool は各行を別々の引数として読みます。Title\n-if\nsystem('cmd')||1\n-Comment というキーは、-Title、-if、system('cmd')||1、-Comment=x という引数列になります。
ExifTool の -if フラグは引数を Perl 式として評価します。system('cmd') は cmd を Gotenberg プロセスとして実行します。アドバイザリは報告者として S-Senhaji をクレジットしています。
モジュールは一部のキーが危険なことをすでに知っていました。dangerousTags のブロックリストが FileName と Directory のキーを削除していましたが、完全文字列一致を使い、制御文字の除去も拒否もしなかったため、改行注入はそのまま通過しました。
どのように悪用されるか?
アドバイザリの概念実証は、未認証の HTTP リクエスト 1 件です。id の出力をサーバー上のファイルへ書き込みます。
curl -s -o /dev/null -w "HTTP:%{http_code}" \
-X POST http://TARGET:3000/forms/pdfengines/metadata/write \
-F 'files=@sample.pdf;type=application/pdf' \
--form-string $'metadata={"Title\\n-if\\nsystem(\'id>/tmp/pwned\')||1\\n-Comment": "x"}'
# → HTTP:200
# On server: uid=1001(gotenberg) gid=1001(gotenberg) groups=1001(gotenberg),0(root)
- 攻撃者は、改行を含むメタデータ JSON キーと有効な PDF を POST します。
- Gotenberg は JSON をデシリアライズし、キーはリテラルの改行を保持します。
- go-exiftool がキーを ExifTool の stdin へ書き込み、引数行へ分割します。
- ExifTool は
-if system('cmd')||1を Perl 式として処理し、cmdを実行します。 - サーバーは HTTP 200 と有効な PDF を返すため、監視には通常の変換に見えます。
アドバイザリのデータ流出形態は、コマンド出力を base64 で符号化して帯域外 HTTP リスナーへ送ります。これによりやり取りはサーバー自身のログから外れます。
VulnCheck の 10 月のテレメトリは、実際の攻撃者がこれで何をするかを示します。あるグループは id で実行を試し、ExifTool の -Subject<= 演算子で応答 PDF の Subject メタデータに出力を読み戻し、次に 3 つの独立したミラーから cache_base という Go リバースシェルを取得しました。Node.js の代替ダウンロードが重要な点です。Gotenberg コンテナにはヘッドレス Chromium 用の Node.js が入っており、wget や curl がない場所でも攻撃者はダウンローダーを確保します。
攻撃の流れは?
一文で述べると、攻撃者は改行を含むメタデータキーを送り、そのキーが ExifTool の stdin で引数行に分割され、注入された -if フラグが Perl の system 呼び出しを評価し、サーバーは通常の PDF を返しながらコマンドを実行します。
POST"] --> B["json.Unmarshal は
改行を保持"] B --> C["go-exiftool がキーを
ExifTool の stdin へ書く"] C --> D["改行が行を分割し
新しい引数行を作る"] D --> E["-if が
system('cmd')||1 を
Perl として評価"] E --> F["コマンドが Gotenberg
プロセスとして実行"] F --> G["有効な PDF と HTTP 200:
エラーの兆候なし"]
攻撃者に何ができるか?
攻撃者は Gotenberg プロセスとして OS コマンドを実行します。アドバイザリの出力は uid=1001(gotenberg) gid=1001(gotenberg) groups=1001(gotenberg),0(root) のプロセスを示します。root グループに入った非特権ユーザーです。CVSS ベクトルは CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H、スコア 9.8 です。
条件は最小です。ポート 3000 へのネットワーク到達、認証不要、ユーザー操作不要。応答は正常な変換であるため、HTTP やり取りのどこにも攻撃の合図がありません。
その後は攻撃者次第です。VulnCheck は観測された活動を、目的の異なる少なくとも 7 つのグループに帰属付けます。大量スキャン、クリプトマイニング、Python リバースシェル、そして Go のリバースシェル cache_base です。VulnCheck が引用する The Hunter's Ledger は、約 200 件の Gotenberg インスタンスが悪用可能と確認され、そのうち約 150 件に polkitd の名で XMRig が設置されたクリプトマイニング攻撃を報告しました。
なぜ修正は機能するか?
修正は 8.31.0 リリースの 3 つのコミットで、すべて同じ exiftool モジュールにあります。1 つ目は、単純なタグ名でないキーをすべて拒否します。
// safeKeyPattern matches legitimate ExifTool tag names: alphanumeric,
// hyphens, underscores, colons, and periods. Rejects control characters
// (especially \n) that would inject stdin arguments via go-exiftool's
// line-based protocol.
var safeKeyPattern = regexp.MustCompile(`^[a-zA-Z0-9\-_.:]+$`)
メタデータオブジェクトの各キーは、go-exiftool に届く前に safeKeyPattern に一致しなければなりません。改行、復帰、その他の制御文字は一致に失敗し、リクエストは HTTP 400 で拒否されます。
2 つ目は同じ制御を値へ拡張します。
func validateMetadataValue(key, value string) error {
if strings.ContainsAny(value, "\n\r\x00") {
return fmt.Errorf("write PDF metadata with ExifTool: invalid metadata value for key %q (contains control character): %w", key, gotenberg.ErrPdfEngineMetadataValueNotSupported)
}
return nil
}
3 つ目は危険タグの照合前に System: などの ExifTool グループ接頭辞を取り除き、System:FileName で回避できないようにしたうえで、FilePermissions をブロックリストに加えます。3 つ合わせて、キーと値の両方で引数密輸の経路を閉じます。リリースノートはこれを、引数密輸とファイルシステム疑似タグ悪用の遮断と説明しています。
侵害されたか確認するには?
VulnCheck は cache_base グループの指標を公開しています。すべて確認してください。
- ネットワーク指標:
210.170.22.208(レジデンシャル日本、観測された攻撃元)、39.105.65.32(Gitea ペイロードサーバー、アリババクラウド北京)、132.145.123.143(ペイロードホスト、Oracle Cloud 東京)、5.161.100.63(2 つ目のインプラントの C2、Hetzner)、ドメインubuntu-repo.strangled[.]net、linux-x86-tcpudp.strangled[.]net、cheeva.strangled[.]netへの通信。 - リクエストの形:
/forms/pdfengines/metadata/writeへの POST のうち、メタデータ JSON に改行が埋め込まれたもの。観測されたペイロードはTitle\n-if\nで始まるキーと一時ファイル/tmp/nx_cmd.txtを使いました。 - ホストの痕跡:
.cached_db.lockという隠しロックファイル、インプラントcache_base、Go インプラントが設定する環境変数PYTHONUNBUFFERED=1。 - インプラントのハッシュ:
cache_baseMD5f5a756d13697cdfa69ed795d4468339d、cache_arm64MD5c31cd755293844f8ac0802d2c438e701、cache_mipsMD52b85605660343399a650b8c3745bccb0。 - 他グループの指標:プロセス名
polkitdで動く XMRig、4thepool_miner.shのダウンロード、S3 バケットのbanner_homepage_800x800.jpg、185.132.53.158:81/anonymus/clientからのペイロード取得。
メタデータエンドポイントへのヒットだけでは証拠ではなく手がかりです。正当なクライアントも PDF メタデータを書きます。キー内の改行、一時ファイル、ロックファイルが判別する信号です。
年表
- 2026-04-06 から 2026-04-13: メンテナが 3 つの ExifTool 強化コミットを 8.31.0 ブランチに投入します。
- 2026-04-17: Gotenberg 8.31.0 がメタデータ無害化と SSRF 強化を伴いリリースされます。
- 2026-04-30: GitHub アドバイザリ GHSA-rqgh-gxv4-6657 が、動作する概念実証とともに公開されます。
- 2026-05-14: CVE-2026-42589 レコードが影響範囲とともに公開されます。
- 2026-06-26: VulnCheck が KEV 型の自社カタログにこの欠陥を追加します。2026-10-30 時点で CISA は追加していません。
- 2026-08-31: XMRig グループが欠陥を突きます。VulnCheck が観測した最古の探索は、回転する Telecom Italia アドレスから 6 月末から 8 月初頭にかけて行われていました。
- 2026-10-19 から 2026-10-24: Contabo スキャナー
5.189.138.115が 364 件のイベントを生成し、30 日合計の 4 分の 1 を超えます。 - 2026-10-26: VulnCheck が悪用と
cache_baseインプラントの分析を公開します。
FAQ
悪用前にスキャナーが気づかなかったのはなぜですか?
この欠陥には CVE と GitHub アドバイザリがありますが、スキャナーは台帳に載ったものしか指摘できません。Docker イメージはパッケージ依存ではないため依存スキャナーには見えず、コンテナは通常どおり PDF を変換し続けます。バージョンエンドポイントが確実な確認手段です。
欠陥は ExifTool と Gotenberg のどちらにありますか?
アドバイザリは Gotenberg に置きます。ExifTool の -if の挙動は文書化されており、go-exiftool の行プロトコルはライブラリの設計です。何がそのプロトコルに入るかを制御するのは Gotenberg であり、すでに持っていたブロックリストは保守者がその責任を受け入れていたことを示します。修正は完全に Gotenberg のコードにあります。
cache_base インプラントは何をしますか?
5.2 MB のシンボル除去済み Go バイナリで、ロックを取り、ipinfo.io に被害者の位置を問い合わせ、2 つの C2 のどちらかに接続し、接続と /bin/sh の間でシェルを流します。それ自体の永続化機構はありませんが、ツールキットに再起動する番犬が入っています。
うちのインスタンスは内部ネットワークです。それでも標的になりますか?
アドバイザリが指摘するとおり内部やクラウドのデプロイではポート 3000 が到達可能なことが多く、30 日間だけで 128 アドレスから 1,358 件が数えられました。内部配置はポートに到達できる者を狭めますが、欠陥は消しません。それでも修正してください。
修正後に何かローテーションが必要ですか?
侵害確認に合致するものがあれば、ホストを侵害済みとして扱ってください。Gotenberg プロセスが読めたすべてを対象に、環境から届くサービス資格情報や API キーを含めてローテーションし、その場で掃除せず修正済みイメージから再配置してください。
Ostorlab で露出した Gotenberg サーバーを見つける
Ostorlab のアタックサーフェスディスカバリーは、インターネットに露出したホストとサービスをインベントリし、文書変換 API を公開しているホストを見つけて、攻撃者より先にバージョンを確認できるようにします。
参考文献
- GitHub アドバイザリ GHSA-rqgh-gxv4-6657、CVE-2026-42589、CVSS v3.1 9.8、2026-04-30 公開、根本原因と概念実証を含む: https://github.com/gotenberg/gotenberg/security/advisories/GHSA-rqgh-gxv4-6657 (2026 年 10 月 30 日確認)
- CVE-2026-42589 レコード、8.31.0 未満が影響、2026-05-14 公開: https://www.cve.org/CVERecord?id=CVE-2026-42589 (2026 年 10 月 30 日確認)
- VulnCheck、"Cache Me If You Can: Unpacking a Go Implant and Its Toolkit"、Jacob Baines、2026 年 10 月 26 日、悪用件数、7 グループ、指標: https://www.vulncheck.com/blog/cache-me-if-you-can (2026 年 10 月 30 日確認)
- Gotenberg 8.31.0 リリースノート、2026-04-17 公開、ExifTool 無害化と破壊的変更: https://github.com/gotenberg/gotenberg/releases/tag/v8.31.0 (2026 年 10 月 30 日確認)
- 修正コミット 405f1069c026、"fix(exitool) [sic]: prevent control characters"、2026-04-06: https://github.com/gotenberg/gotenberg/commit/405f1069c026 (2026 年 10 月 30 日確認)
- 修正コミット 55d19522a816、"fix(exiftool): prevent line breaks"、2026-04-11: https://github.com/gotenberg/gotenberg/commit/55d19522a816 (2026 年 10 月 30 日確認)
- 修正コミット 46e190970fed、"fix(exiftool): remove System: prefixes"、2026-04-13: https://github.com/gotenberg/gotenberg/commit/46e190970fed (2026 年 10 月 30 日確認)
- Gotenberg リポジトリ、2026 年 10 月 30 日時点で 13,478 スター: https://github.com/gotenberg/gotenberg (2026 年 10 月 30 日確認)
- Docker Hub の Gotenberg、2026 年 10 月 30 日時点で 101,471,977 プル: https://hub.docker.com/r/gotenberg/gotenberg (2026 年 10 月 30 日確認)
- The Hunter's Ledger、悪用可能な約 200 件の Gotenberg インスタンスを狙った XMRig 攻撃、VulnCheck が引用: https://the-hunters-ledger.com/reports/gotenberg-rce-cryptomining-107-175-69-137/ (2026 年 10 月 30 日確認)
- CISA KEV カタログの JSON フィード、2026 年 10 月 30 日に CVE-2026-42589 を確認(載っていない): https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json (2026 年 10 月 30 日確認)