12月1日、東京都大田区産業プラザPiOにて「PHPカンファレンス2019」が開催されました。本稿ではその模様をお届けしていきます。今回は、ゲストスピーカーである廣川類さん、Sebastian Bergmannさん、徳丸浩さんのセッションをレポートします。
廣川類さん「PHPの今とこれから2019」
日本PHPユーザー会の廣川類さんは「PHPの今とこれから2019」というタイトルで、先日リリースされたPHP 7.4の話など、最近のPHPについて発表しました。
PHPのあゆみ
PHPは1995年に誕生したWebアプリケーションに使用されるスクリプト言語で、現場の課題を簡単に解決してくれる便利なツールとして、誕生以来、Webとともに成長、進化を続けてきました。
PHPは成長、進化をしていくうちに、大衆的なパーソナルツールから、安全で実用的な高性能ツールのプラットフォームへと変化してきました。PHPの総ステップ数がバージョンアップとともに上がってきているように、その変化を見ることができます。PHP5.0ではオブジェクト機能を強化し、PHP5.3ではいわゆる普通のプログラミング言語として変わり、PHP7.0になりやっと大幅な高速化ができるようになりました。
PHP7の普及
現在のPHP7とPHP5のシェアについて、PHP7は42.1%、PHP5は57.4%であることを示しました。昨年のPHP7のシェアが23.6%であることを考えると、2倍弱増えたことになります。今回のイベント参加者もPHP7とPHP5をそれぞれ使っている方で分かれていましたが、昨年と比べるとだんだんとPHP7が浸透してきている印象をもちました。
PHP7は「より速く、快適に」をモットーに作られています。実用アプリケーションの例としてWordPressを取り上げ、実行速度、メモリ消費ともにPHP5から大きく改善していることを紹介しました。こういった面でPHP7を使うメリットは大いにありそうです。
PHP7.4での改善
PHP7.4の改善、変更のポイントとして、以下の点を挙げました。
クラスプロパティの型指定
OpCacheのプリロード指定:これにより起動時にキャッシュをロードすることで性能を改善できるようになりました。
FFIにより外部機能の利用が容易に
配列スプレッド構文
アロー関数(ショートクロージャ)、匿名関数の記述を簡略化、fn
が予約語に
??=
構文:ある変数が設定されている場合に代入され、そうでない場合に代入文字列を代入する構文。
mb_str_split()
関数の追加
数値リテラルセパレータ
+.
の優先順位を変更:従来、優先順位が同じでした。
弱い参照:キャッシュのようなオブジェクトの破棄に影響を及ぼさない参照の実装に有効になるようになりました。
PHPのこれから
HHVMでJIT(Just-in-Time Compiler)を採用して高速化したように、現在開発中のPHP8でもJITを採用することで高速化の検討をしています。ただし、JITにしても単純にアプリケーションが速くなるわけではないことも付け加えていました。
最後に廣川さんは、「PHPは言語がシンプルでドキュメントも豊富にあるため、学習が容易であること。そしてWebの進化に対応し、必要十分な解を提供してくれるという進化を継続してきたこと。このようなPHPを使ってユーザーはプログラムを書くだけでなく、改善をする意識を持つことで、さらに自身が成長したり、夢を現実にできるハッカーになれるのではないか」として発表を締めくくりました。
Sebastian Bergmannさん「PHPUnit: Past, Present and Future/Sebastian Bergmann」
PHPUnitの生みの親である、ゲストスピーカーのSebastian Bergmannさんは、PHPとPHPUnitの歴史そして今後について話しました。
プログラミングとの出会い
Sebastianさんは、8歳のときに映画『ウォー・ゲーム』(原題:WarGames)に触発されてコンピュータの仕組みやプログラミングを学びたいと思い、紙とペンでプログラミングをはじめました。12歳でBASIC言語を、13歳のときにはAmiga 1200でC言語と、Assembly言語で2D・3Dグラフィックのプログラミングをするようになります。当時のプログラミングではよくコンピュータをクラッシュさせていました。
大学1年生のとき初めてX86ベースのパソコンを手に入れてAmiga Demosceneのアーティストと交流を持ち、そのアーティストをきっかけにPHPと出会います。1999年には本格的にPHPを使い始め、PHPのコミュニティにも参加するようになります。2000年にはPHPへのコントリビュートもはじめます。
PHPUnitの歴史
2000年当時PHPを使ったプロジェクトに関わる中で、ビジネスロジックに対するテストが全く書けないことにフラストレーションを抱えていました。SourceForgeにはすでにPHPUnitという名前のプロジェクトが存在していて、何とか動かそうと調査したり、開発者に問い合わせたり、フォーラムに投稿してサポートを求めたものの全く機能するものではありませんでした。
最初にSebastianさんがPHPUnitを公開したのは2001年11月で、JUnit3のソースコードをコピーして一行ずつPHPに書き換えただけのたった6ファイルのコードで、たくさんバグもありました。ごく初期のPHPUnitはテストを書くためのフレームワークで、テストランナーも存在しておらず、ユーザーが自分でテストランナーを書かないといけませんでした。
JUnitはExceptionを捕捉することでテストの失敗を表現していますが、PHP4にはExceptionの機能がありませんでした。初期のPHPUnitではPHP4でExceptionをエミュレートすることで実現していましたが、サポートするのはとても骨が折れるものでした。2004年にPHP5が言語としてExceptionをサポートしてくれたことは本当に嬉しかったと、当時を振り返りました。そしてPHP5の公開と同日に、テストランナーを備え、Exceptionのエミュレートをしなくて済むようになったPHPUnit2を公開しました。
PHPUnitの歴史を語る上で欠かせないのはXdebug作者であるデリックとの交流だと言います。2006年当時同じ会社に勤めており、住まいも近所だったので頻繁に意見交換をしてモックの考えなどをPHPUnitに取り入れるきっかけになったそうです。2006年はSymfony1.0がオープンソースとして公開されるなど、フレームワークが台頭して今日あるようなエコシステムが確立されるようになった年でもあります。
2017年、PHPUnit6ではnamespaceに対応しました。多くのユーザーからテストのファイルを書き直さなくてはいけなくなってしまったという意見を受け取り、「そのことについては申し訳なく思っている」とコメントしていました。PHPUnitは毎年メジャーバージョンアップをしていますが、新しい機能が毎年追加されているというわけではありません。年に1回のバージョンアップで使われなくなったコードの削除など改善のきっかけにしています。
PHPUnitの今後
2,3年前からPHPUnitにコントリビュートしたい人を集めて、新機能の開発やバグの修正方法をコーチングするコード・スプリントというイベントをヨーロッパで始めています。
Sebastianさんは最後に、次のように話し、発表を締めくくりました。
「20年という歴史を持つPHPUnitですが、まだまだ改善していきたいことはたくさんあります。PHPUnit自体の改善に加えて、ドキュメントの翻訳などPHPUnitにコントリビュートしてくれるすべての人にありがとうと伝えたいです。
2020年にPHPUnitは20周年を迎えます。PHPUnit9に向けて開発を続けているので、是非フィードバックをしてください。また、PHPUnitやPHPに対する質問には何でも答えたいと思っていますので気軽に話しかけてください。私は20年前、PHPのテストができないという問題を解決しようと思い立ち、解決策を探しているうちにたまたま自分で開発することになり、オープンソースコードとして公開した普通の人なのですから」(Sebastianさん)
徳丸浩さん「オニギリペイのセキュリティ事故に学ぶ安全なサービスの構築法」
EGセキュアソリューションズの徳丸浩さんは「オニギリペイのセキュリティ事故に学ぶ安全なサービスの構築法」というタイトルで発表しました(発表資料)。今回の発表はPHP成分は少ないとあらかじめ断り、架空のペイメントサービス「オニギリペイ」がさまざまなトラブルに見舞われる状況をロールプレイングしながら、セキュリティなどの問題を扱いました。
オニギリペイは様々な店舗で決済され、データセンターで加工し、チャージは複数の金融機関が設定するという構成です。この開発のために、主に次の事柄が提示されたと仮定しました。
- 個人情報の漏洩等に対策すること
- 外部ハッカーからのサイバー攻撃に対策すること
- ウイルス対策を施すこと
- SQLインジェクション、XSS等の脆弱性に対応すること
- 不正ログイン対策をすること
- 通信路の暗号化
さらに、CentOS7、PHP5.4、MySQL5.5の使用、AWS、ウイルス対策はフリー、Tripwire(オープンソース版)、常時SSLを使うことになったとしました。
そして、オニギリペイリリースにおけるトラブルを取り上げていきました。
キャンペーンを実施したら、某筋からお叱り
PayPayを上回るキャンペーンを実施せよ!と指示が出たとき、PayPayが最大20%還元のところ最大21%ポイント還元を謳いました。しかし、景品表示法でサービスできる金額は10分の2までだったことに気づいていませんでした。最終的に指導を受けてキャンペーンの見直しを迫られ、消費者に不信感を与えてしまいました。
IDを自動発番しているのに不正ログインが多発した
不正ログインが多発しました。調べてみると、パスワードスプレー攻撃が行われていました。これはDDoS攻撃ではなく、ユーザーIDを変えながら少しずつ試すもので、発覚し辛く、検知し辛いものです。この攻撃は、2013年11月にGitHubで発生した大規模なアカウントハックが先駆的なものだと紹介しました。
そもそもの問題として、オニギリペイでは発番していたユーザーIDが連番だったこと、さらに弱いパスワードを許可していたことを挙げました。結果として、オニギリペイでは2段階認証を必須にしました。
なお、SP800-63-3という基準はパスワードの業界に衝撃を与えたと振り返り、その内容は「最小8文字とする」「複雑性を課すべきではないすべて数字でも良い」「脆弱なパスワードをはじく仕組みを導入(辞書を利用)」「質問の質問を変えさせない」「アカウントの強制パスワード変更は禁止」であることを説明しました。
2段階認証を強制しても不正ログインが止まらない
しかし2段階認証を強制しても不正ログインが止まりませんでした。これはIDとパスワードが設定された時点でセッションIDを発行していたことから、フォームの2段階認証をバイパスできたことが原因でした。直接URLを踏めば大丈夫だったという問題です。今回の発表では簡単な原因にしましたが、時間があればより難しい原因にもできたと言及していました。
ヘルプデスクが狙われる
ログインできないのに利用される問題も起こりました。実態はヘルプデスクからの不適切なパスワードリセットが行われていたことが原因でした。そもそも、本人確認をしてパスワードの再発行を行うというフローがあったのですが、攻撃者が面倒な客であることをアピールし、かつパスワードを電話で話すように強要された結果、ヘルプデスクが口頭で仮パスワードを発行したことによるものでした。
これは、ソーシャルハッキングでは良くある手法とのことです。正規のエスカレーションフローが怪しく、オペレーターが仮パスワードが見えるのもマズイ状況だと言及しました。最終的にマニュアルを見直し、運用でカバーすることになりました。なお、電話でパスワードを伝えてはならず、リセット機能のみであれば担当者がパスワードを目に触れないようにできるとも付け加えました。
スマホアプリの脆弱性を連絡される
Webサーバー側は平文で保存していませんでしたが、端末側のURLにパスワードが平文で記載されていました。これにより端末の紛失・盗難時に保護されていないと指摘を受けました。これについては「iOS KeyChane」「Android Keystore」の利用を挙げました。
iO版のオニギリペイアプリがリジェクトされる
iO版のオニギリペイアプリがリジェクトされました。その原因は、Android版バージョンアップのお知らせと記載してしまったことによるものでした。記載を直しリリースしたとのことです。
OSコマンドインジェクション
OSコマンドインジェクションがあったようです。WebShellを設置されたが、改ざん検知で個人情報漏洩には至りませんでした。原因は、ImageMagickのconvertコマンドを起動しており、エスケープ漏れがあったことに起因していました。なお、PHP7.4にて追加されたproc_openを使うことで、オプションを配列で送ることができるため、原理上コマンドインジェクションがなくなると言及しました。
WAFを導入したら、かえって脆弱になった
WAFの導入後、オープンリバースプロキシになっていたため、SSRF攻撃によってAWS IAMのクレデンシャルが漏洩してしまいました。ちょっとできすぎているんじゃ?という疑問についてはCapitalOneの漏洩事故をモデルにしているとのことで、実際にあった例であると述べていました。
対策としては、ネットワーク的にiptablesを用いて、162…を拒否することで対応でき、最近EC2も対応してきているそうです。またIMDS v2を導入するとputメソッドでトークンを取得する形に変わるため、SSRF攻撃で簡単に取得できる状況ではなくなることも言及しました。エンドポイントの機能そのものを殺す方法ももちろんあると付け加えました。
では、オニギリペイはどうすればよかったのか?
このようなトラブルに見舞われたオニギリペイですが、「サービス規格」「プラットフォーム設計」「業務設計」「機能仕様」など、多層的に対応すべきだったとのことです。これには上流から対応する必要があると指摘しました。
リスクアセスメントの方法としては、大きなところとして次の分析があります。
- ベースラインアプローチ:書いてあるとおりにやればいいだろうというアプローチ。
- 非形式的アプローチ:専門家に依頼するというアプローチ。
- 詳細リスク分析:網羅的に資産や脅威を洗い出すアプローチ。
- 組み合わせアプローチ:ベースと詳細リスク分析で補う組み合わせ。
また、セキュリティにはお金がかかるが、予算を提示するのは発注者であるとし、例えば、ビルを建てる場合どの程度の耐震性を持たせるかは発注者の責任であり、発注者がセキュリティを左右するとしました。そのためにはRFPが重要であるとし、発注者は検討できることを全部書いておくべきだと語ります。
セキュリティ要件の「モデルプラン」の例として、高木浩光氏による「地方公共団体における情報システムセキュリティ要求仕様モデルプラン(Webアプリケーション)」を紹介しました。
アジャイルで開発するときも、どこをイテレーションで実施するのか・しないのかを決めておく必要があるとし、担当者の教育などは1回で良いとか検討すると良いとしました。また、複数イテレーションの間に専門家による分析を挟むなどが良いアイデアだとしました。
いまは攻撃や分析すべきことが多様になっているため、徳丸本で対応しようと試みてきたが、専門家を呼ぶ必要がある状態になりつつあるそうです。とはいえ、できることをしようとする場合は、参考になる文書は(OWASPはやや抽象的なので)IPAが作成したIoTシステム絡みのテキストをお勧めしていました。また脆弱性テストは自動化とか、できるだけのことはツールでするの考え方を付け加えました。