攻撃を知り、防ぐ

ランサムウェアが、サーバーでしていること

暗号化して元を消す動きの検知、おとりによる隔離と解除、鍵の手がかりになる乱数の記録、バックアップの新しさの診断を、ダミーのファイルで試します。

  • レベル: 基礎
  • 約40分
  • 2026-11-12

#ランサムウェアが、サーバーでしていること

ランサムウェアは、ファイルを暗号化して読めなくし、元に戻す鍵と引き換えに金銭を求めます。サーバーで狙われるのは、アプリのデータ、Web のドキュメントルート、データベース、バックアップです。

動きは、おおよそ次の順に進みます。

段階起きること
入る脆弱性や盗まれた認証情報で、サーバーに入る
戻す手段を消すスナップショットやバックアップを消す
暗号化するファイルを暗号文に置き換え、元のファイルを消す
脅す身代金の要求を置く。盗んだデータの公開をほのめかすこともある

この講座では、暗号化の段階を、使い捨ての VM でまねます。本物の暗号化ツール(openssl)を使いますが、暗号化するのは、その場で作ったダミーのファイルだけです。扱う機能は、大量暗号化の検知、おとりファイルによる検知、暗号化に使われた乱数の記録(期限つき)、バックアップの新しさの診断 です。

見張っている範囲を確かめる

何も変更しない操作です。どの手法を、どこまで見ているかは、detection-coverage で分かります。

sudo roamswitch detection-coverage --server | grep -A3 -e T1486 -e T1490
sudo journalctl -u roamswitch-server -b | grep -oE 'following these folders.*|Total monitored canaries.*' | tail -2
sudo find / -xdev -name '.roamswitch_security_canary*' | sort
sudo ls /var/lib/roamswitch/canary
出力の抜粋(Ubuntu 24.04、Web サーバーなし)
  🟡 T1486 Data Encrypted for Impact  [一部]  稼働中
      担当: ransomwareCanaryGuard, entropyWatch
      見えない部分: おとりのファイルは触られたときだけ反応します。エントロピーの監視が見るのは、監視するフォルダー(ドキュメントルート、/var/www、/srv、MariaDB・MySQL・PostgreSQL・MongoDB・Redis の標準のデータの置き場、または entropy_watch_dirs)に書かれたファイルの先頭だけで、1秒に読むのは entropy_watch_max_files_per_sec 個までです。(中略)既定では通知だけで、書き手を止めるのは entropy_watch_freeze をオンにしたときと、ドキュメントルートで entropy_docroot_action=freeze_writer にして、Web サービスが元からあったファイルを置き換えたときです(新しいファイルを増やすだけのアップロードは通知だけです)。

  🟡 T1490 Inhibit System Recovery  [一部]  稼働中
      担当: execRecorder
      見えない部分: 知らせるのは、既知のスナップショット管理ツール以外が btrfs subvolume delete や lvremove を実行したときだけです(EXR-008)。バックアップファイルを消すなど、復旧手段をなくすほかの方法は見ていません。
following these folders roots=["/srv"]
Total monitored canaries: 16
/etc/roamswitch/.roamswitch_security_canary_do_not_delete.pdf
/etc/roamswitch/.roamswitch_security_canary_do_not_delete.xlsx
/etc/roamswitch/.roamswitch_security_canary_do_not_delete.zip
/opt/.roamswitch_security_canary_do_not_delete.pdf
(中略)
/srv/.roamswitch_security_canary_do_not_delete.zip
customer_database_export.csv
financial_statement_2026.xlsx
personal_vault_backup.kdbx
project_source_archive.zip

暗号化(T1486)は、2つの仕組みで見ています。

  • エントロピーの監視(entropyWatch): 監視するフォルダーに書かれたファイルの中身を読みます。この VM では /srv だけを見ていました。ドキュメントルートや /var/www が無いためです
  • おとりのファイル(ransomwareCanaryGuard): 12 個の隠しファイルと、/var/lib/roamswitch/canary の 4 個、合わせて 16 個を見ています

