
eBPF駆動のセキュリティツールであり、Linuxマシンのロックと監査を行います。カーネル機能を制限し、ファイルレス実行をブロックし、メモリを保護し、宣言型プロファイルを介してコンテナとIoTデバイスを強化します。

bpflock - eBPF 駆動のセキュリティで Linux マシンのロックと監査を行います。
注: bpflock は現在 実験段階 にあり、動作が壊れたり、オプションやセキュリティセマンティクスが変更される可能性があります。一部の BPF プログラムは Cilium ebpf ライブラリ を使用するように更新される予定です。
bpflock は eBPF を利用して Linux のセキュリティを強化します。さまざまな Linux 機能へのアクセスを制限することで、bpflock は攻撃対象領域を減らし、よく知られた攻撃手法の一部をブロックすることができます。
ホストの pid およびネットワーク名前空間 で動作するコンテナマネージャ、systemd、その他のコンテナ/プログラムのみが、完全な Linux 機能へのアクセスを許可されます。自身の名前空間で動作するコンテナやアプリケーションは制限されます。
bpflock の bpf プログラムが restricted プロファイルで実行されている場合、特権を持つものを含むすべてのプログラム/コンテナのアクセスが拒否されます。
bpflock は、Linux Security Modules + BPF を含む複数のセキュリティ機能を活用して Linux マシンを保護します。
アーキテクチャとセキュリティ設計のメモ:
bpflock は以下のように分類できる複数のセキュリティ保護を提供します:
ファイルシステム保護
ネットワーク保護
bpflock はセキュリティセマンティクスをシンプルに保ちます。セキュリティのスペクトルを広くカバーし、特定の Linux 機能へのアクセスを制限するために、3 つの グローバル プロファイルをサポートしています。
profile: これは bpf プログラムごとに適用できるグローバルプロファイルで、以下のいずれかを取ります:
allow|none|privileged : これらは同じで、最もセキュリティの低いプロファイルを定義します。このプロファイルでは、すべてのプロセスに対してアクセスがログに記録され許可されます。セキュリティイベントを記録するのに便利です。baseline : 制限的なプロファイルで、ホスト名前空間で実行される特権アプリケーションやコンテナ、または bpflock_cgroupmap bpf マップ内の cgroup ごとに許可されたプロファイルを除き、すべてのプロセスのアクセスが拒否されます。restricted : 非常に制限の厳しいプロファイルで、すべてのプロセスのアクセスが拒否されます。許可 または ブロック された操作/コマンド:
allow|privileged または baseline プロファイルの下で、許可またはブロックされたコマンドのリストを指定して適用できます。
--protection-allow : 許可された操作のカンマ区切りリスト。baseline プロファイルで有効で、非常に特殊で特権操作を実行するアプリケーションに役立ちます。allow | privileged プロファイルの使用を減らすため、 プロファイルを使用する代わりに プロファイルを指定し、そのようなアプリケーションに対してケースバイケースの定義を追加できます。bpf セキュリティの例については bpflock 設定例 を確認してください。
bpflock には以下が必要です:
以下の設定が有効な Linux カーネルバージョン >= 5.13:
CONFIG_BPF_SYSCALL=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_BTF=y
CONFIG_KPROBES=y
CONFIG_LSM="...,bpf"
CONFIG_BPF_LSM=y
もちろん BTF 対応カーネル。
カーネルが CONFIG_BPF_LSM=y でコンパイルされている場合、/boot/config-* を確認してください。しかし、bpflock を実行すると次のエラーで失敗する場合:
must have a kernel with 'CONFIG_BPF_LSM=y' 'CONFIG_LSM=\"...,bpf\"'"
Ubuntu で BPF LSM を有効にする例:
GRUB_CMDLINE_LINUX 変数に以下を追加して保存します。
"lsm=lockdown,capability,yama,apparmor,bpf"
GRUB_CMDLINE_LINUX="lsm=lockdown,capability,yama,apparmor,bpf"
sudo update-grub2
デフォルトの allow または privileged プロファイル (最もセキュリティの低いプロファイル) で実行する場合:
docker run --name bpflock -it --rm --cgroupns=host \
--pid=host --privileged \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
ファイルレスバイナリ実行 をログに記録し制限するには、以下で実行:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-e "BPFLOCK_FILELESSLOCK_PROFILE=restricted" \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
restricted プロファイルで実行すると、コンテナログに次のように表示されます:
time="2022-02-04T14:54:33Z" level=info msg="event=syscall_execve tgid=1833 pid=1833 ppid=1671 uid=1000 cgroupid=8821 comm=loader pcomm=bash filename=./loader retval=0" bpfprog=execsnoop subsys=bpf
time="2022-02-04T14:54:33Z" level=info msg="event=lsm_bprm_creds_from_file tgid=1833 pid=1833 ppid=1671 uid=1000 cgroupid=8821 comm=loader pcomm=bash filename=memfd:memfd-test retval=-1 reason=denied (restricted)" bpfprog=filelesslock subsys=bpf
time="2022-02-04T14:54:33Z" level=info msg="event=syscall_execve tgid=1833 pid=1833 ppid=0 uid=1000 cgroupid=8821 comm= pcomm= filename=/proc/self/fd/3 retval=-1" bpfprog=execsnoop subsys=bpf
restricted プロファイルで実行すると問題が発生する可能性があるため、デフォルトプロファイルは allow です。
カーネルモジュール保護 を適用するには、
環境変数 BPFLOCK_KMODLOCK_PROFILE=baseline または BPFLOCK_KMODLOCK_PROFILE=restricted で実行:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-e "BPFLOCK_KMODLOCK_PROFILE=restricted" \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
例:
$ sudo unshare -p -n -f
# modprobe xfs
modprobe: ERROR: could not insert 'xfs': Operation not permitted
time="2022-02-07T06:50:25+01:00" level=info msg="event=syscall_execve tgid=52323 pid=52323 ppid=52288 uid=0 cgroupid=7014 comm=modprobe pcomm=bash filename=/usr/sbin/modprobe retval=0" bpfprog=execsnoop subsys=bpf
time="2022-02-07T06:50:25+01:00" level=info msg="event=lsm_kernel_read_file operation=loading module tgid=52323 pid=52323 ppid=52288 uid=0 cgroupid=7014 comm=modprobe pcomm=bash filename=xfs.ko retval=-1 reason=denied (restricted)" bpfprog=kmodlock subsys=bpf
カーネルイメージロックダウン を適用するには、環境変数 BPFLOCK_KIMGLOCK_PROFILE=baseline で実行:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-e "BPFLOCK_KIMGLOCK_PROFILE=baseline" \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
$ sudo unshare -f -p -n bash
# head -c 1 /dev/mem
head: cannot open '/dev/mem' for reading: Operation not permitted
time="2022-02-07T06:57:22+01:00" level=info msg="event=syscall_execve tgid=52428 pid=52428 ppid=52288 uid=0 cgroupid=7014 comm=head pcomm=bash filename=/usr/bin/head retval=0" bpfprog=execsnoop subsys=bpf
time="2022-02-07T06:57:22+01:00" level=info msg="event=lsm_locked_down operation=/dev/mem,kmem,port tgid=52428 pid=52428 ppid=52288 uid=0 cgroupid=7014 comm=head pcomm=bash retval=-1 reason=denied (baseline)" bpfprog=kimglock subsys=bpf
bpf 制限 を適用するには、環境変数 BPFLOCK_BPFRESTRICT_PROFILE=baseline または BPFLOCK_BPFRESTRICT_PROFILE=restricted で実行:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-e "BPFLOCK_BPFRESTRICT_PROFILE=baseline" \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
異なる pid およびネットワーク名前空間で bpftool を使用した例:
$ sudo unshare -f -p -n bash
# bpftool prog
Error: can't get next program: Operation not permitted
time="2022-02-04T15:40:56Z" level=info msg="event=lsm_bpf tgid=2378 pid=2378 ppid=2364 uid=0 cgroupid=9458 comm=bpftool pcomm=bash filename= retval=-1 reason=baseline" bpfprog=bpfrestrict subsys=bpf
time="2022-02-04T15:40:56Z" level=info msg="event=lsm_bpf tgid=2378 pid=2378 ppid=2364 uid=0 cgroupid=9458 comm=bpftool pcomm=bash filename= retval=-1 reason=baseline" bpfprog=bpfrestrict subsys=bpf
-e "BPFLOCK_BPFRESTRICT_PROFILE=restricted" プロファイルで実行すると、すべての bpf が拒否されます:
time="2022-02-04T15:44:13Z" level=info msg="event=syscall_execve tgid=2500 pid=2500 ppid=2499 uid=0 cgroupid=9458 comm=bpftool pcomm=sudo filename=./tools/amd64/bpftool retval=0" bpfprog=execsnoop subsys=bpf
time="2022-02-04T15:44:13Z" level=info msg="event=lsm_bpf tgid=2500 pid=2500 ppid=2499 uid=0 cgroupid=9458 comm=bpftool pcomm=sudo filename= retval=-1 reason=denied (restricted)" bpfprog=bpfrestrict subsys=bpf
time="2022-02-04T15:44:13Z" level=info msg="event=lsm_bpf tgid=2500 pid=2500 ppid=2499 uid=0 cgroupid=9458 comm=bpftool pcomm=sudo filename= retval=-1 reason=denied (restricted)" bpfprog=bpfrestrict subsys=bpf
バインドマウントとして設定を渡すには、以下のコマンドを使用します。
bpflock.yaml と bpf.d プロファイル 設定がカレントディレクトリ内の bpflock ディレクトリにある場合、次のように使用できます:
ls bpflock/
bpf.d bpflock.d bpflock.yaml
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-v $(pwd)/bpflock/:/etc/bpflock \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
環境変数の受け渡しは --env-file を使用してファイルで行うこともできます。すべてのパラメータは BPFLOCK_$VARIABLE_NAME=VALUE 形式で環境変数として渡せます。
環境変数をファイルで渡す実行例:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
--env-file bpflock.env.list \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
ドキュメントファイルは こちら にあります。
bpflock はビルドに docker BuildKit を使用し、 いくつかのチェックとテスト実行に Golang を使用します。bpflock は標準の golang パッケージをダウンロードする Ubuntu コンテナ内でビルドされます。
以下を実行して bpflock docker コンテナをビルド:
git submodule update --init --recursive
make
Bpf プログラムは libbpf を使用してビルドされます。使用される Docker イメージは Ubuntu です。
docker を使わずに bpf プログラムのみを直接ビルドしたい場合、Ubuntu では:
sudo apt install -y pkg-config bison binutils-dev build-essential \
flex libc6-dev clang-12 libllvm12 llvm-12-dev libclang-12-dev \
zlib1g-dev libelf-dev libfl-dev gcc-multilib zlib1g-dev \
libcap-dev libiberty-dev libbfd-dev
次に実行:
make bpf-programs
この場合、生成されたプログラムは ./bpf/build/... ディレクトリ内に配置されます。
bpflock は Cilium および bcc プロジェクトのソースコードを含む、多くのリソースを使用しています。
bpflock のユーザースペースコンポーネントは Apache License, Version 2.0 の下でライセンスされています。BPF コードは、記載がある場合、General Public License, Version 2.0 の下でライセンスされています。
privilegedbaseline--protection-block : ブロックされた操作のカンマ区切りリスト。allow|privileged および baseline プロファイルで有効で、完全な restricted プロファイルを使用せずに一部の機能へのアクセスを制限できます。baseline または privileged プロファイルを使用すると、ほとんどの Linux 機能へのアクセスが許可されますが、--protection-block オプションを使用してそのうちの一部をブロックできます。