Article

バックアップデータを確実に保護する方法

高田晃太郎
バックアップデータを確実に保護する方法

複数の業界調査が示すのは不都合な現実です。ランサムウェア被害組織の多くで、攻撃者はまずバックアップを無力化しようとします。最新の調査では、攻撃時にバックアップへのアクセス・改ざんが試みられた事例が約94%に達し¹、別の独立調査でも約93%がバックアップを標的としていたと報告されています²。さらに、国内データではバックアップからの復旧(リストア)を試みた111件のうち90件が被害直前の水準まで完全復元できず、完全復旧は2割前後にとどまったとの報告もあります³。数字の揺れはあっても方向性は明白で、バックアップは作成した瞬間から攻撃対象です。設計と運用を“復元できるか(リカバリできるか)”という一点に収れんさせ、暗号化・隔離・改ざん防止・復旧テストという四点セットで、攻撃と災害復旧(DR)の両方に耐える体制を組むことが必要です⁴。この記事ではCTOやエンジニアリーダーが意思決定できるよう、指標、実装コード、運用設計、そしてビジネスの言葉でのROIまでを一気通貫で示します。

バックアップを守る設計原則と指標

保護の原則はシンプルですが、徹底が難しいものです。まずは3-2-1-1-0ルールに立ち返ります。つまり少なくとも3つのコピーを2種類以上のメディアに保持し、1つはオフサイト、さらに1つはイミュータブル(変更不可のWORM保存)もしくはエアギャップ(物理・論理的切り離し)で、検証エラーを0に近づけるという考え方です⁵。このルールは昔ながらの標語ではなく、ゼロトラスト時代の実装要件に置き換えると、鍵管理が組織外に漏れないこと、書き込み経路と読み出し経路の権限が分離されていること、リテンション(保存期間)が管理者でも容易に解除できないこと、といった具体のチェックポイントに展開されます。さらにRPO(どこまで巻き戻せればよいかの目標)とRTO(どれくらいの時間で復元できるかの目標)を数値で決め、攻撃時の期待損失をモデル化することが投資の基準になります。例えば時給売上が500万円、許容停止がRTO60分、復元成功率が70%とすると、単発インシデントの期待損失は500万円×1時間×(1−0.70)=150万円です。成功率を90%へ引き上げるための追加投資が年額1000万円で、発生頻度が年2回なら、期待損失低減は(0.90−0.70)×500万円×1×2=2000万円/年となり、投資に対する純効果は1000万円のプラスです。技術施策はこのように経営の言葉へ変換して説明すべきです。

脅威モデルとアクセス分離

攻撃者は最短経路で資格情報に触れ、バックアップサーバやストレージの削除権限を奪います。よって運用IDとバックアップ書き込みID、復元実行IDを分け、ネットワークも相互接続を最小化して、横移動のための“橋”を片っ端から落としていく設計が有効です⁴。特にクラウドでは、バックアップ書き込みロールに削除や短期リテンション変更を許可しないことが効きます⁸。オンプレでは管理プレーン(管理用コンソール/ネットワーク)を別セグメントへ退避し、跳び先はMFA(多要素認証)必須にします⁴。鍵はクラウドKMS(鍵管理サービス)やHSM(ハードウェアセキュリティモジュール)に寄せ、復号の発火条件をワークフローで二者承認にすることが推奨です⁸。

測るから強くなる——KPIの置き方

KPIは“取得の成功率”ではなく“復元の成功率”に寄せます。月次の完全リストア成功率、PITR(ポイントインタイムリカバリ)の達成率、メディアごとの整合性検証の失敗率、イミュータブル破壊未遂の検出件数、そして演習から本番復旧までのリードタイム短縮が中心です。パフォーマンスはバックアップ窓の時間内に収まるか、重複排除と圧縮でストレージ効率がどれだけ改善したかという観点で測ります。例えばzstd圧縮を有効にしたファイルバックアップで、1.7倍の重複排除と210MB/sのスループットを観測できれば、2TBのウィンドウは約2時間40分に短縮されます(ワークロードにより大きく変動します)。テストで得た値はダッシュボード化し、SLO違反の早期警報に使います。バックアップは定期的な復元テスト(災害復旧訓練)で検証し、SLO/SLAの達成状況を継続的に評価します⁸。

