kubestronautへの道 ~CKS編 その13 killer coda「Falco Change Rule」~

tech article

今日覚えて帰ること

Falco

falco_rules.yaml を編集して falco の検知ルールを変更する。

initプロセスが…
ystemd の場合は systemctl restart falco
SysVinit の場合は service falco restart
で再起動して、設定を反映させる

Falco Change Rule

Investigate a Falco Rule

Falco has been installed on Node controlplane and it runs as a service.

It’s configured to log to syslog, and this is where the verification for this scenario also looks.

Cause the rule “shell in a container” to log by:

  1. creating a new Pod image nginx:alpine
  2. kubectl exec pod -- sh into it
  3. check the Falco logs contain a related output

Falcoのログを確認してみよう、という問題です。

そもそもFalcoとは何なんでしょうか。

FalcoはLinux OS向けのランタイムセキュリティツールです。 システム上での異常なアクティビティや潜在的なセキュリティリスクをリアルタイムで検知し、警告するように設計されています。 

KubernetesのPod専用のツールかと思っていましたが、Linux OS 全般に対して使えるみたいです。
ざっくり言うと、システムコールを監視して監視ルールで設定した挙動を検知すると、メールやslackなどに通知するツールです。
詳細はこちら。

FalcoでKubernetesのセキュリティモニタリング
Kubernetesのセキュリティを強化するFalcoの機能を解説。Linuxシステムコールをebpf、カーネルモジュールで監視。Helm Chartを使った簡単デプロイ、Web UIの活用、カスタムルール作成、nginxコンテナでのインシデント検出事例を紹介。

では進めていきましょう。

まずはPodを立てて -it オプションつきでPodに入り込みます。

controlplane $ k run pod --image=nginx:alpine
pod/pod created
controlplane $ k exec -it pod -- sh
/ # 


command terminated with exit code 130

つぎに falco が吐き出したログを確認します。

/var/log/syslog に吐き出されるので cat で出力するのもありです。
しかし今回は journalctl の -u オプションを使って出力してみます。
このコマンドは systemd で管理されている unit を指定して、その unit のログのみを出力する、というものです。

