RubyKaigi から帰って、RbBCCにPRが来ていたりして、それからRubyKaigi で吸収した色々とが脳内で合わさって作りたいものが出てきた。
前段階としてRbBCCを頑張って整備し直した。
色々な細かいバグが直ったのと、pin周りを本家BCCよりちょっと使いやすくしてみた。examplesに大体あるので試してみてね。
Vivarium - Ruby特化のeBPFを使ったサンドボックス
で、 ルールルルルルRubyKaigi 2026事後勉強会 で触れた通りVivariumというものを作っている。
Vivariumは、RubyのTracePointと、RbBCC経由でのeBPFを組み合わせ、Rubyのどのメソッドでどのようなシステムイベントが動いているかを観察するフレームワークである。今のところ以下のようなイベントを取得する。
- ソケットの作成と接続
- DNSクエリの発行
- ファイルオープン、リネーム、リンク作成
- 権限変更操作
- プロセスの作成とexecve実行
- ptrace、mount、killなど重要なシステムコール操作
- など...
使ってる技術はこういう感じ:
- カーネル側は主にBPF LSMとTracePoint
- Ruby側はTracePointにフックしてカーネルのMapに溜まったイベントを吸い上げ紐付けている。
この吸い上げの機構が若干ラフなのでそのうち直すが、動くには動く。
動作のためにはBPF LSMが有効になったLinuxが必要(Ubuntu 26.04などでは、起動オプションの書き換えが必要になる)でハードルは極めて高い。
# カーネル側トレースデーモンを起動 $ bundle exec vivariumd & # 例えば監査しながらスクリプトをロードする $ bundle exec vivarium -o ./log.txt load example.rb
これで、 log.txt に起動時に行われたシステムイベントが書き出される。それを人間が読んでもいいし(フォーマットはまだ仮なのでいい感じに変えたい)、そのうち決定論的に警告を出したりできるようにしたいが、今今でも、例えばAIにそのまま投げると割と何が起こったか把握してくれる。
$ echo "./log.txt はRubyのスクリプトをロードした時の監査ログです。 攻撃が行われている可能性があるので、 どういうアクションが試行されたか分析してください。" \ | claude -p --model claude-opus-4-6 ## 監査ログ分析結果 `example.rb` が実行され、**3つの特権昇格を伴う操作が試行されました**。すべて `sudo -n`(非対話モード)経由です。 --- ### 攻撃アクション一覧 #### 1. `sudo -n id` (行10, pid=40011) ...省略... --- ### 総括 | # | コマンド | 攻撃分類 | 危険度 | |---|---------|---------|--------| | 1 | `sudo -n id` | 偵察(sudo 利用可否の確認) | 中 | | 2 | `sudo -n cat /etc/shadow` | クレデンシャル窃取 | **高** | | 3 | `sudo -n cat /proc/1/environ` | 機密情報窃取(環境変数) | **高** | スクリプトは典型的な**特権昇格 → 情報窃取**のパターンを示しています。まず `sudo id` で権限を偵察し、成功すれば `/etc/shadow` でパスワードハッシュ、`/proc/1/environ` で環境変数に格納されたシークレットを窃取する流れです。すべて `-n`(非対話モード)で実行されており、自動化された攻撃スクリプトの特徴です。
たとえば安全な環境で bundle install を実行し、ログを出し、そのプロセスで何かしらの攻撃コードが入り込んでいないかを検査する、といったユースケースを想定している。サプライチェーンアタックをCIで守るみたいなイメージ。
kntrl というツールが似たような発想っぽいけど、やっぱRubyを守りたいじゃん? なのでRuby specificな機能をバンバン入れていく。
で、TracePointを使うと本番環境で動かすには遅くなりすぎるので、サンドボックスみたいな用途をとりあえず考えている。しかし、Rubyのバイナリには豊富な uprobe のアタッチポイントがあることがわかってきた。その辺を代わりに使えば、パフォーマンスの劣化を最低限にしつつRuby側含めた挙動を観察することもできるかもしれない。この戦略では、Rubyが更新されるとキャッチアップが必要なんだけど、そこは情熱とAIでなんとか*1。
また、eBPFを使っているため、不正な挙動を検知したらシステムコールレベルで止める or 即座にkillする、ということも可能。これは現在のカーネルとeBPFでは普通にできることなのだ。
とりあえず、コンセプトはあるけどユースケースはこれから... 競合するソフトウェアも調べねば... みたいな感じで無限にやることが出てきた。というか、AIに聞いたら無限にやるべきことを教えてくれた...。
気長に作ります。
*1:USDTは、 --enable-dtrace されたRubyバイナリをほぼ見たことがないし、あまり考えてない...