バックアップの暗号化・隔離・改ざん防止の実装

抽象論をやめて、実際の構成に落とし込みます。クラウドならオブジェクトストレージのバージョニングとオブジェクトロック、KMSによるサーバサイド暗号化、書き込みと削除の権限分離が基本です⁶⁷⁸。オンプレやハイブリッドでは、暗号化対応のバックアップツールに加えて、オフライン写像(エアギャップ用スナップショット)やWORMストレージを組み合わせます。ここではS3互換ストレージを例に最小構成を示します。目的は“消せない・改ざんできない・復元できる”バックアップデータの確保です。

S3のバージョニングとObject LockをTerraformで有効化

# terraform {
#   required_providers { aws = { source = "hashicorp/aws", version = "~> 5.0" } }
#   required_version = ">= 1.5"
# }
provider "aws" { region = "ap-northeast-1" }
resource "aws_s3_bucket" "backup" {
  bucket = "corp-backup-prod-immutable"
  object_lock_enabled = true
}
resource "aws_s3_bucket_versioning" "v" {
  bucket = aws_s3_bucket.backup.id
  versioning_configuration { status = "Enabled" }
}
resource "aws_s3_bucket_object_lock_configuration" "lock" {
  bucket = aws_s3_bucket.backup.id
  rule { default_retention { mode = "COMPLIANCE" days = 30 } }
}
resource "aws_s3_bucket_server_side_encryption_configuration" "sse" {
  bucket = aws_s3_bucket.backup.id
  rule { apply_server_side_encryption_by_default { sse_algorithm = "aws:kms" kms_master_key_id = "alias/backup-kms" } }
}

この定義ではイミュータブル保存をデフォルト30日で強制し、KMS鍵で暗号化します。ガバナンスではなくコンプライアンスモードを選ぶことで、誤操作や権限昇格の際にも削除を防ぎます⁷。なお、誤設定を避けるためStateは別アカウントのリモートに置き、計画外のDestroyを防ぐガードレールを入れてください。ここまでで“消せないバックアップ先”が用意でき、災害時やランサムウェア感染後のリストアの土台になります。

削除不能を確認するためのAWS CLI検証

set -euo pipefail
NAME=corp-backup-prod-immutable
aws s3api put-object --bucket "$NAME" --key test/lock.txt --body ./dummy.txt \
  --object-lock-mode COMPLIANCE --object-lock-retain-until-date "$(date -u -d '+31 days' +%Y-%m-%dT%H:%M:%SZ)"
# 削除を試み、失敗を期待する
if aws s3api delete-object --bucket "$NAME" --key test/lock.txt 2>err.log; then
  echo "ERROR: delete succeeded unexpectedly" && exit 1
else
  echo "OK: delete blocked as expected" && cat err.log
fi

ここで想定どおり削除が失敗し、AccessDeniedが返ることを確認します。CIで定期実行し、オブジェクトロックとリテンション設定による保護状態が崩れていないかを監視に組み込みます。バックアップの保全性を“手触りのある検証”として自動化することが、復元信頼性の向上につながります。

クライアント側暗号化と整合性検証(restic + KMS)

set -euo pipefail
export AWS_REGION=ap-northeast-1
export RESTIC_REPOSITORY="s3:s3.amazonaws.com/corp-backup-prod-immutable/restic"
export RESTIC_PASSWORD="$(aws secretsmanager get-secret-value --secret-id restic-pass | jq -r .SecretString)"
export AWS_KMS_KEY_ID="alias/backup-kms"
restic init || true
restic backup /srv/data --tag nightly --iexclude-file=/etc/backup/excludes.txt --compression auto
restic forget --keep-daily 14 --keep-weekly 8 --keep-monthly 12 --prune
restic check --read-data-subset=10%

resticはクライアント側で暗号化し、サーバ側に平文が残りません。checkでデータ読み出し検証を混ぜ、劣化を早期に見つけます。一般的な環境ではzstd圧縮と並列化により180–220MB/s程度の実効スループットが出るケースがあり、2TB規模でも夜間のバックアップウィンドウ内に収まりやすくなります。I/O競合を避けるため、I/Oコントローラで優先度を落とし、本番とバックアップの競合を抑えます。機微データの保護では、サーバサイド暗号化やクライアント側暗号化の採用、鍵の適切な管理が推奨されます⁶。ここまでが“守られたバックアップの取得”で、次に“戻せることの検証”へ進みます。

