PHPカンファレンス2017 レポート

徳丸浩さん、著名PHPアプリの脆弱性に学ぶセキュアコーディングの原則 PHPカンファレンス2017 ゲストスピーカーセッション

2017年10月8日、東京・大田区産業プラザPiOにて、PHPカンファレンス2017が開催されました。本稿では、ゲストスピーカーセッションであるEGセキュアソリューションズ株式会社 代表取締役 徳丸浩さんの講演「著名PHPアプリの脆弱性に学ぶセキュアコーディングの原則」をレポートします。

画像

著名なPHPアプリケーションでも脆弱性を狙った攻撃が絶えません。徳丸さんは「脆弱性対処の王道はプレースホルダによるSQLインジェクション対策のように、とにかく個別の脆弱性から守るための局所対策が大切。とはいえ、脆弱性対処を束ねる総論も必要だ」と言います。

今回の講演では、一般的なセキュアコーディングの原則、そしてPHPの著名アプリの脆弱性に関して、どのような考え方をすればそもそも脆弱性が混入しなかったのかを解説しました。

多くの脆弱性は外部からの入力が原因

はじめに、脆弱性の国際的な分類、CVE(Common Vulnerabilities and Exposures)とCWE(Common Weakness Enumeration)について説明しました。

CVEは個別ソフトウェアの具体的な脆弱性を識別する番号です。CVEの例として、WordPress REST APIの脆弱性(CVE-2017-1001000⁠⁠、Apache Struts2 の脆弱性(CVE-2017-5638)を挙げました。CVE-西暦-連番で構成されるため、どの年の脆弱性かを一目見てわかるようになっています。

CWEはSQLインジェクション(CWE-89)やディレクトリトラバーサル(CWE-22)といった脆弱性の種類を表します。IPAでよく使われるCWEを分類し階層的に表した構造図を示し、多くの脆弱性は、外部からの入力値の扱いに起因していると指摘しました(不適切な入力確認:CVE-20⁠⁠。

画像

またJPCERTのJava セキュアコーディングスタンダード(CERT/Oracle版)では「入力値検査とデータの無害化(IDS00-J⁠⁠」の項において⁠信頼境界を超えて渡される信頼できないデータは無害化する⁠と言及されていると紹介しました。つまり、多くの脆弱性が外部からの入力が原因になっていて、それを無力化せよ、という一般的な指針を示していると解説しました。

典型的な脆弱性と信頼境界の関係

プログラムソースや設定ファイル、データベースに記述されているものは無条件に信頼して良いため、プログラムやSQL文の実行に脆弱性が入る余地はないそうです。例として、信頼境界の中で閉じた処理(固定のSQL文を実行する)を取り上げました。仮に局所的な問題があっても攻撃経路が存在しないため、外部から攻撃されることはないと強調しました。

画像

一方で、信頼境界を超えて外部からの入力を元にSQL文を組み立てる場合、徳丸さんは「信頼境界の外に出た値は信頼できない。信頼が必要な値は⁠信頼境界から外に出さない⁠で用いるように」と呼びかけました。

続いて、典型的な脆弱性であるSQLインジェクション・ディレクトリトラバーサル・認可制御不備・セカンドオーダーSQLインジェクションを例に、信頼境界との関係を説明しました。簡単に言うと、信頼できない値はプレースホルダなどを使い安全な形で呼び出しをすれば良いということです。先に取り上げたIDS00-Jの見出しからも⁠信頼境界⁠⁠信頼できない⁠⁠、⁠無害化⁠という言葉が消え、⁠SQLインジェクションを防ぐ」に改訂されたそうです。

理想は、脆弱性がないことが一目で分かること

では、信頼境界は無意味なのでしょうか? 徳丸さんは「そうではない」と述べ、hiddenパラメーターでSQL文を渡している値を2つに整理しました。⁠どんな値でも安全に使える方法があるもの」「値を信頼するしかないもの」です。

どんな値でも安全に使える方法があるものとして、SQLクエリに文字連結を用いず、プレースホルダを用いること。そしてHTML表示の際にもれなくエスケープ処理を行うことを挙げました。 値を信頼するしかない例として、SQL文、プログラムコード、ログインユーザー名を挙げました。

徳丸さんは、脆弱性対処が局所化できる場合はそれがベストだとし、⁠どんな値でも安全に使える方法がある場合は淡々とその方法をやること」と述べました。例えば、ヘッダインジェクションが発生しないライブラリや、PHP最新版を使うことなどが本質的な解決手段とも話していました。

そして、信頼された値が要求される場合は、信頼が必要な値を「信頼境界から外に出さないで用いる」ことを強調していました。なぜなら信頼境界の外に一度出た値は、いくらバリデーションをしても信頼できる値ではないからです。徳丸さんは「信頼されたデータ」が必要な例として、プログラムコード、SQL文、evalの入力、設定ファイル名に記載されたファイル名、正規表現、オブジェクトを挙げました。

画像

ただし、認証・認可によって「信頼できることを確認する」ことは可能だと徳丸さんは補足しました。phpMyAdminにおけるSQL文の呼び出しを例に、認証(ログイン済みユーザー⁠⁠、認可(権限を与えられたユーザー)を説明し、認証・認可によって信頼ができるケースについて解説しました。

局所的に絶対安全な方法で実装すれば、脆弱性は混入しない

開発の現場では「信頼されたデータ」が要求される際に「信頼境界の外へ、本当に値が出ていないか⁠⁠、この確認が漏れてしまうことが多くあると注意を促しました。たとえば、hiddenパラメーターでSQL文を渡しているコードなどです。徳丸さん自身も、納品する直前のもので目にした経験があったそうです。徳丸さんは、⁠局所的に安全を積み重ねることが、脆弱性を作り込まない早道」であると考えをまとめました。

画像

講演の後半は、ケーススタディーとして、いくつかのPHPアプリケーションの脆弱性について解説されました。

Welcart 1.9.3 のオブジェクトインジェクション脆弱性

Welcartは、WordPressをベースにショッピングサイトを構築する際に便利なプラグインで、国内でも非常に多く用いられています。はじめに、Welcartのフォーラムで、ユーザーからインシデント報告された様子を紹介しました。徳丸さんは、Welcart1.9.3と1.9.4の修正の差分を比較し、⁠外部入力(クッキー)をデシリアライズしている、典型的なオブジェクトインジェクションだ」と指摘しました。CMSやフレームワークのような柔軟のものほど起こりやすい脆弱だそうです。unserialize関数に信頼できない値(信頼境界を超えてきた値)を渡してはいけないと指摘しました。

画像

unserialize関数に任意の文字列を処理させることができる場合、攻撃者に都合の良いクラスのオブジェクトを生成させることができます。オブジェクトが生成されるとデストラクタを通ることになるため、オブジェクトが生成されてからバリデーション等をおこなっても手遅れです。とはいえ、シリアライズされた状態のままバリデーションを行うことも困難です。徳丸さんは、⁠外部入力を処理する場合は、JSONを用いることが有効である」と紹介し、やってはいけないことを知らずにやってしまったことが根本的な原因だと解説しました。

WordPress REST APIのコンテンツインジェクション脆弱性

脆弱性情報が公開されてから48時間足らずの間に、改ざんされたWebサイトの数は6万以上にのぼったそうです。認証なしにリクエスト一発でコンテンツを改ざんできる脆弱性を、実際にデバッガで追いかけながら解説されました。

脆弱性の原因は、存在しないコンテンツが指定された場合、update_item_permissions_checkメソッド(権限の確認)の様々なチェックをすべてくぐり抜け、メソッド最後のreturn文にてtrueが返されていたことが原因でした。

画像

認証不要で、極めて容易にコンテンツが改ざんできるため、深刻な脆弱性であることがわかります。

徳丸さんは、⁠この脆弱性は権限チェックの間違いの典型例です。権限のチェックと更新で、異なる入力を用いているわけですから、両者の不整合がチェック漏れの原因になります」と言及し、⁠入力値を使用する度に int にキャストしている箇所があり、これだ潜在的にバグや脆弱性の原因です」と述べました。

徳丸さんは以下のいずれかの方法で対処すべきだったと説明しました。

  • 入力値のバリデーションにて数値以外のものをエラーとする(推奨)
  • 入力時に整数にキャストし、以降の処理では一貫してキャスト後の値を用いる

WordPressのように、メジャーなアプリケーションでも起こった脆弱性なので、教訓として覚えておいてほしいと徳丸さんは話しました。

まとめ

今回、ケーススタディーで紹介された脆弱性のほとんどはバリデーションで防げたものでした。バリデーション(フォームバリデーション)で脆弱性対処ができるとは限りませんが、アプリケーションの前提条件を確認する意味でバリデーションは重要だと、徳丸さんは言います。

最後に、⁠バリデーションはしましょう。誤解されがちだが、私はバリデーションしなくていいとは言っていませんよ(笑⁠⁠」と、徳丸さんが締めくくったところで、ドッと笑いが起きました。

この講演の資料と動画は公開されています。どのような考え方をすればそもそも脆弱性が混入しなかったかという考え方を、実例をもとに知ることができます。非常にわかりやすいので、ぜひご覧ください。

おすすめ記事

記事・ニュース一覧