メインコンテンツまでスキップ

ZTXBAS 本番導入のセキュリティ強化ガイド

本番環境で重要となる ZTXBAS 固有のセキュリティ設定を説明します。Linux カーネルや SSH、ホストファイアウォール等の一般的な保護は対象外です。必要に応じて CIS Benchmarks と Ubuntu Server のセキュリティガイドを参照してください。

初期評価中であれば、まず 導入ガイド の docker run による動作確認を完了してください。

1. 脅威モデル​

ZTXBAS は次の攻撃への対抗を目的としています。

  • フィッシング: オリジンバインディングと端末上の表示によって、別オリジンへの承認転用を防ぎます。
  • 通信上のリプレイ: API リクエストは HMAC-SHA256、時刻制限、ノンスで保護し、TLS で通信路を暗号化します。
  • RP のなりすまし: アプリごとに HMAC シークレットを分離し、漏えい時の影響を当該アプリに限定します。
  • 承認トークンの窃取: JWT は短寿命で ES256 署名され、sub、aud、origin に結び付いています。

保護対象外: 侵害された管理者端末・管理者認証情報、悪意ある RP、攻撃者が使用できるロック解除済みの登録端末、コンテナーの下位レイヤー(ホストカーネル、ハイパーバイザー、物理ディスク)です。管理コンソールへのアクセスは root 権限相当として扱ってください。

2. 実行前のコンテナーイメージ検証​

各リリースイメージは cosign で署名されています。本番配備の前に署名を検証し、デプロイ定義では変更可能なタグよりもイミュータブルなダイジェストを指定してください。以下に公開鍵取得・検証・ダイジェスト指定例を示します。

署名鍵のローテーション: 鍵が変更される場合は旧鍵と新鍵を 1 リリースサイクル併記し、リリースページと SECURITY.md で通知する方針です。OIDC による keyless 署名は GitHub Actions 対応後の計画であり、現行の署名処理はリリース担当者の端末から実行されます。

# Get the public key once (pin both URLs; either is fine).
curl -sO https://corezt.com/ztxbas/cosign.pub

# Verify the tag you're about to run.
cosign verify --key cosign.pub ghcr.io/corezt/ztxbas:1.0.0
docker pull ghcr.io/corezt/ztxbas:1.0.0
docker inspect --format='{{index .RepoDigests 0}}' ghcr.io/corezt/ztxbas:1.0.0
# ghcr.io/corezt/ztxbas@sha256:...

3. コンテナー実行環境の設定​

配布の docker-compose.yml に含まれる制限を、他のオーケストレーターへ移す場合も維持してください。

  • cap_drop: ALL: 権限を付与しません。1024 番未満の特権ポートを直接使用せず、8443/8080/9443 等とリバースプロキシを使います。
  • no-new-privileges: setuid 等を使う権限昇格を防ぎます。
  • read_only: true と /tmp 用 tmpfs: 書き込み先をデータボリューム /var/lib/ztxbas と一時領域に限定します。
  • 非 root ユーザー: コンテナーは uid/gid 10001 で実行されます。データディレクトリは初期起動で 0700 となります。アクセスエラーの対処として安易に root 所有へ変更しないでください。

リソース上限も設定してください。単一インスタンスで数百の同時チャレンジを扱える設計ですが、制限は異常動作時の被害抑止が目的であり、実運用のサイジングとは別です。

cap_drop: [ALL]
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp:size=16m
user: "10001:10001" # non-root in the image
deploy:
resources:
limits:
memory: 512M
pids: 200

4. ネットワークの公開範囲​

公開すべきポートは用途に応じて異なります。

ポートプロトコル内容インターネット公開
8443/tcpHTTPSRP 向け HMAC 認証 APITLS 終端して公開
8080/tcpHTTP(S)管理コンソール直接公開しない
9443/udpAES-GCMモバイルアプリの通信ホストから直接公開

