最近この種のエントリがありませんでしたが、個人的に面白いとセキュリティ系の話題はできるだけ書いていきたいと思っています。
glibcのstrfmon関数の実装に脆弱性があり、簡単なスクリプトで大量のメモリが割り当てられる脆弱性があるようです。影響するglibcは2.10.1以下なので影響範囲は非常に大きいです。
最初はBSDのlibcで脆弱性が発見され、glibcでも影響があることは脆弱性の発見者には分かっていたようです。詳細はアドバイザリに記載されています。
http://packetstormsecurity.org/0909-advisories/glibc-format.txt
詳しい説明はアドバイザリを読んで頂くとして、当初はBSD系OSのglibcで問題が発見されたそうです。NetBSD, FreeBSDとMacOSXに脆弱性レポートを送ったそうですが、修正されたのはNetBSDだけだったそうです。この脆弱性の危険性はglibcの開発チームにも伝えられたがglibc開発者にBogus(偽物)として取り扱われたと書かれています。
And what exactly does an BSD implementation has to do with glibc?
(で、具体的にどうしてBSD実装の問題がglibcに関係してるのかい?)
というレスポンスだったそうです。脆弱性の発見者はglibcのコードにも問題があるから、バグレポートを送信したのですがありがちなレスポンスです。PoCを作ることは面倒です。コードから分かるような脆弱性はPoC無し(さらにはAtack Vector無し)でも修正すべきですが、PoCが無いと開発者はなかなか動いてくれないのはどのプロジェクトでも一緒です。(PoCがあっても動かない場合も…)
この様な事例は少なくありません。この事例は「基盤システムや周辺システム、フレームワーク、ライブラリがアプリケーションを守ってくれるべき」という考え方をベースしていては安全なシステム作りは遠のくばかりである、とする私の考え方の正しさを証明する多数の事例のうちの一つだと言えるでしょう。
PoCがアドバイザリに書いてあったので試してみました。
php -r 'money_format("%.1073741821i",1);'
スワップがどんどん大きくなるところまでは確認しました。8GB積んだPCですが、Momonga Linux 64bit版なので本当にメモリとディスクスペースが無くなるまで メモリを使うと考えられます。Segfaultまでは確認しませんでした。
PoCの引数はstrfmonを使った通貨をフォーマットする引数としては明らかにおかしな形式です。攻撃用のプログラムをシステム上で実行されたらどうしようもありませんが、アプリケーションが「適切」に入力をバリデーションしていればアプリケーションユーザからDoSを行われる危険性はありません。
(解り易い書き方をすると、PHPプログラムでユーザが通貨フォーマットを指定可能、そしてバリデーションをしない、という条件さえ整えば非常に簡単にリモートからDoS攻撃を行える、脆弱性です。当然ですが根本的な問題はPHPの問題でなくlibcのstrfmon関数の問題であり、この関数を利用しているアプリケーション全般に適用できる問題です。)
アプリケーションが”適切にバリデーション“していれば、アプリ自身のみでなく周辺プログラムの“脆弱性”が”セキュリティホール”にならない例は幾らでもあります。ソースコードレベルの監査を行っている人であれば沢山の同様の事例を知っているはずなので良く理解できる話だと思います。
少し前に文字エンコーディングのバリデーションはどこで行うべきかを解説したエントリで使った図です。バリデーションは文字エンコーディングにだけ必用なものではありません。この図の中にには数えきらないほどの入出力先が省略されています。今回の例はOSの基本ライブラリであるlibc/glibcへの不正な出力が問題の引き金でした。このケースもユーザ入力を許可していたとしても普通のバリデーションを行っていれば基盤ソフトの問題(脆弱性)が本当のセキュリティ問題(セキュリティホール)とならない例の一つです。
アドバイザリの通りだとすると#の直後に.が記述された場合に脆弱、つまり、通貨の表示形式のようなフォーマットであれば普通の形式バリデーションで弾けます。テストファースト、TDDとか流行っているのにどうして安全性を向上させるためバリデーションの一つや二つ増やす事が流行らないのか?どうすれば流行るのでしょうね。
アプリケーションでやるべきセキュリティ対策はアプリケーションでやってあたり前である、とセキュリティ専門家やアプリケーション開発の経験者は啓蒙すべきだと思います。アプリケーションにセキュリティホールが無いように作れるのはアプリケーション開発者である、やるべき事はアプリケーションでやり「多重のセキュリティ」により多少のミスがあっても攻撃されないか攻撃され辛いシステムを作る。このように心がけるようにすれば必要以上に複雑に感じられるアプリケーションのセキュリティ対策は非常にシンプルになります。
おまけ
アドバイザリに
Interesting is that the PHP memory_limit has no control over what will happens in the level of the libc. Function strfmon(3) can allocate a lot of data in memory without control by PHP memory_limit.
(PHPのmemory_limit制限はlibcのレベルで何をしようと制御されない事は興味深い。strfmon(3)関数はPHPのmemory_limit制御を超える大量のメモリを割り当てる事ができる)
と書いてありました。PHPをPoCに使っているのでPHPの脆弱性もコードレベルで監査しているか、PHPを使っている方なのでしょう。PHPのmemory_limit制限は”PHPが使ったメモリ”しか計算しません。具体的にはPHPのアプリケーションフレームワーク(言語エンジン、C言語のSAPIやモジュールを作るフレームワーク)で利用されているmalloc等のラッパー関数であるemalloc等で確保したメモリだけしか計算に入れません。
glibcやmysql, postgresqlなどのライブラリが確保したメモリやモジュールとして動作している親のアプリケーション(Apache Web Server等)のメモリ使用量は全く考慮されません。
基本的な知識ですが、仕組みを理解していないと誤解する部分です。
Leave a Comment