TT Lab
はじめる
学ぶ 学習パス コース

cron が午前三時に curl を叩いた

cron が午前三時に curl を叩いた

TT Labで続きを見る

このラボはVM上で動きます

Ubuntu 24.04のVM1台に、Falcoがmodern eBPFドライバーですでに起動しています。システムコールの計装はカーネルの機能なので、ラボのPodではまったく不可能です。立ち上がるのに2–3分かかります(Falcoをインストールするためです)。

目標

タイトルのインシデントを捕まえるルールを自分で書きます。リストとマクロを分け、アラートをJSONファイルに残し、実際にスケジュールされたジョブを仕込んで、ルールが捕まえることをファイルで確認します。次に、同じルールに引っかかる正常な作業をもう1つ作ってそれだけを例外として除外し、悪いものが引き続き捕まるかを、もう一度確認します。

なぜ重要なのか

ログベースの検知には、構造的な限界があります。ログには、プログラムが残すことにしたものだけが残ります。システムコールは違います。プロセスを作るのも、ファイルを開くのも、カーネルを経由する必要があり、カーネルをだますことはできません。

ところが、システムコールをすべて見ると、アラートが多すぎるようになります。そのため、ランタイム検知の実際の作業は、「何を捕まえるか」ではなく、何を除外してよいかです。ルール1つが正常なバックアップ作業まで捕まえると、数日で誰もアラートを見なくなります。そのときルールを広く緩めると、本物のインシデントも一緒に抜け落ちます。例外を狭く、理由を書いて置いておく習慣が、検知体制の寿命を決めます。

ステップ

  1. Falcoのバージョン・ドライバー・サービスの状態を保存してください(保存先: /root/falco/01-engine.txt)。
  2. list1つ、macro1つ、rule1つで、ルールを書いてください(書き込み先: /etc/falco/rules.d/labhub-cron.yaml)。出力に%user.nameと%proc.cmdlineが入っている必要があります。
  3. JSON出力とファイル出力(/var/log/falco/events.json)を有効にして、サービスを再起動してください(設定ファイル: /etc/falco/config.d/labhub-output.yaml)。
  4. 毎分外部にリクエストするcronファイルを作成してください(作成先: /etc/cron.d/telemetry)。
  5. 1分以上待ってから、捕まえたアラート1行を保存してください(保存先: /root/falco/05-alert.json)。
  6. 同じルールに引っかかる正常な作業をもう1つ置くcronファイルを作成し(作成先: /etc/cron.d/backup-sync)、それだけをルールのexceptionsで除外してから、サービスを再起動してください。
  7. events.jsonを空にしてから、スケジュールされたジョブが1回動くまで待ち、正常な作業は捕まらず、悪いものは捕まるかを確認してください(確認結果の保存先: /root/falco/07-verify.txt)。
  8. ルールの根拠を、## 무엇을 잡는가・## 왜 예외를 두었나・## auditd 와 무엇이 다른가・## 다음에 넓힐 곳(韓国語の見出しで、順に「何を捕まえるのか」「なぜ例外を置いたのか」「auditdと何が違うのか」「次に広げる場所」という意味です)の4つの節で書いてください(保存先: /root/falco/08-report.md)。

参考

何がどのドライバーで動いているか

falco --versionのバージョン番号、どのドライバー(ユニット名)で動いているか、サービスの状態を保存してください(保存先: /root/falco/01-engine.txt)。

systemctl show -p Id --value falcoが、実際のユニット名を教えてくれます。falcoは、そのユニットの別名です。ドライバーが分からないと、「なぜ捕まえられないのか」を探せません。

ルールを1本書く

list1つ・macro1つ・rule1つを書いてください(書き込み先: /etc/falco/rules.d/labhub-cron.yaml)。スケジュールされたジョブの下で外部リクエストのツールが実行されたものを捕まえ、outputに%user.nameと%proc.cmdlineが入っている必要があり、priorityはWARNING以上です。

listとmacroは、自分より前に定義されたものだけを参照できるので、リスト → マクロ → ルールの順に書きます。cronがシェルを起動するので、親ではなく祖先を見る必要があります。書き終えたら、デフォルトのルールファイルと一緒に--validateで確認してください。

アラートをファイルに残す

json_output: trueとファイル出力(/var/log/falco/events.json)を有効にして、サービスを再起動してください(設定ファイル: /etc/falco/config.d/labhub-output.yaml)。falco.yamlをまるごと書き換えないでください。

config.dの下のファイルは、既定の設定に追加されます。再起動したあとにジャーナルを見ると、どの設定ファイルを読んだかが1行ずつ出ます。それが「本当に反映された」ことの証拠です。

インシデントを仕込む

毎分curlで外部にリクエストするcronファイルを作成してください(作成先: /etc/cron.d/telemetry)。/etc/cron.dの形式なので、スケジュールのあとに、実行するユーザーの欄があります。

毎分は* * * * *です。リクエストが実際に成功する必要はありません。プロセスが実行されたという事実が、システムコールで捕まります。

捕まったかをファイルで見る

スケジュールされたジョブが1回動くまで待ってから、/var/log/falco/events.jsonから、自分のルールのアラート1行を選んで保存してください(保存先: /root/falco/05-alert.json)。

jq -c 'select(.rule == "<규칙 이름>")' /var/log/falco/events.json | tail -1なら、1行が出ます(プレースホルダーはルール名です)。ファイルには、Falco内部のアラートも混ざっているので、ルール名で絞り込んでください。

正常なものを狭く除外する

同じルールに引っかかる正常な作業をもう1つ置くcronファイルを作成し(作成先: /etc/cron.d/backup-sync)、それだけをルールの例外(exceptions)で除外してから、サービスを再起動してください。conditionの末尾にand not …を付けないでください。

exceptionsは、name・fields・comps・valuesで書きます。fieldsに見るイベントのフィールドを、compsに比較方法を、valuesに値のまとまりを書くと、エンジンが条件のあとにand not (…)として付けてくれます。値を広く取ると、ステップ7で引っかかります。

両方をもう一度動かしてみる

/var/log/falco/events.jsonを空にしてから、スケジュールされたジョブが1回動くまで(最大1分)待ち、telemetryは捕まり、backup-syncは捕まらないことを確認して、2行以上で書いてください(保存先: /root/falco/07-verify.txt)。

例外は、サービスがルールを読み直して初めて適用されます(前のステップで再起動しました)。古いアラートが残っていると判断が曇るので、ファイルを空にして、新しく受け取ったものだけを見てください。例外が広すぎると、捕まえるべきものまで静かになります。

ルールの根拠を残す

## 무엇을 잡는가・## 왜 예외를 두었나・## auditd 와 무엇이 다른가・## 다음에 넓힐 곳(韓国語の見出しで、順に「何を捕まえるのか」「なぜ例外を置いたのか」「auditdと何が違うのか」「次に広げる場所」という意味です)の4つの節を書いてください(保存先: /root/falco/08-report.md)。exceptions・priority・events.jsonの3つの単語が、本文に出てくる必要があります。

次の人がこのルールを見たときに、最初に消したくなるのが例外です。なぜ置いたのかが書かれていないと、本当に消します。前のモジュールのカーネル監査と、何が重なって何が違うのかも整理しておいてください。