controlplane $ journalctl -u falco
-- Logs begin at Sun 2022-11-13 17:25:58 UTC, end at Fri 2024-08-09 12:52:15 UTC. --
Aug 09 12:48:02 controlplane systemd[1]: Starting Falco: Container Native Runtime Security...
Aug 09 12:48:02 controlplane systemd[1]: Started Falco: Container Native Runtime Security.
Aug 09 12:48:02 controlplane falco[9334]: Falco version 0.32.1
Aug 09 12:48:02 controlplane falco[9334]: Falco initialized with configuration file /etc/falco/falco.yaml
Aug 09 12:48:02 controlplane falco[9334]: Fri Aug  9 12:48:02 2024: Falco version 0.32.1
Aug 09 12:48:02 controlplane falco[9334]: Fri Aug  9 12:48:02 2024: Falco initialized with configuration file /etc/falco/falco.yaml
Aug 09 12:48:02 controlplane falco[9334]: Loading rules from file /etc/falco/falco_rules.yaml:
Aug 09 12:48:02 controlplane falco[9334]: Fri Aug  9 12:48:02 2024: Loading rules from file /etc/falco/falco_rules.yaml:
Aug 09 12:48:03 controlplane falco[9334]: Loading rules from file /etc/falco/falco_rules.local.yaml:
Aug 09 12:48:03 controlplane falco[9334]: Fri Aug  9 12:48:03 2024: Loading rules from file /etc/falco/falco_rules.local.yaml:
Aug 09 12:48:03 controlplane falco[9334]: Starting internal webserver, listening on port 8765
Aug 09 12:48:03 controlplane falco[9334]: Fri Aug  9 12:48:03 2024: Starting internal webserver, listening on port 8765
Aug 09 12:48:22 controlplane systemd[1]: Stopping Falco: Container Native Runtime Security...
Aug 09 12:48:22 controlplane falco[9334]: SIGINT received, exiting...
Aug 09 12:48:22 controlplane falco[9334]: Fri Aug  9 12:48:22 2024: SIGINT received, exiting...
Aug 09 12:48:22 controlplane falco[9334]: Syscall event drop monitoring:
Aug 09 12:48:22 controlplane falco[9334]:    - event drop detected: 0 occurrences
Aug 09 12:48:22 controlplane falco[9334]:    - num times actions taken: 0
Aug 09 12:48:22 controlplane falco[9334]: Events detected: 0
Aug 09 12:48:22 controlplane falco[9334]: Rule counts by severity:
Aug 09 12:48:22 controlplane falco[9334]: Triggered rules by rule name:
Aug 09 12:48:22 controlplane systemd[1]: falco.service: Succeeded.
Aug 09 12:48:22 controlplane systemd[1]: Stopped Falco: Container Native Runtime Security.
Aug 09 12:48:22 controlplane systemd[1]: Starting Falco: Container Native Runtime Security...
Aug 09 12:48:22 controlplane systemd[1]: Started Falco: Container Native Runtime Security.
Aug 09 12:48:23 controlplane falco[9564]: Falco version 0.32.1
Aug 09 12:48:23 controlplane falco[9564]: Fri Aug  9 12:48:23 2024: Falco version 0.32.1
Aug 09 12:48:23 controlplane falco[9564]: Falco initialized with configuration file /etc/falco/falco.yaml
Aug 09 12:48:23 controlplane falco[9564]: Fri Aug  9 12:48:23 2024: Falco initialized with configuration file /etc/falco/falco.yaml
Aug 09 12:48:23 controlplane falco[9564]: Loading rules from file /etc/falco/falco_rules.yaml:
Aug 09 12:48:23 controlplane falco[9564]: Fri Aug  9 12:48:23 2024: Loading rules from file /etc/falco/falco_rules.yaml:
Aug 09 12:48:23 controlplane falco[9564]: Loading rules from file /etc/falco/falco_rules.local.yaml:
Aug 09 12:48:23 controlplane falco[9564]: Fri Aug  9 12:48:23 2024: Loading rules from file /etc/falco/falco_rules.local.yaml:
Aug 09 12:48:23 controlplane falco[9564]: Starting internal webserver, listening on port 8765
Aug 09 12:48:23 controlplane falco[9564]: Fri Aug  9 12:48:23 2024: Starting internal webserver, listening on port 8765
Aug 09 12:48:47 controlplane falco[9564]: 12:48:47.196310756: Error Package management process launched in container (user=root user_loginuid=-1 command=apk manifest nginx container_id=d>
Aug 09 12:50:31 controlplane falco[9564]: 12:50:31.651538468: Error File below / or /root opened for writing (user=root user_loginuid=-1 command=pager parent=journalctl file=/root/.lessh>
Aug 09 12:51:54 controlplane falco[9564]: 12:51:54.176947499: Error Package management process launched in container (user=root user_loginuid=-1 command=apk manifest nginx container_id=f>
Aug 09 12:52:02 controlplane falco[9564]: 12:52:02.175012013: Notice A shell was spawned in a container with an attached terminal (user=root user_loginuid=-1 pod (id=f7549504c15a) shell=>

ログが確認できました。

Change a Falco Rule

本日のメインディッシュです。

Change the Falco output of rule “Terminal shell in container” to:

  • include NEW SHELL!!! at the very beginning
  • include user_id=%user.uid at any position
  • include repo=%container.image.repository at any position

Cause syslog output again by creating a shell in that Pod.

Verify the syslogs contain the new data.

監視したときに出力する内容を変えよ、と言っています。

ヒントとして falco の公式サイトへのリンクがありました。
変数の使い方が書いてあります。

Supported Fields for Conditions and Outputs
Events fields that you can use in conditions and outputs of Falco Rules

CKSの試験では falco の公式サイトは見てもOKらしいです。
Kubernetes 公式サイトと同様、検索の仕方などや求めている内容がどこにあるかはある程度把握しておきましょう。

では進めていきます。

やりたいのは、falco のルールを規定しているファイルを編集して、falcoを再起動して編集内容を適用させるという作業です。

falco の設定ファイルは通常 /etc/falco に存在します。

controlplane $ cd /etc/falco/      
controlplane $ ll
total 224
drwxr-xr-x   4 root root   4096 Aug  9 12:47 ./
drwxr-xr-x 144 root root  12288 Aug  9 12:47 ../
-rw-r--r--   1 root root  12314 Jun 24  2022 aws_cloudtrail_rules.yaml
-rw-r--r--   1 root root  12263 Jul 11  2022 falco.yaml
-rw-r--r--   1 root root   1136 Jul 11  2022 falco_rules.local.yaml
-rw-r--r--   1 root root 136382 Jul 11  2022 falco_rules.yaml
-rw-r--r--   1 root root  29834 Jun 24  2022 k8s_audit_rules.yaml
drwxr-xr-x   2 root root   4096 Aug  9 12:47 rules.available/
drwxr-xr-x   2 root root   4096 Jul 11  2022 rules.d/
controlplane $ 

このうち、基本的に扱うファイルは falco_rules.yaml か falco_rules.local.yaml です。
falco_rules.yaml はデフォルト設定用のファイルで、 falco_rules.local.yaml はオーバーライド用のファイルです。

デフォルトの方を編集します。

# In some cases, a shell is expected to be run in a container. For example, configuration
# management software may do this, which is expected.
- macro: user_expected_terminal_shell_in_container_conditions
  condition: (never_true)

- rule: Terminal shell in container
  desc: A shell was used as the entrypoint/exec point into a container with an attached terminal.
  condition: >
    spawned_process and container
    and shell_procs and proc.tty != 0
    and container_entrypoint
    and not user_expected_terminal_shell_in_container_conditions
  output: >
    A shell was spawned in a container with an attached terminal (user=%user.name user_loginuid=%user.loginuid %container.info
    shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline terminal=%proc.tty container_id=%container.id image=%container.image.repository)
  priority: NOTICE
  tags: [container, shell, mitre_execution]

これを

# In some cases, a shell is expected to be run in a container. For example, configuration
# management software may do this, which is expected.
- macro: user_expected_terminal_shell_in_container_conditions
  condition: (never_true)

- rule: Terminal shell in container
  desc: A shell was used as the entrypoint/exec point into a container with an attached terminal.
  condition: >
    spawned_process and container
    and shell_procs and proc.tty != 0
    and container_entrypoint
    and not user_expected_terminal_shell_in_container_conditions
  output: >
    NEW SHELL!!!
    user_id=%user.uid
    repo=%container.image.repository
    A shell was spawned in a container with an attached terminal (user=%user.name user_loginuid=%user.loginuid %container.info
    shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline terminal=%proc.tty container_id=%container.id image=%container.image.repository)
  priority: NOTICE
  tags: [container, shell, mitre_execution]

こうします。

差分をチェックします。

controlplane $ diff falco_rules.yaml falco_rules.yaml.org 
2024,2026d2023
<     NEW SHELL!!!
<     user_id=%user.uid
<     repo=%container.image.repository
controlplane $ 

あとは falco を restart して先ほどと同様コンテナに入り込めばOKです。

systemctl で restart しようとしたらできませんでした。
systemd で管理されていなかったみたいです。(SysVinitよくわからんからやめてほしい…)

controlplane $ systemctl falco restart
Unknown operation falco.

controlplane $ service falco restart

kill -1 <PID> で設定ファイルを再読み込みさせる、という方法もあるみたいです。

kill -1 $(cat /var/run/falco.pid)

残りは先ほどと同様の手順を踏めばよいので省略します。

おまけ

いつも参考にしている2大合格記を参考にすると、falco に関しては以下のことを覚えておけばよさそうです。

  • メッセージから監視に引っかかったコンテナを特定する(ログが見れればOK?)
  • 検知した際に出力されるメッセージのフォーマットを編集する(今日やったやつ)
    •  cut コマンドも使えるようにしておくと良い
【対策メモ】Certified Kubernetes Security Specialist (CKS)試験 - Qiita
はじめに本記事は、Certified Kubernetes Security Specialist (CKS)試験の対策をしている上で覚えておくべきだと感じたことをメモとして残しておくものです。…
【 更新者も必見 】 CKS 攻略ガイド ( 2023 年 6 月版 )
タイトルとURLをコピーしました