モバイル向け UDP 9443 は AES-256-GCM と端末に結び付いた ECDSA アテステーションを利用する独自プロトコルで、一般的な HTTP リバースプロキシを通りません。ホスト側に直接公開し、ファイアウォールで許可します。下記は ufw の設定例です。

ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp comment 'ssh'
ufw allow 443/tcp comment 'caddy → ZTXBAS 8443'
ufw allow 9443/udp comment 'ZTXBAS mobile transport'
# 8080 is NOT opened — see section 6.
ufw enable

5. TLS​

次の 3 方式から選択します。

  • 推奨:Caddy リバースプロキシで TLS を終端。 ACME による証明書の取得・更新を自動化します。docker-compose.caddy.yml を利用できます。
  • 直接 TLS 終端: ZTXBAS_TLS_CERT と ZTXBAS_TLS_KEY に PEM ファイルを指定します。ZTXBAS 自身に ACME や証明書のホットリロードはありません。証明書更新時はコンテナーの再起動が必要です。
  • クラウドロードバランサーで TLS を終端: ロードバランサーが証明書を管理します。X-Forwarded-For および X-Forwarded-Proto の扱いはセクション 7 を確認してください。

TLS 1.2 以上を必須とし、TLS 1.3 を推奨します。ロードバランサーでは TLS 1.2 未満を明示的に無効化します。

6. 管理コンソールを安全に公開する​

管理コンソールのポート 8080 は最も機密性の高い攻撃面です。安全性の高い順に以下を推奨します。

A. ループバック + SSH トンネル(最も安全): 既定の ZTXBAS_CONSOLE_LISTEN_ADDR=127.0.0.1:8080 を維持し、ローカルに SSH ポート転送します。

B. リバースプロキシ + Basic 認証 + IP 許可リスト: console.ztxbas.example.com などのホスト名を Caddy の背後で公開し、Basic 認証と社内/VPN の IP 制限を併用します。Basic 認証だけに依存しないでください。

C. リバースプロキシで mTLS: クライアント証明書と IP 許可リストを組み合わせます。

起動時の安全装置: TLS なしでループバック以外に管理コンソールをバインドすると、ZTXBAS は起動を拒否します。ZTXBAS_ALLOW_INSECURE_CONSOLE=1 を使えるのは、ホスト側の公開をループバック・プライベートアドレスに制限した場合、または認証ヘッダーや Cookie の扱いを確認した TLS 終端リバースプロキシの背後だけです。保護なしで 0.0.0.0 に公開する構成には使用しないでください。

ssh -L 8080:127.0.0.1:8080 ztxbas.example.com
# then open http://127.0.0.1:8080 in your browser

7. リバースプロキシの安全な設定​

Caddy、nginx、ロードバランサーの背後に配置する場合は、信頼するプロキシの CIDR を明示的に設定します。

これにより管理者ログインに対する送信元 IP 単位の制限や監査ログに実クライアント IP を利用できます。信頼していない送信元からの X-Forwarded-For は無視されます。

さらにプロキシ側では外部から受け取った X-Forwarded-* を削除してから、自ら正しい値を設定してください。そうしないと外部クライアントによる IP 偽装を引き継ぐ可能性があります。Caddy 設定例を以下に示します。

ZTXBAS_TRUSTED_PROXIES=10.0.0.0/8,172.16.0.0/12
reverse_proxy ztxbas:8443 {
header_up -X-Forwarded-For
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}

8. SMTP​

ZTXBAS は SMTP が未設定の場合、起動しません。登録用 QR コードのメール送信がユーザーの初期設定に必須だからです。

必要な設定:ZTXBAS_SMTP_HOST、ZTXBAS_SMTP_PORT、ZTXBAS_SMTP_USER、ZTXBAS_SMTP_PASS、ZTXBAS_SMTP_FROM。

  • SPF、DKIM、DMARC を構成した専用送信ドメインを推奨します。
  • 取引メール向け SMTP リレー、または適切に構成した内部 Postfix 等を利用してください。
  • 設定変更後はテスト登録メールの配送結果を受信トレイ、迷惑メール、メールログで確認します。
  • 認証情報は Git に入る平文の compose ファイルではなく、Docker/Kubernetes の secrets に保存してください。