Pythonでリストア整合性を自動検証(ハッシュ照合とリトライ)

import hashlib
import boto3
import botocore
import os
import sys
from time import sleep

def sha256sum(path: str) -> str:
    h = hashlib.sha256()
    with open(path, 'rb') as f:
        for chunk in iter(lambda: f.read(1024 * 1024), b''):
            h.update(chunk)
    return h.hexdigest()

s3 = boto3.client('s3')
bucket = os.environ['BACKUP_BUCKET']
key = os.environ['RESTORE_KEY']
local = '/tmp/restore.bin'

for attempt in range(3):
    try:
        s3.download_file(bucket, key, local)
        expected = s3.head_object(Bucket=bucket, Key=key)['Metadata'].get('sha256')
        actual = sha256sum(local)
        if expected and expected == actual:
            print('OK: integrity verified')
            sys.exit(0)
        else:
            print('WARN: hash mismatch, retrying...', file=sys.stderr)
            os.remove(local)
            sleep(2 ** attempt)
    except botocore.exceptions.BotoCoreError as e:
        print(f'ERROR: {e}', file=sys.stderr)
        sleep(2 ** attempt)

print('FATAL: restore verification failed', file=sys.stderr)
sys.exit(1)

バックアップ時にオブジェクトのメタデータへハッシュ(例: sha256)を記録しておけば、復元後に一致確認できます。失敗時は指数バックオフで再試行し、最終的な異常はCI/CDや監視に連携します。これにより“取れた気になっていたが壊れていた”事故を削減でき、復元テストと日常運用が有機的につながります。

Goでオブジェクトロックの強制力をプログラムから検証

package main

import (
    "context"
    "fmt"
    "os"
    "time"

    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/s3"
    "github.com/aws/aws-sdk-go-v2/service/s3/types"
)

func main() {
    ctx := context.Background()
    cfg, err := config.LoadDefaultConfig(ctx)
    if err != nil { panic(err) }

    cli := s3.NewFromConfig(cfg)
    b := os.Getenv("BUCKET")
    k := "lock/test.txt"

    _, err = cli.PutObject(ctx, &s3.PutObjectInput{
        Bucket:                     &b,
        Key:                        &k,
        Body:                       os.Stdin,
        ObjectLockMode:             types.ObjectLockModeCompliance,
        ObjectLockRetainUntilDate:  awsTime(time.Now().Add(24 * time.Hour)),
    })
    if err != nil { panic(err) }

    _, err = cli.DeleteObject(ctx, &s3.DeleteObjectInput{Bucket: &b, Key: &k})
    if err == nil { panic("delete unexpectedly succeeded") }
    fmt.Println("OK: delete blocked =>", err)
}

func awsTime(t time.Time) *time.Time { return &t }

パイプで標準入力から投入すればCIでも扱いやすく、削除が拒否されることを自動で確認できます。人の手が触れるたびに検証するのではなく、日々のパイプラインで保護の効果を継続的に測定するのがポイントです。これも“復元できるバックアップ運用”の一部です。

マルウェアを持ち込まない——スキャンの組み込み

バックアップは健全でも、復元時にマルウェアを現場へ持ち込めば意味がありません。復元先での隔離ネットワークとスキャンは標準化しましょう⁴。軽量に始めるなら次のようにバックアップスナップショットをマウントして全量スキャンします。

set -euo pipefail
MNT=/mnt/restore
mkdir -p "$MNT"
# スナップショットのマウントは環境に応じて
clamscan -ri "$MNT" --max-filesize=5G --max-scansize=20G || true

脅威が見つかった場合は復元を止め、IOCを抽出して本番ネットワーク側の検査に回します。EDRのオフラインスキャンエンジンを使えば、より実態に即した検査が可能です。復元の前後でスキャンを挟むことにより、バックアップからのリストアが安全であることを裏づけます。

復旧性を証明するテストと運用

