patchのパッチの話

次のような2つのFreeBSD SAがありました。

どちらも、特別に仕組まれた(a specically crafted)ようなパッチファイルを patch(1) に食わせることで、任意コマンドの実行が可能だった、というものでした。patch(1) はシステムのアップデートなどのために管理者権限で実行される場合が考えられ得るため、ちょっと嫌な脆弱性だった、と言えます。

Background の節に、diff(1) が、とか、15:18 には ed(1) が、とか書かれていますが、それらは背景として以外は関係ありません(直接には修正されるわけではありません)。また、patch(1) は元々、Perl などでも有名な Larry Wall さんが書かれたプログラムですが、だいぶ以前にBSD版やGNU版などそれぞれに分岐しており、今回の問題はどちらも基本的にFreeBSD版の問題です。

それぞれの詳細をちょっと見てみます。

15:14

SCCSやRCSを起動するような機能の実装に不備があり、特別に仕組まれた(a specically crafted)パッチファイルによって任意コマンドの実行が可能でした。

差分を見ると、元のコードでは文字列にコマンドラインを組み立てて system(3) で実行していたのを、fork(2) と execv(3) を自前で呼ぶようにして、変なコマンドが呼ばれる可能性が無いような安全なコードに修正されています。

15:18

POSIXでも要求されている機能なわけですが、diff(1) にある機能である ed(1) のコマンドによるパッチを受け入れて、ed(1) にそれを渡してパッチを当てる機能において不備があった、というものです。なんでそんな機能が必要かというと、直接 ed(1) を使ってしまうと、危ないコマンドがあっても実行されてしまうので、patch によって「許されたコマンド」だけを渡すようにすることが期待されているわけです。

差分を見ると、1個目の変更として、ed(1) を red という名前で起動することによって、サブコマンドの実行などが制限されるようにしています(rはrestrictedの意味)。もうひとつの変更は、ed の 's' コマンドをそれまでは単純に渡していた所に、行が継続するかどうかといったチェックが入っています。