9. ディスク上の秘密情報​

データボリュームには次の機密ファイルがあります。

ファイル用途権限
ztxbas.db(-wal / -shm を含む)アプリ、ユーザー、オリジン、監査を格納する SQLite0600
jwt-signing.keyES256 JWT の秘密署名鍵0600
breakglass.txt(初回起動のみ)初期管理者パスワード0600、初回使用後は不要

権限エラーを回避するためにアクセス権を緩めないでください。バックアップでは SQLite 状態と JWT 鍵を一組として保護し、復元時に食い違いを生じさせないようにします。

初期の breakglass パスワードは初回管理者ログイン後に失効する使い捨ての認証情報です。アプリごとの HMAC シークレットも作成時に 1 回だけ表示されるため、RP 側のシークレットマネージャーへ保存し、ソース管理には含めません。

CLI でシークレットをローテーションできます。ただし現行版の切り替えは原子的で、旧シークレットを同時に受け入れる猶予期間はありません。並行して 2 つのシークレットを受け付けるローテーションは v1.1 の計画です。

docker exec ztxbas ztxbas app rotate <app-id>

10. 永続化とバックアップ​

SQLite は WAL モードで動作し、アプリ、オリジン、ユーザー、監査、管理者、セッションの状態を保持します。

オンラインバックアップ: sqlite3 .backup でコンテナーを停止せず DB を保存します。JWT 署名鍵も一緒にバックアップしてください。

オフラインスナップショット: コンテナーを停止し、ボリュームをアーカイブして再起動します。簡単ですが数秒程度の停止が生じます。

バックアップは暗号化し、少なくとも四半期に 1 回は復元テストを行ってください。テスト環境で管理コンソールの起動、アプリ一覧、復元済み鍵による新しい JWT の検証まで確認します。

docker exec ztxbas sqlite3 /var/lib/ztxbas/ztxbas.db \
".backup /var/lib/ztxbas/backup.db"

docker cp ztxbas:/var/lib/ztxbas/backup.db ./ztxbas-$(date +%F).db
# Also grab the JWT signing key — see section 9.
docker cp ztxbas:/var/lib/ztxbas/jwt-signing.key ./jwt-$(date +%F).key
docker stop ztxbas
docker run --rm -v ztxbas-data:/data -v $PWD:/backup alpine \
tar czf /backup/ztxbas-$(date +%F).tgz -C /data .
docker start ztxbas

11. ログと監視​

ZTXBAS は stdout に JSON 形式の構造化ログを出力します。journald、docker logs、Loki、SIEM 収集ツールで扱えます。

監視したい代表的なイベント:

  • hmac.verify.fail の多発:時刻ずれ、漏えいやローテーション後のシークレット不一致。
  • admin.login.fail の多発:管理コンソールへの総当たり攻撃。
  • challenge.expired の多発:プッシュ通知の配送問題や UDP 9443 番への到達性問題。
  • smtp.send.fail:登録メールの送信失敗。

GET /health は生存状態とバージョンのみを返し、SMTP 等の下流サービスは調べません。部分障害時に正常なインスタンスを誤って除外しないためです。外部連携の問題はログ監視で検出します。

{"time":"2026-01-15T10:04:11.812Z","level":"WARN","msg":"hmac.verify.fail",
"app_id":"app_a1b2c3d4e5","reason":"timestamp_skew","skew_sec":312}

12. レート制限​

管理者ログインを含む公開 API へのアクセスは、可能な限りリバースプロキシや WAF で制限してください。元の運用ガイドでは、公開エンドポイントをアプリごとにバースト許容付きで、管理者エンドポイントをクライアント IP およびユーザー名単位で厳しく制限する設計が説明されています。

バージョンに関する注意: API 概要では v1 の組み込みレート制限は強制されないと説明されています。実際の配布バージョンでの実装状況を確認し、組み込み制限があるものと想定せず、エッジのリバースプロキシや WAF で必要な制限を適用してください。