バックアップは取る行為ではなく、復元できることを証明する継続的なプロセスです。完全復元、ポイントインタイムリカバリ、サービステンプレートの再構築、アクセスキーの再発行、監査証跡の保全まで、シナリオをテンプレート化しておきます。特にデータベースは論理バックアップと物理バックアップを併用し、PITRの演習を定期的に回します⁴。オンプレの仮想基盤であれば、隔離セグメント上にサンドボックスを常設し、週次で“冷たい復元”を自動化します。クラウドであればDRリージョンにミニマムのVPC、KMS、IAMロール群を常設しておき、IaCから一括で環境を立ち上げます。これらはすべて、RTO/RPOの達成と復元成功率の引き上げへ直結します。

演習の自動化と計測

演習は“手で確かめる”フェーズを抜け出し、CIジョブとして定着させます。深夜帯にDR環境を起動し、バックアップからサービスを復元、ヘルスチェックを通した上で、コスト最適化のため速やかに破棄するという流れが現実的です。SyntheticsでSLO閾値を評価し、RTO/RPOの実測値を記録します⁸。下は簡易なシェルの例です。

set -euo pipefail
start=$(date +%s)
./infra/apply.sh # IaCでDR環境起動
./restore.sh     # バックアップから復元
./healthcheck.sh # 合格であれば0終了
end=$(date +%s)
echo "RTO=$((end-start))s" | tee -a metrics.log
./infra/destroy.sh

運用に入れば、失敗率のトレンド、演習あたりの人手時間、復元後のデータ整合性エラーの種別などを時系列で可視化します。シナリオ成功率が**95%**を下回る場合は、設計・実装・権限・ネットワークのどこで詰まっているかを根因分析して、優先度の高い技術的負債から返していきます。ここまでを粘り強く回すことが、災害復旧(DR)能力の底上げになります。

権限と鍵管理の運用ガード

最小権限の維持は“設定する”だけでは続きません。権限のドリフトを検出する仕組みを導入し、バックアップ関連ロールに削除や短期リテンションの権限が付与されていないかを毎日チェックします。鍵はKMSやHSMで保持し、ローテーションは自動化、材料の持ち出しはDLPで監視します。人的な誤りを前提に、二者承認と時間的遅延を加えることが効果的で、緊急時にはブレークグラス手順でのみ短期的に緩和できるようにしておきます。監査は四半期単位で証跡を束ね、取締役会や監査委員会に“復旧性”の実測を報告します⁸。これらの統制が、バックアップからの迅速なリストアを最終的に担保します。

経営に効くROIとロードマップ

投資判断の肝は、復元成功率の引き上げがどれだけ損失を圧縮するかにあります。SaaS型のバックアップに切り替えた場合のTCO、重複排除アプライアンスによる容量削減、イミュータブルストレージの追加コスト、演習の自動化で削減できる人件費、といった要素を一段のモデルに落とします。PoCでは“1TB、1000万ファイル、変更率3%/日、RTO4時間、RPO15分”のような現実的な条件を設定し、圧縮・重複排除後の実保存量、ネットワーク帯域の占有、ナイトリースロットの競合、復元後のアプリケーション整合性まで計測します。例えばS3 Standard + Object Lock + クライアント暗号化 + 週次DR演習の組み合わせを前提にした試算例では、平均復元時間が45%短縮、完全復元成功率が**+18ポイント**、ストレージ実効コストが**−28%**となる可能性があります。機材や回線、ワークロードで結果は揺れますが、方向性の再現性は高いと期待できます⁷。

短期は“壊れない保存”に集中し、中期は“復元時間を縮める”へ軸足を移し、長期は“人に依存しない復旧”へ移行します。短期ではオブジェクトロックと鍵管理の強化を先行し、運用権限の棚卸しを同時に進めます。中期ではDR環境のIaC化と演習の自動化で、RTO/RPOをSLOに納めます。長期ではアプリケーション側の再構成自動化、データ整合性検査の内製ランナー、さらには攻撃検知との自動連携で、攻撃兆候をトリガにバックアップ経路の閉塞と追加スナップショット取得を同時に走らせる“攻防連携”を実現します。これらはすべて、バックアップ戦略と復元手順を一体で最適化するロードマップです。

