2016年11月3日にPHPカンファレンス2016が開催されました。本稿では、ゲストスピーカーである徳丸浩さんのセッション「安全なPHPアプリケーションの作り方2016」についてレポートします。
最近のPHP関連の脆弱性
徳丸さんはセッションを通して、PHP関連の脆弱性の話を取り上げていきました。
Joomla!の事例
Joomla!の権限昇格脆弱性についての話がありました。次の2つの問題を含んでいました。
- ユーザ登録時に管理者権限を設定されてしまうという問題
- ユーザ登録を許可していない設定にしてもユーザ登録が行えてしまうという問題
徳丸さんはこれらのデモを行い、攻撃の流れを見せました。
原因としては登録のメソッドが2つ存在し、そのうちの一方がユーザ登録許可の設定を確認していないことが問題となっていることを指摘しました。対策としては、開発側は該当メソッドの削除、利用者側はバージョンアップを行うというものでした。
ここでの教訓は「古いコード・使わなくなったコードは速やかに削除する」というものでした。
さらにJoomla!では以前に類似の脆弱性が起きており、それについても言及していました。
セッション汚染
次に、セッション汚染を取り上げました。セッション汚染とはセッション変数を外部から変更できる脆弱性のことで、これを利用してセッション変数にオブジェクトを突っ込む(オブジェクト・インジェクション)などするととても危険なものです。しかしこれは、PHPあるいはアプリケーションに脆弱性が存在しないと行えるものではありません。
セッション汚染脆弱性についていくつか事例を紹介し、デモを行いました。
徳丸さんは「オブジェクト・インジェクション以前の話で、セッション汚染単体で問題となる可能性が高い」と述べていました。
OSコマンドインジェクション
OSコマンドインジェクションについては、「ケータイキット for MovableType」の脆弱性を取り上げました。
脆弱なコードとその対策版を見比べると、エスケープ処理について追記されているようでした。
徳丸さんは、「この脆弱性に対する調査委員会による調査報告書はよく書かれているので、ぜひ一読してほしい」と話していました。
PHPに用意されたシェルエスケープ関数は安全なのか、についてですが、escapeshellcmd
関数には脆弱性があるということでした。
OSコマンドインジェクション対策として、徳丸さんの著書では4通りの対策を示し、エスケープは4番目で、あまり信頼度は高くないとのことでした。エスケープを避けるために、シェルスクリプトを静的な文字列として定義する、またパラメータは環境変数で渡す、という方法を提示しました。
正規表現インジェクション
phpMyAdminの正規表現インジェクションの例を紹介しました。
正規表現を外部から指定できる状況は避けるべきで、外部由来の値は正規表現として利用しないようにする原則に則って対策することとしました。
SQLインジェクション
Zend FrameworkのSQLインジェクションの例を紹介しました。
識別子と式を区別するやり方のソースを見てみると、最初はカッコがあれば式とみなすというような記述でした。それが改定され、英数字0文字以上に続けて開きカッコがあり、末尾に閉じカッコがあれば式とみなすようになりました。さらに複雑な形式に対応するために改定されますが、それでもまだ攻撃しようとするとできてしまう状況でした。
徳丸さんは、「文字列の内容によって識別しか式かが決まるというものは責任境界があいまいになってしまい、本来はそれぞれのメソッドは名前などで明確に区別されるべき」と指摘しました。そのため、これはZend Frameworkの仕様の問題である、との結論を一旦出していました。
ここで終わりかと思ったところ、さらにZend Frameworkが改定し、カッコのネストを許容するようになりました。改定は続きますが、それでも実際にまだ穴は残っていると説明していました。しかし、Zend Frameworkは2016年9月28日をもってEnd of Lifeとなり、もうZend Frameworkそのものの改定の見込みはありません。Zend Framework側の回答としては「アプリケーション側で対応せよ」とのことで、これに関しては徳丸さんも同意していました。具体的にこれに対する対策としてはZend Framework2または3、あるいは他のフレームワークへの移行を挙げていました。
XSS(JavaScriptリテラルのエスケープ)
script
要素内で文字列リテラル動的生成のアプローチとして、次の3つ挙げました。
- 過剰エスケープ
- HTMLノードとして文字列生成後JavaScriptから参照
- Inline JSONP
そもそもなぜJavaScriptの動的生成を避けるべきかというと、コードとデータを分離すべきであり、またJavaScriptのエスケープはとてもややこしいからだと説明しました。HTMLノードを経由するかInline JSONPの採用を勧めていました。
総括 ― 安全なウェブアプリケーションのための原則
安全なウェブアプリケーションのための原則として、次の6点を挙げていました。
- わかりやすく書こう、うますぎるプログラムはいけない
- 局所的に脆弱性を解消する
- 防御的プログラミング(Defensive programming)を実践する
- 単体テストを徹底する
- コード、命令に対して、外部からの値を持ち込まない
- 危険な機能の利用を極力避ける
これだけ読んでも当たり前のことを言っているだけ、という印象になりがちだと前置きをし、それぞれの解説を簡単に行いました。
「わかりやすく書く」という点では、シンプルに実装する、危険な機能を避けるということでした。また、「防御的プログラミング」については本から引用して「『そうなるはずだ』と決めつけてしまわないことが防御的プログラミング」と話しました。「プログラムには必ず問題があり、変更されるものである」ということです。
まとめ
徳丸さんは、いつも通り淡々とした口調で脆弱性の実例の解説とデモとを行いました。さらっとPPAPなど今はやりの話題を混ぜてくるところも徳丸さんらしいと感じました。
内容としてはもしかしたら「ごく当たり前」「そうすべきだと皆が分かっていること」かもしれませんが、実例をみると危機意識が高まったり、改めて危険性を再認識できたりします。最新の実例やそれの対策をまとめて見ることができる、非常に内容の濃いセッションでした。
資料も公開されていて、これを見るだけでも実例をかなりのところまで知ることができます。非常にわかりやすいので、ぜひ読者の皆様もご一読ください。