13. アップグレード​

  1. リリースノートを確認してください。DB マイグレーションは追加型で、古いバイナリへの単純なダウングレードはサポートされません。
  2. 信頼済みの cosign.pub で新リリースの署名を検証します。
  3. 新しいダイジェストを pull し、データボリュームをバックアップします。
  4. docker compose up -d で起動します。起動時に必要なマイグレーションが適用されます。
  5. ログと /health の新しい version を確認します。

ロールバックが必要な場合は停止してアップグレード前のバックアップに復元したうえで以前のイメージを実行します。新 DB のまま古いバイナリを実行しないでください。

14. インシデント対応​

アプリの HMAC シークレット漏えい: シークレットをローテーションし、RP 側に新しい値を展開します。旧シークレットで作られた進行中のチャレンジは継続しますが、新しい API 呼び出しは旧シークレットで失敗します。

JWT 署名鍵漏えい: v1 では手動で鍵をローテーションし、新しい鍵が起動時に生成されます。JWKS は新しい kid の鍵を配布します。旧鍵で署名された JWT は検証できなくなるため、直近 5 分のユーザー認証に失敗が発生する可能性があります。RP 側で既存セッションを無効化するなど、漏えいを前提とした対応が必要です。鍵を重複公開する猶予期間は v1.1 の計画です。

breakglass パスワード漏えい: 初回使用前なら ztxbas admin reset-password --user admin で再発行し、既存セッションを失効させます。

管理者セッション侵害の疑い: コンソールの Account → Sessions → Revoke all other sessions で他のセッションを無効化し、管理者パスワードを変更します。監査ログでセッション ID と送信元 IP を確認します。

スマートフォンの紛失・侵害: ユーザー登録を解除して端末鍵を無効にし、アカウント回復手順に従って新しい端末で再登録させます。

docker exec ztxbas ztxbas app rotate <app-id>
docker stop ztxbas
docker exec -u root ztxbas rm /var/lib/ztxbas/jwt-signing.key # or delete via the host mount
docker start ztxbas
# From the RP side, using an SDK — or from the console under Users.
curl -X DELETE https://ztxbas.example.com/v1/users/<user-id> ...

15. エアギャップ環境​

ZTXBAS は外部クラウドへのコールバック、ライセンスサーバー、強制テレメトリー、強制更新がないため、分離環境でも運用できます。次の準備が必要です。

  • イメージ配布: cosign で検証した ghcr.io/corezt/ztxbas を内部レジストリへミラーします。
  • TLS: インターネット上の ACME は利用できません。内部 CA の証明書を ZTXBAS_TLS_CERT / ZTXBAS_TLS_KEY に設定します。
  • SMTP: 内部 Postfix/Exchange 等を使用します。
  • 時刻: 内部 NTP を参照する chrony 等で同期します。HMAC の時刻ずれ制限があるため重要です。
  • SDK: Go の GOPROXY や Node・Python の依存パッケージを内部配布できるようミラー・ベンダリングします。

16. 意図的に対象外としている機能​

以下は独立型 ZTXBAS ではなく、より広いアクセス基盤である ZTXGate が対象とする機能です。両製品でモバイル認証アプリは共通で、ZTXGate 内のライセンスされた ZTXBAS 機能は別サーバーではなくライブラリとして統合されます。

  • 管理者向けの SSO/SAML/OIDC
  • 単一管理者を超える管理 RBAC
  • SCIM ユーザープロビジョニング
  • MDM による端末状態の評価
  • stdout ログ転送以上の SIEM 連携
  • マルチテナント分離
  • ZTXGate の WireGuard ベースのクライアントアクセスによる SSH/RDP 等を含むネットワークアクセス制御、および対応 Web アプリへのクライアントレス HTTP/HTTPS アクセス

これらを独立型 ZTXBAS に継ぎ足すより、必要に応じて ZTXGate を採用することを推奨します。