関連リーディング

ゼロトラストの視点からバックアップ権限を設計したい方は、ランサムウェア対策の全体像は、鍵と秘密情報の安全な取り扱いは。

まとめ——“復元できる”を積み上げる

バックアップのゴールは取得ではなく復元です。暗号化・隔離・改ざん防止を組み合わせ、イミュータブルな保存先を用意し⁷、CIに組み込んだ復元演習で“今日も戻せる”という事実を積み上げましょう⁴。技術的にはオブジェクトロック、クライアント暗号化、権限分離、ハッシュ検証という基礎を外さず、運用では指標とダッシュボードで“見える化”し続けます。経営にはRTO/RPOと成功率の改善を数値で示し、投資の正当性を透明に保つことが重要です。あなたの環境でまず一つ、削除が物理的にできない保護を有効化し、週次で小さな復元演習(リストアテスト)を回してみてください。小さな成功を反復することが、非常時の生存率を最大化する最短経路です。

参考文献

  1. Sophos. The impact of compromised backups on ransomware outcomes (2024). https://news.sophos.com/en-us/2024/03/26/the-impact-of-compromised-backups-on-ransomware-outcomes/
  2. Infosecurity Magazine. Backup Targeted in 93% of Ransomware Attacks (Veeam data). https://www.infosecurity-magazine.com/news/backup-targeted-93-per-cent/
  3. ZDNET Japan. 被害に遭ったシステム・機器のバックアップ状況…(国内統計/復旧失敗の理由). https://japan.zdnet.com/article/35201507/#:~:text=%E8%A2%AB%E5%AE%B3%E3%81%AB%E9%81%AD%E3%81%A3%E3%81%9F%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%83%BB%E6%A9%9F%E5%99%A8%E3%81%AE%E3%83%90%E3%83%83%E3%82%AF%E3%82%A2%E3%83%83%E3%83%97%E7%8A%B6%E6%B3%81%EF%BC%88%E5%90%8C139%E4%BB%B6%EF%BC%89%E3%81%A7%E3%81%AF%E3%80%81%E3%83%90%E3%83%83%E3%82%AF%E3%82%A2%E3%83%83%E3%83%97%E3%82%92%E5%8F%96%E5%BE%97%E3%81%97%E3%81%A6%E3%81%84%E3%81%9F%E7%B5%84%E7%B9%94%E3%81%8C116%E4%BB%B6%E3%81%AB%E4%B8%8A%E3%81%A3%E3%81%9F%E3%80%82%E3%81%97%E3%81%8B%E3%81%97%E3%80%81%E3%83%90%E3%83%83%E3%82%AF%E3%82%A2%E3%83%83%E3%83%97%E3%81%8B%E3%82%89%E5%BE%A9%E6%97%A7%E3%82%92%E8%A9%A6%E3%81%BF%E3%81%9F%E7%B5%84%E7%B9%94%EF%BC%88%E5%90%8C%20111%E4%BB%B6%EF%BC%89%E3%81%AE%E3%81%86%E3%81%A910%E4%BB%B6%E3%81%A7%E3%81%AF%E3%80%81%E8%A2%AB%E5%AE%B3%E7%9B%B4%E5%89%8D%E3%81%AE%E6%B0%B4%E6%BA%96%E3%81%AB%E3%81%BE%E3%81%A7%E5%BE%A9%E6%97%A7%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%8B%E3%81%A3%E3%81%9F%E3%80%82
  4. CISA. Stop Ransomware: Ransomware Guide. https://www.cisa.gov/stopransomware/ransomware-guide
  5. ENISA. Secure Backups (3-2-1 and related guidance). https://www.enisa.europa.eu/securesme/cyber-tips/strengthen-technical-measures/secure-backups
  6. AWS Prescriptive Guidance. Encryption best practices for Amazon S3. https://docs.aws.amazon.com/prescriptive-guidance/latest/encryption-best-practices/s3.html
  7. AWS Documentation. Amazon S3 Object Lock overview. https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lock-overview.html
  8. AWS Well-Architected Framework. Secured backups (Reliability). https://docs.aws.amazon.com/wellarchitected/latest/framework/rel_backing_up_data_secured_backups_data.html