Web サーバーが配信するフォルダー(/var/www/html など)には、おとりを置きません。誰でも取得できてしまうためです。ドキュメントルートを守るのはエントロピーの監視だけで、止めるかどうかは entropy_docroot_action で決めます(自動隔離の方針の設定 で試します)。

戻す手段を消す動き(T1490)で見ているのは、スナップショットを消すコマンドだけです。バックアップのファイルを消されても、知らせません。

#暗号化して元を消す動きを見つける

ランサムウェアの多くは、暗号文を新しいファイルに書いてから、元のファイルを消します。大量暗号化の検知 は、この動きを見ます。中身が暗号化されたように見えるファイルを、1つの書き手が 5 秒に 20 個書くと、通知します(設定ファイルの注記)。

平文のファイルを、暗号文に置き換える

練習用の 2 つのスクリプトを作ります。1つめは、平文のダミーのファイルを 40 個作ります。2つめは、各ファイルを openssl で暗号化して .locked を付け、元を消します。パスワードは練習用の文字列です。

cd ~
cat > make-dummies.sh <<'S'
#!/bin/sh
# 練習用: 中身が平文のダミーのファイルを 40 個作る
mkdir -p "$1"; cd "$1" || exit 1
for i in $(seq 1 40); do
  yes "invoice $i: dummy line for practice" | head -c 8192 > "report_$i.txt"
done
S
cat > encrypt-demo.sh <<'S'
#!/bin/sh
# 練習用: ランサムウェアの動きをまねる。暗号化した複製を書き、元を消す
cd "$1" || exit 1
for f in report_*.txt; do
  openssl enc -aes-256-cbc -pbkdf2 -pass pass:practice -in "$f" -out "$f.locked" && rm "$f"
done
S
chmod +x make-dummies.sh encrypt-demo.sh
sudo mkdir -p /srv/appdata && sudo chown "$USER" /srv/appdata

平文のファイルを作ってから、暗号化します。

./make-dummies.sh /srv/appdata
sleep 6
./encrypt-demo.sh /srv/appdata
ls /srv/appdata | head -3
sleep 8
sudo roamswitch notifications | grep -A22 -m1 '続けて書かれました'
出力の抜粋
report_1.txt.locked
report_10.txt.locked
report_11.txt.locked
  監視中のフォルダーに、暗号化されたように見えるファイルが続けて書かれました
    🚨 監視しているフォルダーで、中身が暗号化されたように見えるファイルが、1つのプロセスから5秒のあいだに 21 個書かれました(平均エントロピー 7.98 ビット/バイト)
    ホスト: ubuntu (IP: 192.168.64.8)
    /srv/appdata/report_1.txt.locked
    /srv/appdata/report_10.txt.locked
    (中略)
    ... +11
    対応: 通知のみ(プロセスは止めていません)。書き込んだプロセスを自動で止めるには、/etc/roamswitch/server.conf で entropy_watch_freeze=true にして再起動してください
    推奨対応: このプロセスがここに書き込んでよいものか確認してください。心当たりがなければ止め、バックアップから元のファイルを戻し、侵入の経路(Web サーバーのアクセスログ、直近のログイン)を調べてください。
    時刻: 2026-11-12 01:26:24
    プロセス: admin / /usr/bin/dash / コマンド: /bin/sh ./encrypt-demo.sh /srv/appdata (pid 1333)
    親プロセス: dash ← tart-guest-agent ← systemd / サービス: tart-guest-agent.service
    暗号化されたファイルの復号ツールを探す(公開されている場合だけ・無償): No More Ransom https://www.nomoreransom.org/ja/decryption-tools.html / 警察庁 https://www.npa.go.jp/bureau/cyber/countermeasures/ransom.html

読み方は次のとおりです。

  • 平文のファイル 40 個を書いたときは、通知は出ませんでした。エントロピー(中身のでたらめさ)が低いからです
  • 暗号文は、平均 7.98 ビット/バイトでした。上限は 8 で、暗号文やランダムなバイト列は、この近くになります
  • プロセスの行は、openssl ではなく、ループを回したスクリプト(encrypt-demo.sh)を指しています。止めるなら、この PID です
  • 対応の行のとおり、既定では止めません。書き手を止める(SIGSTOP)のは、entropy_watch_freeze=true にして再起動したときだけです
  • 最後の行は、公開されている復号ツールの探し先です
