Califのセキュリティ研究者は、約40年前のバグに起因するOpenBSDのローカル権限昇格(LPE)の脆弱性を実証しました。この欠陥はオリジナルのBSDソースコードに由来しており、そこでは共有メモリのアタッチカウンターが符号付き16ビットのshortとして定義されていました。このカウンターは符号付きであるため、共有メモリのアタッチレコードを伴うプロセスを繰り返しフォークすることで、値が最大制限の32,767を超えてラップアラウンドし、負の値になる可能性があります。この整数オーバーフローと、カーネル内の別の範囲外書きを組み合わせることで、攻撃者はroot権限を取得することが可能になります。

この画像は、記事で説明されているOpenBSDのカーネルバグに関する主要な研究プロジェクトを表している。
このエクスプロイトの仕組みは、KARL、SMAP、SMEPといった現代的なセキュリティ対策をバイパスするための複雑な一連の操作に依存しています。研究者はまず、259のプロセスをフォークすることで、共有メモリのアタッチ数を負の値(-32,643)にラップアラウンドさせました。次に、`sysctl(KERN_MALLOCSTATS)`のメトリクスを使用してメモリ割り当てを追跡しながら、ヒープグルーミングを実行しました。`IPC_RMID`操作中にレースコンディションを制圧することで、研究者はサイズを誤認した共有メモリセグメントをアタッチすることに成功しました。これにより、カーネルのメンバーシップフィールドを上書きする条件付きの範囲外書きがトリガーされました。最終的に、グループメンバーを走査するためにソケットを閉じることで、ページテーブルエントリ(PTE)の自己参照マッピングを変更するアトミックなデクリメントをトリガーし、それをユーザーアクセス可能モードからスーパーバイザアクセス可能モードに切り替えることで、カーネルコードの実行を可能にしました。
これらの脆弱性はOpenBSDのerrata 026および018で修正されましたが、研究者は依然として残るいくつかのアーキテクチャ上のリスクを強調しました。彼らは、OpenBSDのKARLシステムが関数とデータの位置をランダム化する一方で、カーネルのメモリアロケータは依然として決定論的であることを指摘しました。これは、起動初期の割り当てが一貫して予測可能な場所に配置されることを意味し、`lo0`や`enc0`のioctlハンドラなどの関数ポインタを上書きするための理想的なターゲットとなります。これらのリスクを軽減するために、研究者はいくつかの改善策を提案しました。これには、二重連結リストの不変性をチェックする「safe-unlinking」の実装、自己参照PTEマップの割り当てアドレスのランダム化、またはベースアドレスと実行時の割り当て順序の両方をランダム化することでカーネルアロケータを非決定論的にすることなどが含まれます。また、彼らは「Alloc Tokens」のような今後のコンパイラ機能を指し示しました。これは、ポインタを含む割り当てをポインタを含まない割り当てから分離し、同様のクラスの脆弱性を無効化できる可能性があります。