脆弱性を探しに行って見つけた話
はじめに
no starch pressからFrom Day Zero to Zero Day[1]という本が出たので読んでいました。
第3章まで読んだので一旦実践してみようと思い自分で未知の脆弱性を探していたところ、運良く一個見つけたのでそこに至るまでの過程を書いていきたいと思います。
ターゲットを探す
本には
- Familiarity
- Availability
- Impact
を意識してターゲットを探すとよいというようなことが書いてあったので、まず自分の得意なRust
で作られているOSSから脆弱性を探すことにしました。
既知の脆弱性を探す
3章 Variant analysis
に既知の脆弱性から直し忘れを探すと良いということが書いてあったのでRUSTSECとかGitHub Advisory Databaseを見ることにしました。
脆弱性を探す目的でOSSを探すことは今までなかったのですが、少なくともそこからなにかインスピレーションを得られないかと思いながら見ていました。
そこでピンときたのが、bytecodealliance/wasmtimeのWasmtime doesn't fully sandbox all the Windows device filenamesでした。
この脆弱性の詳しい内容は割とどうでもいいのですが、Webassembly(WASI)のファイルシステムのサンドボックスという部分に何か直感を感じました。
かなりわかりやすくSource-Sink analysisでいうSinkです。
自分で実装することを想像したらちょっと嫌だし、絶対他に何かバグがあるだろうと思いました。
本に載ってたような、CodeQLとかSemgrepなどの静的解析を使ったVariant analysis
は出来なさそうですがとりあえずコードを見てみることにしました。
コードレビュー
Wasmtime
のWASI
の実装は
といくつかありますが、運良く最初に開いたPreview1
の実装でなにやら怪しい部分を見つけました。
ここです
このimpl DerefMut for Descriptors
に非常に強い違和感を覚えました。
Descriptors
はLinuxのfile descriptorと同じでファイルとかを開いたときとかに割り振られるやつです。
問題はこのDescriptors
は常識的に考えて、
の関係を維持する必要がありますが(used
とfree
が同じ数字のdescriptorを持っていたらなにか変なことが起きるということが言いたい)
impl DerefMut for Descriptors
があることによって、別の場所でused
のみを触る可能性がある → 間違って上記の関係がぶっ壊れる可能性があります。
というわけでDescriptors
のDerefMut
を使っているところを探したところ見つかったのがこれです。
fd_renumber
はWASI preview1のdup2(2)
のようなものです。
st.descriptors.insert(to.into(), desc);
この部分がfree
をケアしていなくて、明らかにヤバそうです。
というわけでPOC
// wasi = "=0.11.1"
use std::os::fd::{AsFd, AsRawFd};
fn main() {
let file0 = std::fs::File::create("test0").unwrap();
let fd0 = file0.as_fd().as_raw_fd();
unsafe { wasi::fd_renumber(fd0 as u32, fd0 as u32) }.unwrap();
let file1 = std::fs::File::create("test1").unwrap(); // This line cause a panic in assertion
let fd1 = file1.as_fd().as_raw_fd();
dbg!(fd0, fd1);
}
これが実行時になんやかんやで
でpanicします。panicは脆弱性なのか
結論から言えばプロジェクトによります。
wasmtime
の他の脆弱性を見てみると、panicはDoS扱いになるようです。
しかし、他のRustプロジェクトのcloudflare/pingoraを見てみるとただのpanicくらいなら(単一のコネクションがおかしくなるだけなので)脆弱性とまではいかない感じがします。
レポートを送る
wasmtime
ではこのバグは脆弱性な気がしたためGitHubのSecurityタブからレポートを送りました。
結果
すぐに返信があり、約一週間でパッチがリリースされ公開となりました。
CVE-2025-53901としてCVEの番号もつきました。🥳
ページにはしっかりと脆弱性の詳細が書かれていますが、これは後でプロジェクトの方が作ってくれた文章です。
なのでレポートする時点でここまでしっかり書く必要はなく開発者の方に意図が伝われば十分な気がします。
おわりに
- 意外に探せば脆弱性ある
- コード全体を見なくても局所的な情報からなにか見つけられる
-
正式な発売日は2025/8/12のようですが、O'Reilly Safari Books Onlineではすでに読めます。おすすめ ↩︎
Discussion