Share
Embed
Transcript
22 slides
-
自己紹介 さんらいふ(X: @5un1fe3) • • 学生時代は超小型人工衛星(CubeSat)の開発とか 通信のセキュリティや低レイヤへの興味がわき 界隈をチェンジ 最近の活動 •
• 技術同人誌 Kernel/VMは見る専だったが今回初発表 -
この時間が休憩タイムなあなた 検証が終わりかけの頃、先行事例を知ってしまいました(単に勉強不足)。 Kernel/VMはまだまだ始まったばかりです。 以下のような話題に覚えのある方や詳しい方、 その他なんとなく内容に想像がつく方は10分間の休憩をどうぞ • • Cilium Tetragon Microsoft
Defender for Endpoint Linux版にeBPFベースのセンサー追加 https://github.com/cilium/tetragon https://learn.microsoft.com/ja-jp/defender-endpoint/linux-support-ebpf -
作った機能 条件は緩めで、広く検知できるよう素朴に実装 「eBPFを使ってイベントが検知できそうか」を検証 1. 2. 3. 4. 5. 6. プロセスツリーの追跡
特定パスからのプロセス実行検知 ファイルレス実行検知 権限昇格検知 ポートスキャンの検知・遮断 C2通信っぽい挙動の検知 -
1.プロセスツリーの追跡 イベント発生時にプロセスを追跡するために情報を取っておく sys_enter_execveや、sched_process_fork といったTracepointにフック Kernel sys_enter_execve sched_process_fork pid, ppid, tgid,
パス などプロセス情報取得 write Event格納 RingBuf read プロセス情報を格納 Userland Hashmap ProcInfo struct ProcessEvent{ pub event_type: EventType, pub pid: u32, pub tgid: u32, pub parent_pid: u32, pub target_pid: u32, pub uid: u32, pub comm: [u8; 16], pub filename: [u8; 256], pub filename_len: u32, pub fd: i32, pub prot: u32, pub is_deleted: u32, pub exec_time_ns: u64, pub old_uid: u32, } -
2.特定パスからのプロセス実行 Kernel sys_enter_execve sched_process_fork pid, ppid, tgid, パス などプロセス情報取得 write
プロセス系Event 格納 RingBuf read プロセス情報を格納 監視対象パスか判断 ppidを辿って プロセスツリー追跡 Userland Hashmap ProcInfo Hashmap AyashiiProcInfo -
3.ファイルレス実行検知 その1. リンク解除済ファイルの実行検知 bprm_check_security (LSM) をフック Kernel bprm_check_security dentryがリンク解除 していたら書込み
write Event 格納 RingBuf イベントが起きたこと を検知して発火 Userland -
3.ファイルレス実行検知 その2.オンディスクからの痕跡消去実行の検知 memfd_create/exit、execveat の組み合わせで検知 Kernel memfd_create memfd_exit execveat Event 格納
RingBuf fd/name Hashmap MemInfo Userland fdを検索して、 見つかれば発火 -
4.権限昇格検知 commit_creds(kprobe)をフック。 現在のプロセスのeuidが0以外で、新しいタスクのeuidが0なら発火 Kernel commit_creds 新しいプロセスのeuidが0 かどうか 現在のプロセスのeuidが0 でないかどうか Event
格納 RingBuf Userland プロセスの情報が あるか Hashmap AyashiiProcInfo -
5.ポートスキャンの検知・遮断 XDPでポートスキャンを検知・ブロック Kernel パケットの情報を XDPコンテキスト からパース 送信元IPアドレスごとに ウィンドウ内で閾値回数以 上パケットを検知 以降ウィンドウ中は
DROP Event 格納 RingBuf 発火 Userland -
6.C2通信っぽい挙動の検知 socket_connect(LSM)のフックと、組み合わせで検知 configに書いたIPアドレス宛の通信で、監視対象パスからの実行であれば発火 Kernel IPアドレス/ポート、pidなど を取得 socket_connect Event 格納 RingBuf
指定のIPアドレスか判断 プロセスの情報があるか Userland Hashmap AyashiiProcInfo -
情報取得のため構造体をたどるイベント ファイルレス実行検知でbprm_check_secyurityをフック後、unlink確認まで struct linux_binprm { ~~ struct file *interpreter; struct
file *file; struct cred *cred; ~~ }; struct file { ~~ union { const struct path f_path; struct path __f_path; }; union { struct mutex f_pos_lock; u64 f_pipe; ~~ } struct path { struct vfsmount *mnt; struct dentry *dentry; }; カーネルの構造体はオフセットが結構変わる -
だが現実は厳しい 1. rustcにリロケーション情報を与える機能がない疑惑 https://github.com/aya-rs/aya/issues/349 2. verifierによるポインタアクセスの制約 実行時に読んだ値(BPFマップの値など)とのポインタ演算を拒否 ・LSMフックの ctx.arg(n) は「trusted
pointer」 ・LSMフックの場合は、BPFマップ経由で値を渡してオフセットを反映させることも難 しい -
それでも ...! 1. ユーザー空間側が、デーモン起動の都度、 bpftool btf dump file /sys/kernel/btf/vmlinux -j
をサブプロセスとして実行 2. 得られたJSONをパースし、union/structを再帰的に辿って必要なフィールドオフ セットを解決。オフセットを構造体にまとめる。 3. まとめたオフセットはグローバル変数として、 ロード前にオフセット値を書き換え (最初では0で初期化) -
もう一度検知を見せてくれ 1. 簡単に、HelloworldのELFを/tmpに置いて実行(/tmp/a.out) →検知ログが出てこない 2. execveを検知するのみの頃のプログラムにロールバックしてリトライ →検知ログが出てこない 3. /tmp/a.outを100回実行する →
9回検知 → 9/100 = 0.09 $ lscpu ~ CPU: →1/12 ~ 0.083… 12 -
CPU 0しか検知してないぞこれ ... $ taskset -c 0 /tmp/a.out → 100件中100件検知
どうしようと思ったがここで時間切れ