GKEでFalcoを使ってみる
Falcoの概要
FalcoはSysdigにて作成されたオープンソースのセキュリティツール。
CNCFに寄贈され、インキュベーションプロジェクトとなっている。
ざっくり言うと、コンテナの侵入検知を行える。事前にNGとなるルールを定義し、意図しない振る舞いをしていないかを検知出来る。
脆弱性を突かれてコンテナ内に侵入された際も、何を実行されたのか等を後追いできるためフォレンジックに役立つ。
仕組みとしては、FalcoではカーネルからのLinuxシステムコールを解析し、事前定義したルールに基づきエンジンがチェックする。
※ https://falco.org/ja/docs/getting-started/ より引用
以下にも書かれているが、デフォルトのルールとしては以下がある。
デフォルトでは、Falco には成熟したルールのセットが同梱されています。
- 特権コンテナを使用した特権のエスカレーション
- setns のようなツールを使ったネームスペースの変更
- /etc, /usr/bin, /usr/sbin などのよく知られたディレクトリへの読み込み/書き込み
- シンボリックリンクの作成
- 所有権とモードの変更
- 予期しないネットワーク接続またはソケットの変異
- execve を使ってプロセスをSpawnした
- sh, bash, csh, zsh などのシェルバイナリの実行
- SSH バイナリ ssh, scp, sftp などを実行する
- Linux の coreutils 実行ファイルを変異させる
- ログインバイナリの変異
- shadowutil や passwd の実行ファイルを変異させる
- shadowconfig
- pwck
- chpasswd
- getpasswd
- change
- useradd
などなど
ノイズなどが多い場合や、検知したい項目がある場合は以下のyamlを修正することでルールの変更が出来る。
デフォルトで非常に多くの項目(3000行以上)があるので、先ずはデフォルトのルールに従って運用していって、設定ファイルを育てていくのが良さそう。
環境作成
GKEクラスタの作成
今回は GKE version 1.20.12-gke.1500 を使用した。
またDataplane v2も有効化している。
helmリポジトリの登録
Falcoを実行する最も安全な方法はホスト(GKEのノード側)に直接インストールすることとされている。
理由としてはFalco自身がKubernetesから分離されているため。
GKEの場合はノードのイメージはCOS(Container-OptimizedOS)を使うのが一般的なため、独自のイメージを作るのは避けたい。
そもそも、COSはセキュリティが強化されており、システムコールをFalcoが処理するためのカーネルモジュールを挿入できない。
しかし、COSの場合はeBPFを使用してシステムコールのストリームをFalcoに提供する機能があるため、実現できる。
helmにて導入を行う。
~ helm repo add falcosecurity https://falcosecurity.github.io/charts
~ helm repo update
~ helm repo list | grep falco
falcosecurity https://falcosecurity.github.io/charts
Falcoのインストール
~ helm install falco falcosecurity/falco --set ebpf.enabled=true
NAME: falco
LAST DEPLOYED: Fri Dec 17 11:19:02 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Falco agents are spinning up on each node in your cluster. After a few
seconds, they are going to start monitoring your containers looking for
security issues.
No further action should be required.
Tip:
You can easily forward Falco events to Slack, Kafka, AWS Lambda and more with falcosidekick.
Full list of outputs: https://github.com/falcosecurity/charts/falcosidekick.
You can enable its deployment with `--set falcosidekick.enabled=true` or in your values.yaml.
See: https://github.com/falcosecurity/charts/blob/master/falcosidekick/values.yaml for configuration values.
podが起動している。
~ kubectl get pod
NAME READY STATUS RESTARTS AGE
falco-cpmbq 1/1 Running 0 11m
falco-j6nmt 1/1 Running 0 11m
kubectl get configmap
NAME DATA AGE
falco 5 29m
どのようなログが出るか見てみる
podの起動
nginxを起動して、その中で試してみる。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2 #
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21.4
ports:
- containerPort: 80
~ kubectl apply -f deploy_nginx.yml
deployment.apps/nginx-deployment created
Falcoのログは標準出力に出ているため、 sternを使用して見ていく
stern falco
sshで接続
nginxコンテナにsshで接続する
~ kubectl exec -it nginx-deployment-6b689c98c5-nbz7r -- sh
以下のルールにひっかかる。
- 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]
Falcoには以下のログが記録されている
falco-cpmbq falco 09:25:27.022956239: Notice A shell was spawned in a container with an attached terminal (user=root user_loginuid=-1 k8s.ns=default k8s.pod=nginx-deployment-6b689c98c5-2vmhk container=d003af23ea19 shell=sh parent=runc cmdline=sh terminal=34816 container_id=d003af23ea19 image=docker.io/library/nginx) k8s.ns=default k8s.pod=nginx-deployment-6b689c98c5-2vmhk container=d003af23ea19
ファイルの追加
nginxのコンテナ内にファイルを追加してみる。
touch /etc/sakon.conf
以下のルールにひっかかる。
- rule: Write below etc
desc: an attempt to write to any file below /etc
condition: write_etc_common
output: "File below /etc opened for writing (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline parent=%proc.pname pcmdline=%proc.pcmdline file=%fd.name program=%proc.name gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] container_id=%container.id image=%container.image.repository)"
priority: ERROR
tags: [filesystem, mitre_persistence]
Falcoには以下のログが記録されている
falco-cpmbq falco 09:30:22.522301023: Error File below /etc opened for writing (user=root user_loginuid=-1 command=touch /etc/sakon.conf parent=sh pcmdline=sh file=/etc/sakon.conf program=touch gparent=<NA> ggparent=<NA> gggparent=<NA> container_id=d003af23ea19 image=docker.io/library/nginx) k8s.ns=default k8s.pod=nginx-deployment-6b689c98c5-2vmhk container=d003af23ea19 k8s.ns=default k8s.pod=nginx-deployment-6b689c98c5-2vmhk container=d003af23ea19
パッケージのインストール
# apt update
Get:1 http://security.debian.org/debian-security bullseye-security InRelease [44.1 kB]
Get:2 http://deb.debian.org/debian bullseye InRelease [116 kB]
Get:3 http://deb.debian.org/debian bullseye-updates InRelease [39.4 kB]
Get:4 http://security.debian.org/debian-security bullseye-security/main amd64 Packages [99.5 kB]
Get:5 http://deb.debian.org/debian bullseye/main amd64 Packages [8180 kB]
Get:6 http://deb.debian.org/debian bullseye-updates/main amd64 Packages [2592 B]
Fetched 8481 kB in 2s (4443 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
All packages are up to date.
Falcoには以下のログが記録されている
falco-cpmbq falco 04:21:47.738779670: Error Package management process launched in container (user=root user_loginuid=-1 command=apt update container_id=a041c1608bbd container_name=nginx image=docker.io/library/nginx:1.21.4) k8s.ns=default k8s.pod=nginx-deployment-6b689c98c5-nbz7r container=a041c1608bbd k8s.ns=default k8s.pod=nginx-deployment-6b689c98c5-nbz7r container=a041c1608bbd
vimのインストール
# apt install vim
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
libgpm2 vim-common vim-runtime xxd
Suggested packages:
gpm ctags vim-doc vim-scripts
The following NEW packages will be installed:
libgpm2 vim vim-common vim-runtime xxd
0 upgraded, 5 newly installed, 0 to remove and 0 not upgraded.
Need to get 8173 kB of archives.
After this operation, 36.9 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
Falcoには以下のログが記録されている
falco-cpmbq falco 04:22:54.512922215: Error Package management process launched in container (user=root user_loginuid=-1 command=apt install vim container_id=a041c1608bbd container_name=nginx image=docker.io/library/nginx:1.21.4) k8s.ns=default k8s.pod=nginx-deployment-6b689c98c5-nbz7r container=a041c1608bbd k8s.ns=default k8s.pod=nginx-deployment-6b689c98c5-nbz7r container=a041c1608bbd
以下のルールにひっかかる。
- rule: Launch Package Management Process in Container
desc: Package management process ran inside container
condition: >
spawned_process
and container
and user.name != "_apt"
and package_mgmt_procs
and not package_mgmt_ancestor_procs
and not user_known_package_manager_in_container
output: >
Package management process launched in container (user=%user.name user_loginuid=%user.loginuid
command=%proc.cmdline container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
priority: ERROR
tags: [process, mitre_persistence]
falcosidekickを使ってみる
Falcoには falcosidekick
という様々なエコシステムに接続するためのdaemon機能が追加出来る。
UIに接続できたり、SlackやTeams、Google Chatなどに通知を送ったり、DatadogやPrometheusにメトリクスを送ったりすることが可能となる。
KafkaやGCPのPub/SubやAWS SQS,SNSなどにもStreamingを送ることが可能。
※ https://falco.org/blog/extend-falco-outputs-with-falcosidekick/ より引用
falcosidekickを有効にする
helm upgrade falco falcosecurity/falco \
--set falcosidekick.enabled=true \
--set falcosidekick.webui.enabled=true \
--set falcosidekick.config.slack.webhookurl="https://hooks.slack.com/services/XXXXXXXX" \
--set ebpf.enabled=true
podが上がってきている。また、serviceも作られている
~ kubectl get pod
NAME READY STATUS RESTARTS AGE
falco-2dn9w 1/1 Running 0 7m3s
falco-falcosidekick-c6fcc8d5c-24hc9 1/1 Running 0 9m47s
falco-falcosidekick-c6fcc8d5c-q9wds 1/1 Running 0 9m47s
falco-falcosidekick-ui-7cb9856769-z4qxp 1/1 Running 0 9m47s
falco-k7dfq 1/1 Running 0 7m41s
nginx-deployment-6b689c98c5-2vmhk 1/1 Running 1 19h
nginx-deployment-6b689c98c5-62gdl 1/1 Running 0 19h
~ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
falco-falcosidekick ClusterIP 10.108.6.189 <none> 2801/TCP 10m
falco-falcosidekick-ui ClusterIP 10.108.12.65 <none> 2802/TCP 10m
kubernetes ClusterIP 10.108.0.1 <none> 443/TCP 2d4h
slack通知を確認する
先程同様touchでファイルを作ってみる
touch /etc/sakon2.conf
以下のように通知が送られる
UIに接続する
kubectl port-forward svc/falco-falcosidekick 2801
http://localhost:2802/ui/#/
でブラウザからアクセス可能