Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
コードで理解する eBPF セキュリティモニタリング
Search
mrtc0
February 17, 2024
Technology
320
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
コードで理解する eBPF セキュリティモニタリング
*
https://engineercafe.connpass.com/event/309223/
*
https://github.com/mrtc0/ebpf-demo/
mrtc0
February 17, 2024
More Decks by mrtc0
See All by mrtc0
Datadog を使ったプロダクトとクラウドの セキュリティモニタリング
mrtc0
0
3.5k
Product Security Casual Talk #1 - Datadog を使ったセキュリティモニタリングと 自動化の取り組み
mrtc0
2
730
GMO ペパボ株式会社 23卒・24卒向け セキュリティ勉強会 実践 DevSecOps パイプライン
mrtc0
1
760
実践 DevSecOps パイプライン ~システム開発へのセキュリティの取り入れ方~
mrtc0
2
630
脅威モデリングで考える Kubernetes セキュリティ / CloudNative Days Tokyo 2021 #CNDT2021 #CNDT2021_B
mrtc0
8
3.5k
ProSec-IT 2021 Container Security
mrtc0
2
840
GMO Developer Day 2021 - DevSecOps 推進の取り組みの紹介.pdf
mrtc0
4
1.9k
Web セキュリティ研修 / GMO ペパボ 新卒研修 2021
mrtc0
7
47k
実践コンテナ & Kubernetes セキュリティ
mrtc0
12
4.1k
Other Decks in Technology
See All in Technology
AIは実装を速くする。では、私たちは何を今作るべきか?-立場を越えてリリースに向き合ったチーム開発の実践 / 20260801 Hiromi Nakaya and Naoki Takahashi
shift_evolve
PRO
3
380
取引先から届く 「セキュリティチェックシート」の読み解き方
kamadamakoto
0
110
toio・myCobotでフィジカルAIっぽいことを行うための検討(とりあえず調査) / フィジカルAI LT(IoTLTによる開催)
you
PRO
0
280
PLaMo 3.0 Primeの構造化出力サポート
pfn
PRO
0
180
Issue設計から始める仕様駆動開発 / 20260731 Mizuki Hirata
shift_evolve
PRO
1
130
オートロックマンションなのに、各部屋は施錠なし!? 攻撃者が組織内ネットワークで大暴れする理由 / The Front Door Is Locked, but the Rooms Are Wide Open: Why Attackers Move Freely Inside Enterprise Networks
nttcom
0
1.5k
事業価値と Engineering 2026年度版
recruitengineers
PRO
32
16k
データ組織の転換期 一足飛びしない段階的戦略
leveragestech
PRO
0
150
修正PRを食べてレビュースキルが賢くなる:Claude Codeによる自己改善サイクル
yuyaumetsu
4
1.2k
JavaScript 研修 (2026)
recruitengineers
PRO
0
290
Eight Engineering Unit 紹介資料
sansan33
PRO
3
8.1k
Data Hubグループ 紹介資料
sansan33
PRO
0
3.1k
Featured
See All Featured
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
650
Balancing Empowerment & Direction
lara
6
1.2k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
890
A Modern Web Designer's Workflow
chriscoyier
698
190k
How to Talk to Developers About Accessibility
jct
2
480
Mind Mapping
helmedeiros
PRO
1
300
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.1k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
350
The Cult of Friendly URLs
andyhume
79
7k
Utilizing Notion as your number one productivity tool
mfonobong
4
500
Navigating Team Friction
lara
192
16k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
610
Transcript
コードで理解する eBPF セキュリティモニタリング 2023/02/15 eBPF & コンテナ情報交換会 @ 福岡
森田 浩平 / Kohei Morita 2018年にGMOペパボ株式会社に新卒入社, 2022年より株式会社グラファーにてプロダクトセキュリティに従事。 OWASP Fukuoka Chapter
Leader,セキュリティ・キャンプ講師, 著書に「基礎から学ぶコンテナセキュリティ」など。 出身は愛媛県松山市、現在は福岡で妻+猫1匹と生活中
https://gihyo.jp/book/2023/978-4-297-13635-2
モニタリング用途で使用される。現在はこちらが多めな印象。 より強固にしたい場面で。ただし、実装としては少ない印象。
何を監視するのか • 次のようなイベントをトレースし、普段と異なる挙動を検出できる。プロセスのコンテキスト情報を手 軽に深く安全に取得できるのが eBPF の特徴 • システムコールの呼び出し • ネットワークトラフィック
• ファイルアクセス
コードで理解する eBPF セキュリティモニタリング 題材として “curl のときに example.com への通信をブロックする” 小さいプログラムを作る 。
1. 通信を発生させる関数に attach してプロセスコンテキストを取得・表示する 2. eBPF Map に設定を書き込んでユーザーランドで表示結果をフィルタする 3. curl のとき example.com への接続の場合に通信をブロックする コードは https://github.com/mrtc0/ebpf-demo にあります。
アタッチする関数の決定 $ dig +short example.com 93.184.216.34 $ sudo strace curl
https://example.com |& grep 93.184 connect(5, {sa_family=AF_INET, sin_port=htons(443), sin_addr=inet_addr("93.184.216.34")}, 16) = -1 EINPROGRESS (Operation now in progress) getpeername(5, {sa_family=AF_INET, sin_port=htons(443), sin_addr=inet_addr("93.184.216.34")}, [128 => 16]) = 0
connect システムコールを確認する
#include "vmlinux.h" #include <asm/unistd.h> #include <bpf/bpf_core_read.h> #include <bpf/bpf_helpers.h> #include <bpf/bpf_tracing.h>
#define AF_INET 2 #define TASK_COMM_LEN 16 char LICENSE[] SEC("license") = "Dual BSD/GPL"; SEC("kprobe/security_socket_connect") int handle_security_socket_connect(struct pt_regs *ctx) { struct event evt; /* int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen); PT_REGS_PARM2 は第二引数の address を取得するマクロ */ struct sockaddr *address = (struct sockaddr *)PT_REGS_PARM2(ctx); sa_family_t fam; bpf_core_read(&fam, sizeof(fam), &address->sa_family); if (fam != AF_INET) { return 0; } } https://github.com/mrtc0/ebpf-demo/blob/master/bpf/trace_connect.c
#define EVENTS_RING_SIZE (4*4096) struct event { struct in_addr dst; u8
comm[TASK_COMM_LEN]; }; // events をユーザーランドと共有するための Map struct { __uint(type, BPF_MAP_TYPE_RINGBUF); __uint(max_entries, EVENTS_RING_SIZE); } events SEC(".maps"); https://github.com/mrtc0/ebpf-demo/blob/master/bpf/trace_connect.c
SEC("kprobe/security_socket_connect") int handle_security_socket_connect(struct pt_regs *ctx) { struct event evt; struct
sockaddr *address = (struct sockaddr *)PT_REGS_PARM2(ctx); sa_family_t fam; __builtin_memset(&evt, 0, sizeof(evt)); bpf_core_read(&fam, sizeof(fam), &address->sa_family); if (fam != AF_INET) { return 0; } // events Map に書き込む struct sockaddr_in *addr = (struct sockaddr_in *)address; bpf_get_current_comm(&evt.comm, sizeof(evt.comm)); evt.dst = BPF_CORE_READ(addr, sin_addr); bpf_ringbuf_output(&events, &evt, sizeof(evt), 0); return 0; } https://github.com/mrtc0/ebpf-demo/blob/master/bpf/trace_connect.c
実行結果 $ sudo ./bbarrier tracer 2024/02/15 11:28:31 waiting for events...
2024/02/15 11:28:37 event: comm=curl addr=889192575 # 127.0.0.53 2024/02/15 11:28:37 event: comm=curl addr=584628317 # 93.184.216.34 2024/02/15 11:28:37 event: comm=curl addr=584628317 # 93.184.216.34 $ curl https://example.com/ $ dig +short example.com 93.184.216.34
IP アドレスが 93.184.216.34 のときだけ検知したい • ユーザーランドでフィルタしても良いが今回は eBPF プログラム内で行ってみる
BPF_MAP_TYPE_LPM_TRIE
struct { __uint(type, BPF_MAP_TYPE_LPM_TRIE); __uint(max_entries, 256); __type(key, struct ipv4_lpm_key); __type(value,
__u32); __uint(map_flags, BPF_F_NO_PREALLOC); } denied_ipaddr_map SEC(".maps"); int handle_security_socket_connect(struct pt_regs *ctx) { ... struct ipv4_lpm_key key = { .prefixlen = 32, .data = evt.dst.s_addr }; if (bpf_map_lookup_elem(&denied_ipaddr_map, &key)) { bpf_ringbuf_output(&events, &evt, sizeof(evt), 0); } ... } err = objs.DeniedIPAddrMap.Put(&socketConnectIpv4LpmKey{ Prefixlen: 32, Data: network.IPToInt(exampleComIPAddr), }, uint32(0)) https://github.com/mrtc0/ebpf-demo/blob/master/bpf/trace_connect.c https://github.com/mrtc0/ebpf-demo/blob/master/pkg/tracer/socket_connect.go
実行結果 $ r$ sudo ./bbarrier tracer 2024/02/15 13:57:58 waiting for
events... 2024/02/15 13:58:02 event: comm=curl addr=[93 184 216 34] 2024/02/15 13:58:02 event: comm=curl addr=[93 184 216 34] $ curl https://example.com/ $ curl https://github.com/
Fault Injection (Error Injection) A. bpf_override_return() と bpf_send_signal() を使う ◦
e.g. Tetragon B. LSM BPF を使う ◦ e.g. Teleport
bpf_override_return() と bpf_send_signal() • 関数の戻り値を変更し、プロセスにシグナルを送る ◦ 戻り値を変更できるのは一部の関数のみ • 悪意あるプロセスがシグナルをハンドリングしている場合、シグナルを送っても無効化されるので、 bpf_override_return()
と組み合わせるべし BPF LSM を使う • 素朴に BPF プログラム内で return -EPERM とかすれば良い • Ubuntu 22.04 LTS では、起動時のパタメータを変更する必要があって、シュッとは使えない
bpf_override_return() が使える条件 • Tracepoint では使えないので Kprobe を使う • また、Kprobe の中でも許可されている関数しか使えない
◦ cat /proc/kallsyms | grep _eil_addr ◦ 対象のほとんどがシステムコール • 今は x86 でしか使えないはず (man 7 bpf-helpers 調べ) ◦ ( ちなみに LSM BPF も ARM64 は still in development だったと思う...
アタッチする場所を変更じゃ mrtc0@sandbox:~$ cat /proc/kallsyms | grep _eil_addr | grep security_socket_connect
mrtc0@sandbox:~$ cat /proc/kallsyms | grep _eil_addr | grep connect 0000000000000000 d _eil_addr___ia32_sys_connect 0000000000000000 d _eil_addr___x64_sys_connect security_socket_connect では使えない...
SEC("kprobe/sys_connect") int kprobe__sys_connect(struct pt_regs *ctx) { ... struct denied_command comm;
bpf_get_current_comm(&comm.comm, sizeof(evt.comm)); if (bpf_map_lookup_elem(&denied_ipaddr_map, &key) && bpf_map_lookup_elem(&denied_command_map, &comm)) { bpf_ringbuf_output(&events, &evt, sizeof(evt), 0); bpf_send_signal(9); bpf_override_return(ctx, -1); } return 0; } https://github.com/mrtc0/ebpf-demo/blob/master/bpf/enforce_connect.c
実行結果 $ r$ sudo ./bbarrier enforce 2024/02/15 13:57:58 waiting for
events... 2024/02/15 13:58:02 event: comm=curl addr=[93 184 216 34] mrtc0@sandbox:~$ curl -sI https://example.com Killed mrtc0@sandbox:~$ curl -sI https://github.com HTTP/2 200 server: GitHub.com mrtc0@sandbox:~$ wget https://example.com --2024-02-17 06:00:06-- https://example.com/ Resolving example.com (example.com)... 93.184.216.34, 2606:2800:220:1:248:1893:25c8:1946 Connecting to example.com (example.com)|93.184.216.34|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 1256 (1.2K) [text/html] Saving to: ʻindex.htmlʼ
eBPF でセキュリティモニタリングがどう変わる? • 従来までプロセスのコンテキストを深く追うことは Kernel Module を作るしかなかった ◦ それが非常に簡単に、かつ、安全に実現できるようになった •
従来の技術でも工夫次第で十分にモニタリングはできるが、コンテナ環境では限界がある ◦ すでに多くの企業が eBPF を使ったモニタリングを実装・運用している • 主要なディストリビューションで「カーネルのバージョンが新しい」「デフォルトで eBPF に関する Kernel Config が有効になっている」状態になると、もっと広がる • プロセスのコンテキスト情報を蓄積・分析する基盤があれば、「本当に疑わしい挙動」のみにフォーカ スできるようになる (誤検知が減る) ◦ フォレンジックの分野でも状況証拠が多く手に入る