openssl で書いたのに、なぜ数えたのか

ソースの注記では、python3、openssl、gpg は、自分で作るファイルについては信頼される書き手です。暗号化したファイルを作るだけでは、数えません。同じフォルダーで、ほぼ同じ数の元のファイルが 5 秒以内に消えると、その書き手か、親(シェルのループ)を数えます。この VM のデーモンのログにも、created 21 high-entropy files while unlinking as many in the same folders within 5s と残りました。

openssl と rm は数ミリ秒で終わるので、見張りが読むときには、書き手がもういないことがあります。そのときは、フォルダーで数えます(同じフォルダーで 5 秒のうちに 20 個できて、同じ数が消えた)。ログは their writers had exited before they could be read; the process that removed them: 2166 の形になり、通知のプロセスの行は、ループを回したスクリプトを指しました。同じフォルダーで続けて 6 回流すと、6 回とも通知が出ました。個数は 21〜35 個でした。前の回の .locked の書き直しも数えます。

監視するフォルダーの外では、同じ動きでも通知は出ません。アプリのデータを /opt などに置いているなら、entropy_watch_dirs に足します。

監視するフォルダーを足す

設定ファイルを書き換え、デーモンを再起動する操作です(変更を伴う操作です)。前の演習のスクリプトを、/opt/appdata で動かします。

