MicroArchitectures
H.Ueda
Programmer
ブログ
NTFSドライバーの「信頼」が招く権限昇格:ntfs3の脆弱性を深掘りする
最近、「ただのファイル属性」がroot権限に化ける Linux ntfs3に潜んだ権限昇格のわな:Linuxカーネルが“ファイルのうそ”を信じたという記事を読み、ファイルシステムの「信頼境界」という考え方が実務的にも非常に興味深いと感じたので、こちらで内容を整理してみたいと思います。
これ要注意ですね。ntfs3ドライバを使っている場合ですね。
LinuxカーネルでNTFSを扱うためのドライバー「ntfs3」において、一般ユーザーがroot権限を取得できてしまう「InjectionBunny」と呼ばれる脆弱性が報告されました。この問題の面白いところは、高度なメモリ破壊(バッファオーバーフローなど)を必要とせず、カーネルが「ファイル属性」というデータをそのまま信じてしまった点にあります。
権限昇格が発生する仕組み
この脆弱性は、Linux側でNTFS上の「WSL(Windows Subsystem for Linux)」用の拡張属性を読み取る処理に起因しています。
ntfs3ドライバーは、NTFS上のファイルが持つ $LXUID(所有者ID)や $LXMOD(パーミッション)といった属性を読み取り、それをLinuxカーネル内部の「inode」情報に反映させます。しかし、この際に「SUID(Set User ID)」などの特殊な実行権限ビットを適切に除去していなかったことが問題となりました。
処理の流れを簡単に図解すると、以下のようになります。
flowchart TD
A["細工されたNTFSイメージ<br>(USBメモリなど)"] --> B["$LXUID=0 (root)<br>$LXMOD=0104755 (SUID付)"]
B --> C["ntfs3ドライバー<br>(ntfs_get_wsl_perm)"]
C -- "SUIDビットを消さずに反映" --> D["Linux上のファイルとして認識<br>(root所有・SUID有効)"]
D --> E["一般ユーザーが実行"]
E --> F["実効UIDが 0 (root) に昇格"]
なぜこれが問題なのか
通常、私たちが自分のPCでファイルを作成するとき、勝手に他人の所有(特にroot所有)のSUIDファイルを作ることはできません。OSの権限チェックによって阻まれるからです。
しかし、この「InjectionBunny」では、攻撃者があらかじめ自分の管理下にある環境で、NTFSイメージの中に「所有者はrootで、SUIDビットが立っている」という嘘の情報を書き込んでおきます。これをLinuxにマウントさせると、カーネルがその嘘をそのまま信じて「これはroot権限で実行すべきファイルだ」と判断してしまうわけです。
脆弱性の核心:ntfs_get_wsl_perm()
具体的な原因は、カーネルソースコード内の fs/ntfs3/xattr.c にある ntfs_get_wsl_perm() という関数にあります。
この関数はWSLの拡張属性を読み取りますが、以下のような対応関係でデータをコピーしていました。
| NTFS側の属性 | Linux側の属性 (inode) | 内容 |
|---|---|---|
$LXUID |
i_uid |
ファイルの所有者ID |
$LXGID |
i_gid |
ファイルの所有グループID |
$LXMOD |
i_mode |
パーミッション(ここが問題) |
本来、外部からマウントされた「信頼できない」データに含まれるパーミッション情報を i_mode にコピーする際は、セキュリティのためにSUIDビット(04000)やSGIDビット(02000)をマスク(除去)すべきでした。しかし、このチェックが漏れていたため、ファイル属性がそのまま実行時の権限に化けてしまったのです。
攻撃のシナリオと条件
「NTFSをマウントしただけで即座にハックされる」というわけではありませんが、いくつかの条件が重なると危険です。
- 細工されたデバイスの接続: 悪意のあるファイル属性を書き込んだUSBメモリなどを物理的に挿入する。
- マウントオプション: そのNTFSボリュームが
nosuidオプションを付けずにマウントされる。 - 実行: 一般ユーザーが、そのボリューム内にある細工されたバイナリを実行する。
もしループバックデバイス(ディスクイメージをファイルとしてマウントする仕組み)が利用できる環境であれば、物理的なUSBメモリすら不要で、ダウンロードしたイメージファイルから攻撃が成立する可能性もあります。
どのように防ぐべきか
この問題への対策として、まずはカーネルを修正済みのバージョンにアップデートすることが先決かと思います。
また、運用の工夫でリスクを下げることも可能です。例えば、外部ストレージをマウントする際には必ず nosuid オプションを付与するように設定しておくといった対策が考えられます。これは「ファイルシステム上のSUIDビットを無視する」という設定なので、今回のような「嘘の属性」による権限昇格を防ぐのに有効です。
# マウント時の例
mount -t ntfs3 -o nosuid /dev/sdb1 /mnt/usb
まとめ
今回の脆弱性は、システムが外部のデータ(ファイルシステムのメタデータ)をどこまで信頼すべきか、という「信頼境界」の難しさを改めて浮き彫りにした事例だと感じます。
メモリ安全性の問題ではなく、ロジック上の「うっかり」が深刻な権限昇格につながるというのは、ソフトウェア設計において教訓にすべき点かもしれません。普段何気なく使っているUSBメモリや外部ディスクも、OSにとっては「信頼できない入力データ」の塊であることを意識しておくと良さそうです。