フレームワークの責務とセキュリティ
お久しぶりです。 夜中にモツ煮込み作りながら書いてます。
さて、今回はフレームワークの責務とセキュリティについて思うところがあって久しぶりにエントリを書くことにしました。
背景
まず、背景としてBEAR.Sundayの一部であるBEAR.PackageにサンプルとしてBasic認証の実装を追加するPullRequest#90でのやり取りがあります。このPRはzukimochiさんが作ったものに僕が修正を加えて出した物です。この中では、Basic認証用のパスワードをハッシュとして扱うように実装されています。
多くの人が斜め読みしているのは背景説明が長すぎるからだと思ったので削除しました。詳しく知りたい方はPRをご覧ください。
本題
いよいよ本題です。 PRの最後にkoriymさんが発言している次の言葉はフレームワーク開発に於いてとても重要です。
より関心のある問題に集中するために、特に専門としていない問題に注力しすぎないようにするために役立てているのです。
言い換えれば、「余計な機能作ってる暇あったらよりいいフレームワーク作ろうぜ!」といったところでしょうか。この考えをもとに開発することによってフレームワークは肉を削ぎ落して、骨格だけをもつ枠組みとしてより洗練されていきます。
そこで重要になってくるのが、削ぎ落すべきものと削ぎ落してはならないものの線引きです。先のPRでの問答は「生パスワードのセキリティリスク」がその線の内か外かあるいは内側の場合どう対処するのかの議論になります。ちなみに、本エントリのタイトル「フレームワークの責務とセキュリティ」の責務とは境界線の内側のことです。
では、この実装がフレームワークの実装として取り込まれるという前提で話を進めましょう。
ここで、生パスワード保存機能を削ぎ落さずにリリースした場合に想定しうるセキュリティリスクを考えてみると、こんなシナリオが浮かびます。
- 開発者が生パスワードを設定ファイルに書く形で管理画面のアクセス制御を行うアプリケーションを作成
- アプリケーション利用者AがSNSでも利用しているパスワードを設定ファイルに書きインストール
- アプリケーションのバグ(ディレクトリトラバーサル脆弱性)を利用し攻撃者がパスワード設定ファイルを取得
- 攻撃者がアプリケーション利用者AのSNSアカウントを乗っ取る
より具体的にしました
これは、PRで挙げた問題点の具体例ですね。
では、このセキュリティリスクに対する責務はフレームワークにあるのでしょうか? それとも、フレームワークの本質ではないと切り捨てるべきでしょうか?
僕はフレームワークの責務であると考えます。 提供する機能がセキリティリスクを抱えているのであれば当然です。フレームワークに余分な複雑さを持ち込みたくないのは分りますし、一般にはそうあるべきですが、セキュリティリスクが絡む場合はリスク回避もフレームワークの責務です。
ならばどうすればいいのか、選択肢は3つほどあります。
1つ目は、問題の機能自体を切り捨てることです。 もしフレームワークの本質を損なわないのなら切り捨ててしまえば簡単です。フレームワークが十分な拡張性を持っているならば、第三者による実装に期待することができます。
2つ目は、セキュリティリスクを抱えていることをフレームワークの利用者(=アプリケーション開発者)に対して周知徹底することです。 マニュアルやソースコード中のコメントにわかり安く注意事項を表示します。先のシナリオでは開発者が広く一般に使われるアプリケーションを生パスワードを利用する形で実装しなければ、リスクは回避できたわけです。消極的な対策であり、マニュアルをきちんと読まない開発者を想定するとまだリスクは残りますが、責務を果たしていると言えるでしょう。
3つ目は、リスク排除した実装を提供することです。今回で言えば、生パスワード保存を提供せず、適切なハッシュ化などを用いたパスワード保存のみを提供します。 こちらも、生パスワード保存機能を自分で開発して利用してしまう開発者というリスクはまだあるわけですが、それを言い出したらさすがにきりがないですし、水が低い方に流れるように、開発者も楽に実装できる方に流れるのできっとハッシュ化されたパスワード保存を利用してくれるでしょう。(これがPRでの僕の主張です)
最終的にどれを選択するかはリードコミッターやプロダクトオーナーの采配によることになりますが、何も対策しないというのはあり得ません。オープンソースでタダで開発していても、その倫理的責任から逃れることはできません。
また、3つ目の積極的な解決方法を容易にとることができるのであれば、2つ目を採用するのではなく3つ目で対策を行うべきでしょう。責任の範囲内ではベストエフォートをなすべきです。