sudo mkdir -p /opt/appdata && sudo chown "$USER" /opt/appdata
./make-dummies.sh /opt/appdata; sleep 3; ./encrypt-demo.sh /opt/appdata; sleep 8
sudo journalctl -u roamswitch-server --since -15s | grep -c burst
sudo roamswitch server config set entropy_watch_dirs /srv,/opt/appdata
sudo roamswitch server restart
sleep 8
sudo journalctl -u roamswitch-server --since -12s | grep -o 'following these folders.*'
rm -f /opt/appdata/*
./make-dummies.sh /opt/appdata; sleep 3; ./encrypt-demo.sh /opt/appdata; sleep 8
sudo roamswitch notifications | grep -A3 -m1 '続けて書かれました'
出力の抜粋
0
  ✓ サーバー設定を更新・保存しました。 (entropy_watch_dirs = /srv,/opt/appdata)
  反映するには: sudo systemctl restart roamswitch-server または sudo roamswitch server restart

  🔄 roamswitch-server サービスを再起動中...
  ✓ roamswitch-server サービスを正常に再起動しました。

following these folders roots=["/opt/appdata", "/srv"]
  監視中のフォルダーに、暗号化されたように見えるファイルが続けて書かれました
    🚨 監視しているフォルダーで、中身が暗号化されたように見えるファイルが、1つのプロセスから5秒のあいだに 21 個書かれました(平均エントロピー 7.98 ビット/バイト)
    ホスト: ubuntu (IP: 192.168.64.8)
    /opt/appdata/report_1.txt.locked

足す前は、デーモンのログに、大量暗号化(burst)の記録が 0 件でした。足して再起動すると、同じ動きで通知が出ました。設定は、保存しただけでは効きません。再起動が要ります。

元に戻すときは、空にして再起動します。

sudo roamswitch server config set entropy_watch_dirs ""
sudo roamswitch server restart

ログの見るフォルダーが roots=["/srv"] に戻れば、元どおりです。

書いたフォルダーだけを見るようになります

entropy_watch_dirs が空のときだけ、ドキュメントルート、/var/www、/srv、データベースの標準のフォルダーを見ます(設定ファイルの注記とソース)。値を書くと、書いたフォルダーだけを見ます。既定の場所も見続けたいときは、上の例の /srv のように、一緒に書きます。書けるのは 32 個までです。

#おとりのファイルが書き換えられたとき

おとりファイルによる検知 は、おとりのファイルの書き換えを見ます。おとりは、ふつうの作業では触らない名前の隠しファイルです。Server Edition では、書き換えを見つけると、ホスト全体を隔離します。

おとりを暗号文で上書きする

ホスト全体の通信を止める操作です(変更を伴う操作です)。SSH の保守用のポートは残りますが、必ず使い捨ての環境で試してください。ランサムウェアと同じように、おとりを暗号文で上書きします。

sudo sh -c 'openssl enc -aes-256-cbc -pbkdf2 -pass pass:practice -in /srv/.roamswitch_security_canary_do_not_delete.pdf -out /tmp/x.locked && cp /tmp/x.locked /srv/.roamswitch_security_canary_do_not_delete.pdf'
sleep 3
sudo roamswitch server ebpf | sed -n 5,6p
curl -sS -m 5 -o /dev/null https://example.com; echo "curl rc=$?"
sudo roamswitch notifications | grep -A10 -m1 'カナリア発火'
出力の抜粋
  現在の隔離状態: [隔離中: host_with_maintenance_ssh]
  保守用開放ポート: [22]
curl: (28) Connection timed out after 5003 milliseconds
curl rc=28
  ランサムウェア・カナリア発火
    🚨 カナリア(おとり)ファイルが改ざん / 暗号化書き込みされました
    ホスト: ubuntu (IP: 192.168.64.8)
    対象デコイ: /srv/.roamswitch_security_canary_do_not_delete.pdf
    疑わしいプロセス: cp (PID: 3074)
    実行した封じ込め: ホストをAir-Gap隔離しました(原因プロセス(cp、PID 3074)は、すでに終了していたため、凍結できませんでした)
    時刻: 2026-11-12 01:28:37
    プロセス: root / /usr/bin/cp / コマンド: cp /tmp/x.locked /srv/.roamswitch_security_canary_do_not_delete.pdf (pid 3074) ※プロセスは既に終了していたため、実行の記録(2026-11-12 01:28:36)から補いました。
    親プロセス: dash ← sudo ← dash ← tart-guest-agent ← systemd / サービス: tart-guest-agent.service
    暗号化されたファイルの復号ツールを探す(公開されている場合だけ・無償): No More Ransom https://www.nomoreransom.org/ja/decryption-tools.html / 警察庁 https://www.npa.go.jp/bureau/cyber/countermeasures/ransom.html

おとりは、書かれたらすぐに調べます(inotify)。この VM のデーモンのログでは、コマンドを始めてから 0.1 秒足らずで Canary file TAMPERED が出ました。待つのは 3 秒で足ります。

外への通信は止まりました。保守用に、SSH の 22 番は開けたままです。書き換えた cp はすでに終わっていたので、凍結はしていません。通知の最後の行は、公開されている復号ツールの探し先です。RoamSwitch が復号するわけではありません。

この隔離は、cp が終わっていても、自動では解けません。調べ終わったら、確認応答を返し、隔離を解きます。原因が消えたと確かめられないので、emergency-restore は RESTORE の入力を求めます。入力できない形(パイプなど)で動かすと、何もせずに終了コード 2 で終わります。最後の再起動で、ふだんの守りの規則を入れ直します。

sudo roamswitch server ack
sudo roamswitch emergency-restore
curl -sS -m 5 -o /dev/null https://example.com; echo "curl rc=$?"
sudo roamswitch server restart
sleep 10
sudo head -c 32 /srv/.roamswitch_security_canary_do_not_delete.pdf; echo
出力の抜粋
  ✓ 現在の緊急隔離(18秒経過)を確認しました。確認済みの間は自動で縮退・復旧せず、現在の隔離を維持します。
  解除するには: sudo roamswitch emergency-restore
  現在の状態:
    隔離中(原因: ランサムウェア用おとりファイルの改ざん, 段階: 全面)

  ⚠️ 隔離の原因が解消したことを、確認できていません。この状態でネットワークを元に戻すと、原因が残っている場合、その影響を受けたまま通信が再開します。
  続けるには RESTORE と入力してください:
  🔄 緊急遮断・隔離ルールを全解除し、ベースラインへ復旧中...
    ✓ 隔離の記録
    ✓ 通信を止めうるファイアウォールのテーブル
    ✓ DNSの設定
    ✓ 接続の追跡
  次のファイアウォールのテーブルは、隔離ではないので残しました:
    - roamswitch_server: サーバーの受信の規則(ssh_ports・allowed_ports だけを通す、ふだんの防御)
  ✓ ネットワークを復旧しました。
  ポートスキャンの検知など、ここで外した規則は、再起動まで戻りません。戻すには: sudo systemctl restart roamswitch-server
  原因が残っている可能性があります(原因が消えたことは確かめられていません)。何が起きたかは roamswitch timeline で確かめてください。

curl rc=0
%PDF-1.4 ROAMSWITCH_CANARY_INTEG

emergency-restore は、最初に隔離の原因と段階(全面)を出します。プロンプトで RESTORE と入力すると、外した項目を並べ、通信が戻りました。ふだんの受信の規則(roamswitch_server)は残します。おとりも元の中身に戻っています。

隔離の間に外へ送れなかった通知は、解除のあとで、見出しに 【遅延送信】 を付けて送り直されます。この VM の通知の履歴にも、【遅延送信】 ランサムウェア・カナリア発火 が残りました。隔離の最中は、外の通知先に届かないことがある、と考えておきます。

隔離の範囲、自動で解ける条件、確認応答の使い方は、自動隔離の方針の設定 で詳しく扱います。

#鍵の手がかりを残しておく

暗号化の鍵は、カーネルから受け取った乱数で作ります。暗号化に使われた乱数の記録(期限つき) は、プロセスが受け取った乱数を、期限つきで記録します。その型のランサムウェア向けの復号ツールがあれば、鍵を作り直す手がかりになります。RoamSwitch は記録するだけで、復号はしません。 復号できるとは限りません。

既定はオフです(prn_record=false)。roamswitch-prn-recorder の status・export・purge は、roamswitch と同じく、動かす人の言語(LANG)で出ます。保持は既定で 24 時間(prn_retention_hours、1〜168)、容量は既定で 256 MiB(prn_max_mib、16〜4096)です。

乱数の記録を、オンにして、消す

設定ファイルを書き換え、デーモンを再起動する操作です(変更を伴う操作です)。

sudo roamswitch-prn-recorder status
sudo roamswitch server config set prn_record true
sudo roamswitch server restart
sleep 10
sudo roamswitch-prn-recorder status
出力の抜粋
記録していません
保存済み: セグメント 0 個、0 バイト
[OK] root: root で動いています
[OK] kernel: 7.0.0-42-generic(BPF のリングバッファには 5.8 以降が要ります)
[OK] btf: /sys/kernel/btf/vmlinux
[OK] driver hook: 負荷のかからない方法が仕掛けるカーネルの関数があります
[OK] tracepoints: syscalls:sys_enter_getrandom が使えます
[WARN] vdso: このカーネルの vDSO は getrandom を出しています: それを使う C ライブラリ(glibc 2.41 以降)はシステムコールなしで乱数を返すので、その乱数は記録されません。x86-64 では、カーネルパラメータ vdso=0 で vDSO を止められます
  ✓ サーバー設定を更新・保存しました。 (prn_record = true)
  反映するには: sudo systemctl restart roamswitch-server または sudo roamswitch server restart

記録中です
取った乱数は約 1 秒以内にファイルへ書き込まれ、書き出し(export)に入るのはそのあとです
保持期限 24 時間、容量の上限 256 MiB
この起動から: 記録した件数 95、除外した自分の件数 1、カーネルで取りこぼした件数 0
記録の方法: カーネルの乱数の関数に仕掛けています(他の処理に負荷なし。書き出しの source は、乱数をシステムコールで受け取ったことを示す syscall です)
保存済み: セグメント 1 個、6468 バイト
最も古い記録は約 0 分前、最も新しい記録は約 0 分前
(中略)

最初の status は、このマシンで記録できるかも点検します。2 回目の「最も古い記録は約 0 分前」は、最初の記録の時刻から数えた分です。再起動の 10 秒後なので 0 分でした。[WARN] vdso は、glibc 2.41 以降の C ライブラリが使う経路では記録できない、という意味です。この VM の glibc は 2.39 でした。

前の章のスクリプトで暗号化をまねて、記録を書き出します。

./make-dummies.sh /tmp/prn-demo
./encrypt-demo.sh /tmp/prn-demo
sleep 5
sudo roamswitch-prn-recorder export --output /root/prn.jsonl --since-hours 1
P=$(sudo grep -m1 '"command":"openssl"' /root/prn.jsonl | sed 's/.*"pid":\([0-9]*\).*/\1/'); echo "first openssl pid=$P"
sudo roamswitch-prn-recorder export --output /root/prn-one.jsonl --pid $P
sudo ls -l /root/prn-one.jsonl
sudo cut -c1-120 /root/prn-one.jsonl
出力の抜粋
330 件を /root/prn.jsonl に書き出しました
注意: このファイルには鍵の元になる乱数が入っています。保持期限は適用されません。使い終わったら、自分で安全に削除してください
first openssl pid=3950
2 件を /root/prn-one.jsonl に書き出しました
注意: このファイルには鍵の元になる乱数が入っています。保持期限は適用されません。使い終わったら、自分で安全に削除してください
-rw------- 1 root root 654 Nov 12 01:29 /root/prn-one.jsonl
{"captured_length":8,"operation":"getrandom","process":{"command":"openssl","pid":3950,"tid":3950},"requested_length":8,
{"captured_length":48,"operation":"getrandom","process":{"command":"openssl","pid":3950,"tid":3950},"requested_length":4

status の 2 行目のとおり、取った乱数がファイルに書き込まれるのは、約 1 秒あとです。暗号化の直後に書き出すと、openssl の記録が入らないことがあります。sleep 5 は、そのための待ち時間です。

--pid で、1つのプロセスが受け取った乱数だけを取り出せます。通知に出た PID で絞るときに使います。書き出したファイルは -rw-------(root だけが読める)です。

オフに戻すと、記録は消えます。

sudo roamswitch server config set prn_record false
sudo roamswitch server restart
sudo roamswitch-prn-recorder status
sudo journalctl -u roamswitch-server --since -10s | grep -o 'prn_record is off.*'
sudo rm -f /root/prn.jsonl /root/prn-one.jsonl
出力の抜粋
記録していません
保存済み: セグメント 0 個、0 バイト
(中略)
prn_record is off: the recorded random bytes were removed removed=1

書き出したファイルは、期限でも、オフにしても消えません。最後の行のように、自分で消します。

記録は、鍵そのものとして扱います

設定ファイルの注記では、この記録には、このホストの TLS や SSH の通信の秘密も入ります。オンにするのは、記録を root だけが扱えると確かめたときにします。書き出したファイルを、チャットや Issue に貼らないでください。

#戻せる状態を保つ

暗号化を見つけても、すでに暗号化されたファイルは戻りません。戻すには、バックアップが要ります。バックアップの新しさの診断 は、最後のバックアップが 7 日以内に動いたかを診断します。restic、borg、Timeshift、snapper、rsnapshot、systemd のタイマー、cron などから探します。

バックアップの新しさを診断する

systemd のユニットを置き、バックアップを動かす操作です(変更を伴う操作です)。練習用に、/srv/appdata を tar で固めます。前の章で暗号化したファイルは消し、平文のダミーを作り直してから始めます。

rm -f /srv/appdata/*; ./make-dummies.sh /srv/appdata
sudo roamswitch status --server | grep -A3 'バックアップの最新性'
sudo tee /etc/systemd/system/appdata-backup.service >/dev/null <<'U'
[Unit]
Description=Practice backup of /srv/appdata

[Service]
Type=oneshot
ExecStart=/usr/bin/tar -czf /var/backups/appdata.tgz -C /srv appdata
U
sudo systemctl daemon-reload
sudo systemctl start appdata-backup.service
sudo roamswitch status --server | grep -A1 'バックアップの最新性'
sudo tee /etc/systemd/system/appdata-backup.timer >/dev/null <<'U'
[Unit]
Description=Daily practice backup of /srv/appdata

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target
U
sudo systemctl daemon-reload
sudo systemctl enable --now appdata-backup.timer
sudo systemctl start appdata-backup.service
sudo roamswitch status --server | grep -A1 'バックアップの最新性'
出力の抜粋
  [要対策] バックアップの最新性 - バックアップの仕組みが見つかりません
         restic・borg・Timeshift・snapper・rsnapshot・systemd のタイマー・cron などから、最後にバックアップが実行された日時を調べ、7日以内かどうかを確認します。復元できるかどうかまでは確認しません。復元テストは利用者のファイルを書き換えるため、自動では行いません。
         ↳ 定期的に動くバックアップを用意してください (例: restic や borg を systemd のタイマーで毎日実行する、デスクトップなら Timeshift や Déjà Dup)。保存先は、この端末とは別のディスクかサーバーにしてください。ほかの方法でバックアップを取っている場合は、この項目は無視して構いません。
         準拠: CIS 11.2 / NIST CSF PR.DS-11
  [要対策] バックアップの最新性 - バックアップの実行の記録はありますが、定期的に動かす設定 (systemd のタイマー・cron) が見つかりません (backup)
         restic・borg・Timeshift・snapper・rsnapshot・systemd のタイマー・cron などから、最後にバックアップが実行された日時を調べ、7日以内かどうかを確認します。(中略)
Created symlink /etc/systemd/system/timers.target.wants/appdata-backup.timer → /etc/systemd/system/appdata-backup.timer.
  [合格] バックアップの最新性 - 最後のバックアップは24時間以内です (backup)
         準拠: CIS 11.2 / NIST CSF PR.DS-11

ユニットの名前に backup が入っているので、バックアップの仕組みとして見つかりました。最後の実行の時刻は、systemd の記録(ExecMainExitTimestamp)から取ります。

サービスを 1 度動かしただけでは、[要対策] のままです。定期的に動かす設定(タイマーか cron)が無いからです。タイマーと組にして動かすと、合格になりました。

次に、バックアップを失敗させます。固める元を、無いフォルダーに変えます。

sudo mkdir -p /etc/systemd/system/appdata-backup.service.d
printf '[Service]\nExecStart=\nExecStart=/usr/bin/tar -czf /var/backups/appdata.tgz -C /srv no-such-folder\n' | sudo tee /etc/systemd/system/appdata-backup.service.d/break.conf >/dev/null
sudo systemctl daemon-reload
sudo systemctl start appdata-backup.service
sudo roamswitch status --server | grep 'バックアップの最新性'
sudo rm -r /etc/systemd/system/appdata-backup.service.d
sudo systemctl daemon-reload
sudo systemctl start appdata-backup.service
sudo roamswitch status --server | grep 'バックアップの最新性'
出力の抜粋
Job for appdata-backup.service failed because the control process exited with error code.
  [要対策] バックアップの最新性 - 直近のバックアップが失敗しています (backup: appdata-backup.service)
  [合格] バックアップの最新性 - 最後のバックアップは24時間以内です (backup)

直近の実行が失敗すると、その前に成功していても、[要対策] に変わります。直して動かし直すと、合格に戻りました。

診断は、戻せるかどうかまでは確かめません。戻せるかは、別の場所に展開して比べます。

rm -rf /tmp/restore-test; mkdir /tmp/restore-test
tar -xzf /var/backups/appdata.tgz -C /tmp/restore-test
ls /tmp/restore-test/appdata | wc -l
diff -r /srv/appdata /tmp/restore-test/appdata && echo "same as /srv/appdata"
実行結果
40
same as /srv/appdata

元に戻すときは、タイマーとユニットを消します。/etc/systemd/system に新しいユニットを置くと、その場で、重要なファイルの監視(FIM)の通知が出ます(書いたプロセスつき)。消せば、sudo roamswitch fim verify は元どおりになります。残すユニットなら、sudo roamswitch fim update で基準を更新します。

sudo systemctl disable --now appdata-backup.timer
sudo rm -f /etc/systemd/system/appdata-backup.service /etc/systemd/system/appdata-backup.timer /var/backups/appdata.tgz
sudo systemctl daemon-reload
やってはいけないこと
  • バックアップを、守りたいデータと同じディスクに置いたまま済ませる。この演習の /var/backups は、練習のための置き場です。ランサムウェアは、同じマシンから読み書きできるものを暗号化します
  • 暗号化の通知が来たあとで、バックアップから急いで戻す。侵入の経路が残っていれば、戻したファイルも暗号化されます。先に書き手を止め、経路を調べます
  • 戻せることを、1度も試さないまま、バックアップがあると考える
暗号化の通知が来たとき
  • 書き手に心当たりがある(自分のバックアップ、アプリの正規の処理): 書き込みの量と場所が、ふだんどおりかを確かめます。ふだんどおりなら、通知の時刻と書き手を記録して、調べ終えます
  • 心当たりがない: 通知の PID の書き手を止めます。既定では止まっていません。止めたら、封じ込めが働いたあとの最初の1時間 の手順で、証拠を残し、侵入の経路を調べます
  • 毎回、止めるまで待てない: entropy_watch_freeze=true にして再起動すると、次からは書き手を自動で止めます。止めないプロセスは protected_processes で決めます

#見えない部分

この VM で確かめたことと、確かめた範囲
  • 監視するフォルダーの外は見ません。/opt/appdata は、足すまで、同じ暗号化でも記録が 0 件でした
  • 遅い暗号化は見えません。1つの書き手が 5 秒に 20 個に満たないと、数えません(detection-coverage の説明)
  • 別のコマンドで被せる形は数えません。暗号文を別の場所に作り、cp や mv を別のコマンドとして動かして既存のファイルに被せる形です(detection-coverage の説明)。この形でも、おとりを書き換えれば、おとりのほうが反応します。この講座の演習でも、cp で被せたおとりで、ホストが隔離されました
  • おとりは、触られたときだけ反応します。おとりの無いフォルダーだけを暗号化されると、おとりは反応しません
  • 乱数の記録は、vDSO の経路を見ません。glibc 2.41 以降の C ライブラリが、システムコールを使わずに受け取った乱数は記録されません(roamswitch-prn-recorder status の点検と、設定ファイルの注記)
  • バックアップの診断は、知っている道具と名前だけを探します。自作のスクリプトや、外部のサービスのエージェントでのバックアップは、「見つかりません」になります。戻せるかは確かめません
確認問題

暗号化の通知が来ました。entropy_watch_freeze は変えていません。書き込んだプロセスは、どうなっていますか

解説を見る

entropy_watch_freeze の既定は false で、通知の「対応」の行にも「通知のみ(プロセスは止めていません)」と出ます。止めるのは、自分で行います。ホスト全体の隔離は、おとりが書き換えられたときの対応です。

確認問題

「バックアップの最新性」が合格になりました。言えることはどれですか

解説を見る

診断が見るのは、最後の実行の時刻と結果と、定期的に動かす設定があるかだけです。置き場所や、戻せるかどうかは見ません。戻せるかは、演習のように、別の場所に展開して比べて確かめます。

#次に学ぶこと

扱う機能

対応する攻撃手法 (ATT&CK): T1486

確認した内容

2026-11-12に確認しました。対象は Linux 1.17.39 です。使い捨ての Ubuntu 24.04 の VM(公開版 1.17.39)で、openssl による暗号化、監視するフォルダーの追加、おとりの上書き(3 秒の待ちで検知・隔離)と端末からの RESTORE での解除、乱数の記録と書き出し(LANG での言語の切り替えと「最も古い記録」の分)、タイマーの有無でのバックアップの診断を、日本語と英語で実行して確かめました。

コマンドの出力は、製品の版や環境によって変わります。違いが出たら、まず製品の版を確かめてください。