2012年7月6日金曜日

PHPの入門書を書くことになりました&レビュアー募集のお知らせ

PHPの入門書をソフトバンククリエイティブさん出すことになりました。かねがね、PHPの入門書がよろしくないという問題意識を持ち、かつ色々な場でお話ししておりましたが、またしても「言い出しっぺの法則」が発動して、自分で書くことになりました。
PHPの入門書を(たぶん)10冊以上読んで(あるいは眺めて)、以下のような感触を持っています。
  • ものすごく初歩的な本は悪くないが、行き着くゴールが極めて限定される
  • SQLなどまで行き着く入門書は、後述する欠点を持つ傾向がある
  • 中級者・上級者向けについては、良いものが出て来た
PHP入門書の欠点というのは以下のようなものです。私の読んだPHP入門書は、次のいずれかに該当します。
  • 執筆者のスキルが低いために説明やサンプルの品質が低い
  • 執筆者のスキルは高いはずだが、説明のスキルが低く、不正確
  • 執筆者のスキルが高く説明も正確だが、初心者には難しく入門書でなくなってしまっている
ということから、上記の欠点のない(許容できる程度に少ない)入門書が書けないか考えました。
セキュリティについては前面に出さず、ふつーに、当然のように安全なものができあがることを目指しております。

現時点の構想は下記の通りです。変更の可能性があります。ノンプログラマ向けの本ではなく、開発者の卵向けという位置づけです。

対象読者

  • プログラマ・SE一年生でこれからPHPを学習する人
  • なにかプログラミング言語の経験があるとなお可
  • HTMLの基礎を知っていて簡単なHTMLを書けるとなお可(ただしHTMLの基礎知識は説明する)

学習環境

学習環境は以下を考えています。変更の可能性があります。
  • PC / Macに対応
  • VMware / Virtual Box ※XAMPPにするかもしれません(検討中)
  • Ubuntu + PHP + MySQL ※XAMPPにするかもしれません(検討中)
  • NetBeansによる開発・デバッグ環境
  • テストについても言及するかも
  • デプロイについても言及するかも

目標

本書のゴールは以下を考えています。変更の可能性があります。
  • 簡単なWebアプリがPHPにより作れる
  • PHPの基本をマスターする
  • 関数やクラスの使い方をマスターする
  • メールフォームが作れる
  • SQLを用いた検索フォームが作れる
  • 会員管理、認証のあるアプリケーションが作れる
  • NetBeansによるデバッグの仕方を習得する
  • より高度な技術を習得するための土台ができる
  • セキュリティ的な問題はなくす
    • ただし、あまりセキュリティの原理的なところは踏み込まず、「こうするとよい」というハウツーにとどめる
    • 要は「安全なWebアプリケーションの前に読む本」という位置づけにもなる

レビュアー募集

現状のPHP入門書に不満があるとして、自分なら十分なものが書ける根拠があるかというと、なかなか難しいと感じています。このため、今回も、レビュアーを公募して、皆様のお力をお借りしながら、少しでも良いものにしたいと希望しております。レビュアーに期待していることは以下のようなことです。
  • 初心者目線で、読んでわかりにくい箇所の指摘
  • PHPのエキスパートとしての指摘
  • 文章表現に対する指摘
  • 正確でない用語の指摘
  • 誤字・脱字・誤変換などいわゆるTYPOの指摘
  • その他、説明や構成に対するアドバイスなど
とくに初心者目線での指摘を頂ける方を募集します。自薦だけでなく、部下・教え子・後輩の推薦も歓迎します。ただし、応募はご本人からお願い致します。
レビュアーには「あの○○さん」のようなすごい方もおられますが、その中でも臆せずに「自分には分かりにくい」と言えるガッツのある人を歓迎(大歓迎)します。

当方からの謝礼としては以下を予定しています
  • 本の中での謝辞(本名またはハンドル)
  • 献本(紙の本と電子版)
  • 打ち上げへのご招待(会費は当方が負担します)
以下の条件を承諾していただけることが前提です。
  • いただいた指摘やアドバイスは真剣に検討致しますが、採用するとは限りません
  • ご意見を採用する・しない、採用後の表現は、最終的には徳丸が決定します
  • 具体的な修正案を盛り込んだ場合、著作権は徳丸に帰属します
  • 本の内容について秘密保持をしていただきます(常識的な範囲で)
人数としては、十数名程度と思っています。

レビュアーをやってみたいという方は、以下のいずれかの都合の良い方法で徳丸までご連絡ください。応募期間は、7月13日金曜日までとします。
  • phpbook @ tokumaru.org へのメール(@を半角にしてください)
  • twitter, facebookでのDM
連絡いただく内容としては、基本的には以下の内容です。
  • お名前(本名 または ハンドルネーム)
  • メールアドレス
  • 自己紹介(簡単で結構です)
  • アピール(こんな指摘がしたい and/or できる)
  • ブログなどのURL
徳丸が面識のない方については、基本的にブログなどでアウトプットを出している方から選考させていただきたいと考えています。これは、判断基準として既存のアウトプットを見させていただくという意味です。高度な内容である必要はまったくありません。逆に、既に面識がある方(twitter、facebookなども含みます)の場合は、単に「レビュアー立候補します」のみで結構です。

選考結果については、「レビュアー選考が終わり当選者の方にメールで通知しました」という形にしようと思っています。選に漏れた方は、別に「劣っている」という判断ではありませんので、恨まないでくださいね。

それでは、よろしくお願い致します。

PS.
今朝、某社のJavaScript勉強会に参加させていただきました。ツッコミどころ満載のテキストに各位がツッコムのを最初は自分も笑っていたのですが、段々顔が引きつってくるのを感じました。他人事ではありません。入門書を書くのは大変ですね。

追記(2012/7/10))

大変多くの募集をいただきありがとうございます。現時点では、「他の言語は経験があるがPHPは知らない」という方の応募をたくさんいただいております。もちろんそのような方も歓迎ですが、「他の言語も含めてプロクラムは書けない」という方を優先枠として選定させていただきたいと思っております。
プログラムが書けるようになるまでの過程では、多くの困難があると予想されますので、疑問点等については徳丸ができる限りフォローいたします。場合によっては他のレビュアーの方もフォローしてくれるかも知れません。いわば「プログラミング道場」のようなものですね。
以下の条件に当てはまる方を歓迎いたします。
  1. 現時点ではプログラムが書けない(HTMLは書けてもよい)
  2. プログラミングができるようになりたいと強く思っている
  3. 約半年掛けてプログラミングを習得する時間的猶予がある
という方の応募をお待ちしています。また、これ以外の募集についても引き続き行います。

追記(2012/7/18))

昨日選考を終わり、当選の方にはメールで連絡差し上げました。たくさんのご応募ありがとうございました。

2012年6月26日火曜日

COOKPADの「伏せ字にせず入力」ボタンは素晴らしい

@tokuhiromから教えてもらったのですが、COOKPADのスマートフォン向けWebサイトのログインページには、パスワードを「伏せ字にせず入力」するボタンがついているのですね。

さっそく見てみましょう。まずはログイン画面です。パスワード欄の下側に、「伏せ字にせず入力」ボタンが見えます。


まずはこのままでメールアドレスとパスワードを入力してみましょう。デフォルトでは、パスワードは伏せ字になりますね。


ここで「伏せ字にせず入力」のボタンを押すと、入力中のパスワードが表示されます。メールアドレスとパスワードは例ですので、まねしないように。


「元に戻す」ボタンを押すと、伏せ字に戻ります。

僕はこれを知って興奮しました。なぜなら、拙著「体系的に学ぶ 安全なWebアプリケーションの作り方」には以下のように書いたからです(P337~P338)。
パスワード入力欄のマスク表示は、現在の常識的なガイドラインですが、実は筆者自身は疑問を持っています。パスワード入力欄をマスク表示にすると、記号や大文字・小文字交じりの安全なパスワードを入力しにくくなるので、利用者は簡単な(危険な)パスワードを好むようになり、かえって安全性を阻害するリスクの方が大きいのではないかというのがその理由です。
【中略】
パスワード認証の最大の脅威は、インターネット越しの総当たり的な攻撃であり、その対抗策は良質なパスワードを設定することに尽きます。そのため、今後は「パスワードの文字を表示する」チェックボックスを備えるWebサイトが増えるかもしれませんね。ただし、ブラウザのパスワードの自動補完機能により画面表示の初期状態からパスワードが設定されている場合があるので、他人が見ている場でいきなりパスワードが表示されると困ります。このため、「パスワードの文字を表示する」チェックボックスの初期状態はオフになっていることが条件です。
こう書いたものの、同書執筆時には、現物のWebサイトの例を示すことができませんでした(良く探せばあったかもしれません)。COOKPADのスマートフォン向けサイトは、私の予言(?)を完全に満たしていますね。

パスワードの取り扱いについては、「定期的に変更するべきか」、「どう保存すればよいのか」、「入力中のパスワードは表示するべきか」という3大論争(?)がありますが、COOKPADのこの実装は、「パスワードを見せる」先駆的な取り組みと言えそうです。

もっとも、ケータイ(フィーチャーフォン)向けのサイトでは、パスワードを表示させる例は珍しくありませんでした。これは、テンキーでパスワードを入力するのが難しい機種があったからだと思います。いきおい、モバイルバンキングでもパスワード代わりに4桁暗証番号というサイトが珍しくないわけですが、これは本当に本末転倒だと思います。良質なパスワードを利用者につけてもらうことこそが第一優先であって、その次に、入力中のパスワードをのぞき見されない工夫をすべきと考えます。

というわけで、COOKPADの取り組みは素晴らしいと感じました。

追記(2012/06/26 19:10)

つい興奮して手放しの絶賛をしましたが、注意すべき点もあります。この点についてご指摘をいただきました
パスワードフィールドを伏字にしない話、理念としては頷けるのだが、現状で徳丸さんの提案に従ってサイト側で実装するのは考えものかもしれない。問題は2種類ある。ひとつはアクセシビリティ、ひとつは特定環境におけるパスワード漏洩リスクの増大。さらに実装がばらつくことによる実効性の低下も懸念される。やはりこの手の基本的な UI の改良はブラウザ側で行われることが望ましい。【後略】続きを読む
詳しくはkokuboさんのエントリをお読みいただくとして、このような試みは始まったばかりですので、本当にどう実装するのがよいのか、見落としているリスクはないのかという検討が必要だと思います。ご指摘ありがとうございました。

[PR]
安全なWebアプリケーションの作り方DRMフリーのPDFによる電子版もあります。
[PR]
7月5日インフィニテック社のセミナーで基調講演します

2012年6月19日火曜日

IPAからAndroidアプリの脆弱性に関するレポート出ました

「Androidアプリを作っている(作ってもらっている)けど、脆弱性が心配」という声はtwitterでも目にすることがあります。そして、「『安全なウェブサイトの作り方のAndroidアプリ版』があったらいいのに」という希望を目にしたこともあります。
6月13日にIPAから公表された「IPA テクニカルウォッチ『Androidアプリの脆弱性』に関するレポート」は、この『安全なウェブサイトの作り方のAndroidアプリ版』に相当する位置づけのドキュメントです。なぜそう思うかというと、以下の性格が『安全なウェブサイトの作り方』と共通するからです。
  • Androidアプリの基本的な問題に絞っている
  • 届出の多い脆弱性にフォーカスしている
以下、もう少し詳しく紹介します。

Androidアプリの脆弱性とは何か

同レポートでは、Androidアプリの脆弱性を以下のように定義しています(同書P3)。
■ 「脆弱性」
Android OSに備わっている仕組みを”Androidアプリが適切に使用していない”場合、他のアプリが所有しているデータに不正アクセスしたり、他のアプリの権限を不正に使用したりするセキュリティ上の問題が発生する。本書では、このようなセキュリティ上の問題をAndroidアプリにおける脆弱性と位置づけている。
この不正なことを誰が(何が)するかというと、不正なアプリであるわけで、これも以下のように定義されています。
■ 「不正なアプリ」
本書では、他のAndroidアプリの脆弱性を悪用し、他アプリのデータにアクセスしたり、他アプリの権限を不正に使用したりするAndroidアプリを指す。
ということで、要は、「アプリケーションが、Androidに備わっている仕組みを適切に使用していないことが原因で、不正なアプリ(マルウェア)が、アプリのデータに不正にアクセスできる、あるいはアプリの権限を不正に使用できる」状態をAndroidアプリの脆弱性として位置づけています。

では、Androidアプリには他のタイプの脆弱性はないかというと、必ずしもそうではないと思います。例えば、AndroidアプリがSQLiteを使っていて、そこにSQLインジェクション脆弱性がある場合、アプリの脆弱性ですが、「Androidの仕組みを適切に使用していない」ことが原因とは言えません。
このため、同書はAndroidアプリ「固有の」脆弱性にフォーカスして解説しているととらえればよいと思います。その結果、同書は表紙を含めても24ページと大変コンパクトにまとまっています。この薄さは読者にはありがたいですね。

■『Androidの仕組み』とは

Androidに備わっている仕組みを適切に使用しないことで脆弱性が生まれるわけですから、脆弱なAndroidアプリを作ってしまう開発者は、Androidの仕組みを正しく理解していないと推測されます。このため、同書は、2章をAndroidの仕組みの解説にあてています。その中から、「図2-1 Androidの仕組みの動作イメージ」という図を引用します。


「おいおい、これはAndroidの基本そのものではないか。そんなものは知っている」と思われた読者が多いかもしれませんが、現実に、その基本がちゃんと分かっていないために多くの脆弱性が生まれているわけで、分かっているつもりの方でも、もう一度同書でおさらいをしておくと良いのではないでしょうか。

■届出の多い脆弱性

同書の3章は、「IPAに報告されたAndroidアプリの脆弱性」ということで、IPAに届出のあったAndroidアプリの脆弱性42件のうち、31件が「アクセス制限の不備」と分析し、そのうち21件がコンポーネントのアクセス制限の不備、10件がファイルのアクセス制限の不備となっています。ということから、同書は、以下のように分析しています。
これらの設定は、Androidにおいては基本的な設定である。しかし、多くの届出があったという事実から、このAndroid特有の設定内容が開発者に周知できておらず、結果的に、アクセス制限の不備の脆弱性を作り込んでしまっているのではないかとIPAでは推測する。

■脆弱性例の紹介

同書の4章はIPAに届出のあった脆弱性の中から、典型的なものを5種類紹介しています。このような脆弱情報の現物(アプリ名などは伏せてありますが)は中々目にする機会がないので、とても貴重で興味深い内容です。以下に目次を紹介します。
4.1. ファイルのアクセス制限不備の脆弱性
(1) SD カードに機微な情報を保存
(2) ファイルが不正なアプリからアクセス可能
4.2. コンポーネントのアクセス制限不備の脆弱性
(1) 不正なアプリに機能を悪用される
(2) ファイルが不正なアプリからアクセス可能
4.3. ログ出力に関する情報漏えい
(1) 機微な情報をログに出力
4.1と4.2の両方に「(2) ファイルが不正なアプリからアクセス可能」がありますが、4.1はファイルのアクセス許可の問題に起因するもの、4.2はコンテントプロバイダの設定不備に起因する問題です。特に4.2節は、Androidの特徴がよく出ていて興味深い内容だと思います。

■まとめ

「IPA テクニカルウォッチ『Androidアプリの脆弱性』に関するレポート」について紹介しました。既にAndroidアプリの脆弱性については、「Android Security 安全なアプリケーションを作成するために」やJSSECの『Android アプリのセキュア設計・セキュアコーディングガイド』があり、いずれも素晴らしい内容だと思いますが、どちらも「分厚い」もので、Androidアプリのセキュリティ入門としては、少しとっつきにくいという人もおられたと思います。
一方、IPAの「『Androidアプリの脆弱性』に関するレポート」の方は、24ページという薄さと、基本にフォーカスして説明してあるという点で、全てのAndroidアプリ開発者およびAndroidアプリを発注する立場の方に読んでいただきたい内容です。

なお、徳丸はIPA非常勤職員として同書のレビューに参加いたしました。しかし、このエントリは個人の見解として書いているものであり、IPAとしての見解ではありません。

2012年6月14日木曜日

さくらDNSにサブドメインハイジャックを許す脆弱性

さくらインターネット株式会社のDNSサービスにセキュリティ上の問題がありましたが、改修されましたので報告します。
DNSサービスへのドメイン登録時における不具合について 
障害内容 :
当社の提供するネームサーバサービスにおいて、既に登録されているドメインのサブドメインが、他の会員IDの方に登録できる状態となっておりました。この障害により、悪意のある第三者がドメインの一部を乗っとれる脆弱性につながる危険性がありました。
本問題につきましては現在は解消されており、全ての登録について不正がないかの調査を行っております。
この問題の発見者は前野年紀氏で、私はさくらインターネット株式会社に問題を通告し、改修を促すための連絡などでお手伝いをしました。
(12:00追記)なお、この脆弱性が混入したのは6月8日頃で、さくらインターネットは6月11日から修正を開始し、昨日(6月13日)には改修されましたので迅速な対応であったと考えます(追記終わり)。

問題の概要

さくらのレンタルDNSサーバーにおいて、他人(ドメイン名の保有者でない人)が勝手にサブドメインを登録できることが問題でした。 たとえば、架空の会社エグザンプル株式会社がホームページwww.example.jpを運営しており、ドメイン名example.jpをさくらDNSで運用しているとします。この状況で、第三者がexample.jpのサブドメインwww2.example.jpのゾーンを追加し、www2.example.jpのAレコード(IPアドレスの指定)を登録できました。この結果、第三者がwww2.example.jpというサイトを公開できることになります。

勝手にDNSサーバーを立てて他人のサブドメインを登録できることは問題ない

ここからは、問題点を説明するために、本来できてよいこと、できてはまずいことを順に説明します。 まず、第三者が独自のDNSサーバーを立てて、そこに勝手に別人のドメイン名を登録することはできてしまいます。私が運営するDNSサーバーに、google.comやamazon.comやapple.comなどを勝手に設定することできるし、問題にもならないということです。
それが問題にならない理由は、この勝手なDNSサーバーは上位DNSサーバーからgoogle.comなどのドメイン名を委譲されていないので、どこからも参照されないからです。

権威サーバーと同じサーバー上に、他人がサブドメインを登録できることが問題

次に、話を進めるために、以下のシナリオを考えます。
私がもつドメイン名 tokumaru.org の適当な預け先がなく、知り合いのいるエグザンプル株式会社に「御社のDNSサーバーを貸して下さい。そして、tokumaru.orgを設定させて下さい」と頼んだとします。この設定自体は問題がなく、交渉次第では貸してくれるでしょう。
ところが、私が悪い奴で、tokumaru.orgを追加するついでに、www2.example.jpのゾーンも追加したとします。example.jpのゾーンはいじれないので、www2.example.jpは、example.jpから委譲されてはいません。しかし、example.jpとwww2.example.jpは同じDNSサーバー上にあるので、外部からwww2.example.jpを問い合わせると、このDNSサーバーに登録された内容を応答してしまいます。これが問題です。
すなわち、さくらDNSの問題は、「ちょっとDNSサーバー貸して下さい」と頼みながら、そのDNSサーバーに元々設定されているドメイン名のサブドメインが登録できてしまう(チェックされない)ことが問題です。

実験

これだけだと分かりにくいと思うので、実験をしました。 私は元々tokumaru.orgをさくらDNSで運用していました。その状態で、前野年紀氏が徳丸の許可の元、私とは別アカウントでサブドメインqmail.tokumaru.orgの登録を試み、成功しました(この設定は現在はできません)。本稿執筆時点で、qmail.tokumaru.orgは参照可能です。


このドメイン名を外部から問い合わせると以下のような流れになります。

# ネット利用者が qmail.tokumaru.org にアクセスしようとする
# ブラウザがDNSキャッシュサーバーに qmail.tokumaru.org を問い合わせる
# DNSキャッシュサーバーはルートDNSサーバーに qmail.tokumaru.org を問い合わせる

$ dig +norecurse qmail.tokumaru.org @198.41.0.4
;; AUTHORITY SECTION:
org.                    172800  IN      NS      a0.org.afilias-nst.info.
;; ADDITIONAL SECTION:
a0.org.afilias-nst.info. 172800 IN      A       199.19.56.1

# ルートDNSサーバーは、qmail.tokumaru.org は知らないけど
# orgドメインの権威サーバーなら知っているよと、a0.org.afilias-nst.info などを返す
# DNSキャッシュサーバーは、a0.org.afilias-nst.infoにqmail.tokumaru.orgを問い合わせる

$ dig +norecurse qmail.tokumaru.org @199.19.56.1
;; AUTHORITY SECTION:
tokumaru.org.           86400   IN      NS      ns1.dns.ne.jp.

# a0.org.afilias-nst.infoは、tokumaru.orgの権威サーバーはns1.dns.ne.jp(さくらDNS)だよと返す
# DNSキャッシュサーバーはns1.dns.ne.jpのIPアドレスを知らないので、あらためてルートDNSサーバーにns1.dns.ne.jpを問い合わせる

$ dig +norecurse ns1.dns.ne.jp @198.41.0.4
;; AUTHORITY SECTION:
jp.                     172800  IN      NS      a.dns.jp.
;; ADDITIONAL SECTION:
a.dns.jp.               172800  IN      A       203.119.1.1

# ルートDNSサーバーは、jpドメインの権威サーバーがa.dns.jpなどであると返す
# DNSキャッシュサーバーは、ns1.dns.ne.jpをa.dns.jpに問い合わせる

$ dig +norecurse ns1.dns.ne.jp @203.119.1.1
;; AUTHORITY SECTION:
dns.ne.jp.              86400   IN      NS      ns1.dns.ne.jp.
;; ADDITIONAL SECTION:
ns1.dns.ne.jp.          86400   IN      A       210.188.224.9

# ns1.dns.ne.jpのIPアドレスが返ってくる
# DNSキャッシュサーバーは、ns1.dns.ne.jpにqmail.tokumaru.orgを問い合わせる

$ dig +norecurse qmail.tokumaru.org @210.188.224.9
;; ANSWER SECTION:
qmail.tokumaru.org.     3600    IN      A       14.192.44.5

# ns1.dns.ne.jpは、(前野氏が設定した)qmail.tokumaru.orgのIPアドレスを返す
tokumaru.orgの権威サーバーをさくらDNS(ns1.dns.ne.jp)に設定したのは徳丸ですが、その状態で前野氏が、さくらDNSにqmail.tokumaru.orgゾーンを勝手に(実際には徳丸の承認の元)設定したために、結果として qmail.tokumaru.orgを前野氏が有効に設定できたことになります。

影響

この問題の直接の影響は、サブドメインのゾーンを勝手に登録され、AレコードやMXレコードなどを自由に登録されてしまうことですが、その結果として、以下のような影響が考えられます。

自ドメインでのクッキーを勝手にセットさせられる
先ほどのqmail.tokumaru.org上のコンテンツで、やろうと思えば、domain=tokumaru.orgのクッキーをセットすることができます。通常、クッキーは第三者から勝手にセットされることはないので、アプリケーションのクッキー利用方法によっては影響を受ける場合があります。
具体的には、以下の場合に影響を受けます。
  • セッション・フィクセイション脆弱性がある場合
  • クッキーに意味のある文字列を入れている場合
いずれも好まし良くない実装ですが、クッキーを勝手に改変されることはないという想定に依存しているアプリケーションは、潜在的な問題が顕在化します。

フィッシングに悪用される
攻撃者が勝手にwww2.example.jpを設定して独自のコンテンツを作成した場合、フィッシングサイトに悪用することが考えられます。多くのフィッシングサイトは、あきらかに不自然なURL上にあるので、そこが見分けるポイントの1つになりますが、本物のドメイン名のサブドメイン上にフィッシングサイトがあると、だまされる人が増えると考えられます。

成りすましメールアドレスに悪用される
メールアドレスのドメイン名として、mx.example.jpやmail.example.jpなどのサブドメインを使っている企業は珍しくありません。このため、mx.example.jpを勝手に登録して、このドメインのメールアドレスから、偽のメールを出すという悪用が考えられます。やはり本物のドメイン名を使っていることから、「メールアドレスは今後 xxx@mx.exmaple.jpになります」と書いてあれば、だまされる人はかなり多いと予想されます。
通常、送信元のアドレスを偽装することは容易ですが、その場合返信を受け取ることはできません。しかし、サブドメインを悪用すると、返信メールを受け取ることができるので、秘密情報の聞き出しなどにも悪用可能です。

まとめ

さくらDNSの「サブドメインハイジャック」の脆弱性について報告しました。
ドメイン名はインターネットの信頼の基幹となるサービスですので、サブドメインといえども乗っ取られることは極めて危険と考えられます。私自身、さくらDNSの利用者でしたので、他人事ではありません。とりあえず、さくらDNSで運用していたhash-c.co.jpドメインは引っ越しました。tokumaru.orgも時期を見て引っ越そうと思っていますが、この記事のサンプルになっているのでとりあえずそのままにしています。
Webサイトを運営する個人や中小企業にとって、安全なDNSサーバーの確保は頭の痛い問題です。さくらDNSに引っ越す前は、お名前.comのレンタルDNSを使っていましたが、以前長時間サービス停止するというトラブルがあり、私も被害にあいました。
さくら以外のレンタルDNSサーバーを利用している方は、サービス提供元に対して、この種の問題がないか確認するとよいでしょう。

2012年5月7日月曜日

CGI版PHPにリモートからスクリプト実行を許す脆弱性(CVE-2012-1823)

CGI環境でPHPを動作させているサイトには、リモートからスクリプト実行を許してしまう脆弱性があります。php.netから提供されている修正リリース(PHP 5.3.12 / PHP 5.4.2)は不完全なため、該当するサイトは至急回避策を導入することを推奨します。

概要

CGIの仕様として、クエリ文字列に等号を含めない場合は、クエリ文字列がCGIスクリプトのコマンドライン引数として指定されます。
例えば、http://example.jp/test.cgi?foo+bar+bazという呼び出しに対しては、test.cgiは以下のコマンドラインで呼び出されます。
test.cgi foo bar baz
この仕様を悪用して、CGI版のPHPにコマンドライン引数としてPHPのオプションを指定できます。例えば、http://example.jp/test.php?-s というリクエストは、-sオプション(スクリプトソースを表示)と解釈され、PHPスクリプトを実行する代わりに、ソースを表示します(下図)。


これはPHPの脆弱性CVE-2012-1823と識別されています。

実証例

CVE-2012-1823の影響はスクリプトソースの表示だけではありません。PHPのオプションを組み合わせることにより、外部から任意のスクリプト実行が可能となります。具体的には、-dオプションを用いて、php.iniのディレクティブを外部から指定できます。metasploitminute.comで紹介されていたExploitを元に、攻撃例を紹介します。以下の2つのphp.iniディレクティブを指定します。
allow_url_include=On
auto_prepend_file=php://input
最初のディレクティブは、includeするファイルをURL指定でリモートから読み出すことを許可するものです。2番目のディレクティブは、PHP実行に先立ち、スクリプトをincludeしておくものですが、ファイル名としてphp://inputを指定しているため、POSTパラメータとして送信した内容をPHPスクリプトとして実行します。両者の組み合わせにより、外部から指定したスクリプトを実行することができます。
BurpSuiteのrepeater機能を用いて上記Exploitを実行した例を以下に示します。


readfile('/etc/passwd');により、/etc/passwdファイルが表示されています。また、X-Powered-Byヘッダから分かるように、上記はPHP5.4.2で実行されており、改修が不完全であることが分かります。

影響

外部からスクリプト実行が可能であることから、機密性・完全性・可用性の全てで大きな影響があります。影響を受けるサイト(下記)は至急の対策を推奨します。

影響を受けるサイト

当脆弱性の影響は、PHPをCGIとして実行しているサイトに限られます。
ApacheモジュールやFastCGIとしてPHPを実行しているサイトには影響ありません。

回避策

当脆弱性の対策としては、ApacheモジュールまたはFastCGIへの移行を推奨します。

どうしてもCGIのままにしなければならない場合は、php-cgiを呼び出すラッパー(/cgi-bin/php-wrapper)を以下のように記述します。実行権限を付与してください。php-cgiにはコマンドライン引数を渡さないところがポイントです。
#!/bin/sh
exec /usr/local/bin/php-cgi
PHPの設定を以下のように変更します。/cgi-bin/ディレクトリにphp-cgi(CGI版PHP)がコピーしてある場合は削除してください。
AddHandler application/x-httpd-php5 .php
Action application/x-httpd-php5 /cgi-bin/php-wrapper
すると、php-cgiにパラメータが渡されなくなることから、CVE-2012-1823の影響を回避することができます。php-cgiにコマンドライン引数を渡さなくてもPHPの実行に支障ありません。

参考


注記

当脆弱性は極めて影響が大きい反面、影響を受けるサイトは限られます。
当脆弱性が判明した時期が、日本の連休中にあたっていたため、対策に必要な最低限の情報のみ提供しておりましたが、海外では攻撃のための情報が流通し始めており、かつ日本での連休が明けたことから、詳細情報を公開しました。

[PR]HASHコンサルティングが提供するセキュリティ情報メールマガジン(無料)

2012年4月16日月曜日

情報処理試験問題に学ぶJavaScriptのXSS対策

平成24年度春期の情報処理技術者試験の問題と解答(一部)が公開されていますね。情報セキュリティスペシャリスト試験(SC)の午後Ⅰ(全4問中2問を選択)では、問1と問2がWebアプリケーションに関する問題でした。このエントリでは問1について書きます。

問1は、インターネット通販A社のサイトで脆弱性検査を実施したところ、指摘事項2点が報告されたところから始まります。

指摘事項A:画面の遷移の中で、暗号化通信と非暗号化通信が混在しているが、暗号化通信でだけ使用されるべきクッキーに、(   a   )属性が設定されていないページが存在する。
指摘事項B:任意のスクリプトが実行可能であるページが存在する。

指摘事項A中の(a)は、他を見なくても「セキュア」属性だと分かりますね。徳丸本(体系的に学ぶ 安全なWebアプリケーションの作り方)では、4.8.2クッキーのセキュア属性不備(P209)に説明があります。

指摘事項Bは、ここだけ読むと、XSSのようでもあり、サーバーサイドのスクリプトインジェクションのようでもありますが、検査ログからXSSであることがわかります(下図はIPAからの引用)。XSSは、徳丸本4.3.1クロスサイトスクリプティング(基本編)と4.3.2クロスサイトスクリプティング(発展編)にて説明しています。


ここまでは、ごく基本的な問題ですが、問題文P6に出てくる以下の部分は、少しだけひねってますね。
このプログラムは、利用者が入力した文字列をダイアログに表示するために、受け取ったパラメタの値をスクリプトに埋め込み、動的にスクリプトを生成する。図4の(   c    )行目では、通常のHTMLにパラメタの値を埋め込むときと同じ方法でエスケープ処理を行っていたことから、生成されるスクリプトに問題が生じてしまうことが分かった。
JavaScriptの文字列リテラルにパラメータを埋め込んでいる箇所を探すと、37行目であることが分かります。
37:  out.println("<a name=\"#\" onclick= \"alert('" + escape(word) + "')\">");
これは、徳丸本では、◆イベントハンドラのXSS(P109)に説明がある内容です。
イベントハンドラのJavaScript文字列リテラルの中味を動的生成する場合は、徳丸本P110に説明するように、二段階でエスケープしなければなりません。

①まず、データをJavaScript文字列リテラルとしてエスケープする
②この結果HTMLエスケープする

情報処理試験の問題文もそうなっていますが、問題はエスケープする文字です。徳丸本では、最低限エスケープが必要な文字として以下の4種を挙げています。


これに対して、情報処理試験の問題文では、エスケープすべき文字を2種類に限定しています。従って、上記4文字から2文字を除外する必要があります。
まず除外できるのがダブルクォート「"」です。JavaScriptの文字列リテラルは、シングルクォートでもダブルクォートでも囲むことができるので、両方の場合に対応する前提では、両方の引用符をエスケープする必要があります。しかし、この問題では、シングルクォートで文字列を囲っていることが分かっているので、ダブルクォートの方は、エスケープ対象から除外することができます。
残り3文字のうち、シングルクォート「'」とバックスラッシュ「\」はエスケープしないとXSS脆弱性となるので、この2文字が解答でしょうね。

なお、バックスラッシュのエスケープを怠ると、以下の文字列で攻撃が可能です。
\');alert("XSS");//
この場合、シングルクォートのみがエスケープされると、生成されるJavaScriptは下記となります。
alert('\\');alert("XSS");//')
攻撃文字列先頭の「\」と、シングルクォートのエスケープの「\」があわせて「\」一文字と解釈され、後続のシングルクォートがエスケープされない状態で余ります。このため、文字列リテラルが終端され、その後ろはJavaScriptのコマンドとして解釈されます。すなわち、スクリプトのインジェクションができたことになります。

一方、改行については、エスケープしなくても上記のような攻撃には至りませんが、JavaScriptのエラーにはなります。また、JavaScriptの文字列リテラルの引用符をシングルクォートで統一しているプロジェクトはマレだと思われるので、徳丸本の基準に従うのが実務上はよいと思います。あくまで、テストとして、エスケープの原理を理解していることを問う問題と考えるべきでしょう。

twitter等でたまに「情報処理試験対策のために徳丸本読んでる」等のツイートを見かけることがありますが、私は「試験対策になるのだろうか」と思っておりました。この問題を見る限り、情報セキュリティスペシャリスト試験(SC)の対策になる場合もありそうですね。但し、今回引用していませんが、実際に攻撃があったかどうかをログから判定する問題など、徳丸本の知識だけでは解答出来ないものも当然あります。

追記(2012/04/30)

水無月ばけらさんから指摘がありました。「平成24年度春期情報セキュリティスペシャリスト試験のXSS問題
  • 「このコードに限定した話」という仮定を置かない場合、escape2は単引用符、バックスラッシュ、改行に加え、二重引用符などもエスケープする必要があるかもしれない。
  • 「このコードに限定した話」と仮定し、かつ「不具合なく動作する」ことを想定した場合、escape2は単引用符、バックスラッシュ、改行をエスケープする必要がある。
  • 「このコードに限定した話」かつ「攻撃さえ防げれば良く、不具合があっても良い」と想定した場合、escape2は少なくとも単引用符をエスケープする必要がある。
    • 単引用符を「\'」にエスケープすれば、バックスラッシュのエスケープも必須になる
    • 単引用符を「\u0027」にエスケープすれば、バックスラッシュのエスケープは必要ないかもしれない (見落としがある? 突破できる?)
たしかにそうですね。
ということは、上記に指摘した解以外に、複数の解が正答になってしまうということで、問題としてはよろしくない、ということになります。この問題については全員を正解とするか、理論的に正答と見なせる解(何種類かありそうですが)を全て正答にする、という対処が必要になりそうです。IPAとしてはどうするのでしょうか。

追記(2012/06/08)

IPAから正答が公開されました。これを読むと、設問3(2)はやはりシングルクォートとバックスラッシュのエスケープを想定正解としていますね。\u0027にエスケープするとした人はいなかったのでしょうか。

[PR]
WAF始めました。詳しくはHASHコンサルティング株式会社まで。
安全なWebアプリケーションの作り方DRMフリーのPDFによる電子版もあります。

2012年4月11日水曜日

「クロスサイトスクリプティング対策」でGoogle検索して上位15記事を検証した

昨年の11月にブログエントリ『「SQLインジェクション対策」でGoogle検索して上位15記事を検証した』という記事を書いたところ、非常に好評で、「次はXSSについて書いてください」という要望をいただいておりました。中々XSSについては手がついておりませんでしたが、ようやく書いてみました。以下のURLで検索した結果の上位15位の記事を検証しました。
検索結果は変動するため、私が検索した際の結果をEvernoteの公開ノートとして記録しています。
記事の「正しさ」の検証基準としては、IPAの「安全なウェブサイトの作り方改訂第5版」を参考に、最低限として以下が記述されているかどうかを確認しました。
  • HTMLのエスケープ処理を行う
  • 属性値はダブルクォートで囲む
  • レスポンスヘッダのContent-Typeフィールドに文字コード(charset)の指定を行う
それでは始めます。

1位 クロスサイトスクリプティング対策の基本(前編)

Webアプリケーションセキュリティの大御所、国分裕さんの記事です。2002年11月なので約10年前の記事ですね。当時としては素晴らしい内容ですが、サニタイジングという用語の使い方など、さすがに現在初心者が読むにはふさわしくないでしょう。また、レスポンスヘッダに文字コード(文字エンコーディング)を指定するという説明はありません。
さらに、この記事では、現在ではHTTPヘッダインジェクション、あるいはHTTPレスポンス分割などと呼ばれる攻撃手法もXSSの一種として説明しています。当時は、HTTPヘッダインジェクションの解説はほとんどなかったので貴重な内容だったと思いますが、現在はXSSとHTTPヘッダインジェクションは別の脆弱性として分類することが一般的だと思います。

2位 クロスサイトスクリプティング

Wikipediaの解説です。
概ね正しい内容ですが、辞書的な書き方で、初心者が参考にするには読みにくい内容です。ここでも、文字エンコーディングについての言及はありません。

3位 第5回 クロスサイト・スクリプティング対策も忘れずに

徳丸の記事です。
この記事は、SQLインジェクションの改ざん対策の補助的な対策として書かれた内容ですので、XSS対策単体として読むと不十分な内容です。

4位 [1-2.]クロスサイトスクリプティング

セキュアプログラミング講座(旧版)の記事です。旧版の方が検索結果の上位にくるのですね。
内容は概ね正確ですが、「サニタイジング」という用語の使い方など、古さを感じます。さらに、文字エンコーディングの指定についても言及がありません。
古い記事を敢えて読む理由はないでしょう。

5位 クロスサイトスクリプティングの対策について|OKWave

OKWaveでのQ&Aの記事です。2002年の内容で、回答者は国分さんの記事(#1)を参照しています。この例に限らず、質問サイトのやりとは検索結果の上位にくることが多いようですが、必ずしも正確な回答でないので、参照する人は注意が必要です。
この記事も、現時点で参考にする必要はないでしょう。

6位 第8回 クロスサイトスクリプティング対策の落とし穴

大垣さんの記事です。「落とし穴」とあるように、基本的な対策を説明したものではありません。
また、細部を確認してみると、ミスが目立ちます。

(1)ereg_replaceの使い方の間違い
ereg_replaceの引数の順番が違います。

誤: $safe_text = ereg_replace($_GET['text'], '[<>]', '');
正: $safe_text = ereg_replace('[<>]', '', $_GET['text']);

(2)悪い例の選択が良くない
「しかし,javascript文字列がなくてもブラウザがJavaScriptと認識してしまうケースは多数あります。」と指摘した上で、「javascript以外でJavaScriptと認識する文字列」を説明していますが、元の例がonmouseoverイベントでの説明ですので、javascript:はそもそも不要です(後の方で説明されています)。javascript:スキームの例を示すのであれば、onmouseoverイベントではなく、a要素のhref属性に突っ込む例を示すべきでしょう。

(3)typo
また、以下のonmouseorverはonmouseoverのtypoでしょう。
<b onmouseorver="alert('XSS')">XSS</b>
また、読者は、「どうやってb要素にonmouseover属性を突っ込む攻撃ができるんだろう?」と悩んでしまいそうです。通常あり得ないシナリオで説明すると、余計なところで読者に負担を掛けます。

ということで、元々初心者向きでないことと、記事のクォリティが低いという問題があります。

7位 PHP と Web アプリケーションのセキュリティについてのメモ

小邨孝明さんの記事です。小邨さんは徳丸本のレビュアーのお一人で、同書執筆時にずいぶんとお世話になりました。
この記事は、PHPアプリケーションのセキュリティに関わるものにとっては必読です。特に、PHP固有の問題については、他の記事からは得られない貴重な内容が書かれています。XSSについても必要な内容がコンパクトにまとめられています。
また、小邨さんのブログもPHPのセキュリティの重要な情報源です。関係者は過去記事を一通り読んでおきましょう。

8位 配列データを一気にクロスサイトスクリプティング対策する関数(php)

入力データをあらかじめHTMLエスケープしてしまう関数が紹介されていますが、このような方法は現在では否定されています。
その理由は、プログラムの内部でHTMLエスケープ済みのデータを扱うことになり、生データが必要な場合に、一々アンエスケープしなければならず、却って煩雑になるからです。結果として、多重エスケープの問題が生じたり、エスケープもれ(すなわちXSS)が生じる原因になります。

しかしながら、PHPではこのような好ましくない書き方がかなり普及してしまっているような気がします。私がそう思う根拠は、PHPには、htmlspecialchars関数の第4引数(double_encode: 二重エスケープをしない指定)やhtmlspecialchars_ decode関数(アンエスケープ用関数)が用意されていることです。表示の際にHTMLエスケープするという標準的な書き方をする限り、これらの機能は必要ありませんし、PHP以外の言語では見かけない機能です。

あらかじめHTMLエスケープしておくという書き方は、PHPのマジッククオートと似た考え方と言えます。ご存じの通り、マジッククォートとは主にSQLインジェクション対策として、あらかじめ入力値のシングルクォートやバックスラッシュをエスケープしておくものですが、SQLインジェクション対策としては不完全である上に、多重エスケープなど副作用が大きく、PHP5.4では廃止されました。

ということで、無精をせずに、必要な都度HTMLエスケープするようにしましょう。あるいは、表示の際に自動的にHTMLエスケープしてくれるフレームワークを使いましょう。

9位 クロスサイトスクリプティング対策としてやるべき5つのこと

いかにもなタイトルですが、「5つのこと」として以下が推奨されいます。
  1. <>"&は文字参照にする
  2. Javascriptに動的に文字列を渡す時はURLエンコードする
  3. hrefやsrcの値がURLか確認する
  4. php.iniでsession.cookie_httponly=on
  5. httpd.confでTraceEnable Off
「属性値をダブルクォートで囲む」ことと「HTTPレスポンスヘッダに文字エンコーディングを指定する」が抜けています。とくに前者は致命的です。
また、上記2の「URLエンコード」という見出しは間違いのように見えますが、本文で説明されている内容はURLエンコード(%xxという形式)ではなく、Unicodeエスケープ(\uXXXXという形式)です。すなわち本文の方は正しいのですが、見出しでの用語の間違いはまずいです。

ということで、不正確な内容です。

10位 クロスサイトスクリプティングとは【XSS】 - 意味/解説/説明/定義 : IT用語辞典

用語辞典の解説です。
対策としては、訪問者からの入力内容をそのまま表示せずに、スクリプトなどのコードを識別して無効化する処理を施すことが必要である。
これはダメですね。「入力内容」、「スクリプトなどのコードを識別」は余計であり、誤解を招きます。

11位 クロスサイト スクリプティング フィルター

IEのXSSフィルタの説明であり、アプリケーション側の対策の話ではありません。

12位 クロスサイトスクリプティングとは

対策としては以下の3つが挙げられています。
  • 入力データのチェック
  • クッキーに重要な情報を保存しない
  • デフォルトでエスケープするテンプレートを使う
肝心のHTMLエスケープの説明がないので、XSS対策の説明としては不十分です。

13位 間違ったクロスサイトスクリプティング(XSS)対策 - YouTube

LACの川口洋さんによるビデオ解説です。1分程の短いプレゼンです。特別目新しい内容ではありませんが、面白く見ることができます。
あくまで、間違った例に対する説明であり、対する正しい方法が説明されているわけではありません。

14位 そのやり方でクロスサイトスクリプティング対策は完全ですか?

WAFの宣伝です。以下のように、まずXSS対策のプログラミングの難しさが説明されます。
クロスサイトスクリプティングは【略】一般的には「プログラマが、入力フォームを作る時にJavaScriptなどのコードを別な文字に置換するなどの対応を行うべき」と考えられています。
しかしながら、掲示板のような簡単なプログラムならいざ知らず、昨今のWebシステムは数百、数千のプログラムから構成されることが普通ですから、こうしたシステムで 全てをプログラマの努力に頼ることは難しいだろうという認識も生まれています。
これはまぁいい。「難しい」のは事実ですから。しかし、以下はどうでしょうか。
リリース後のアプリケーションにたった1箇所の問題があっただけで、それまでの検査コストがすべて無駄になる
「すべて無駄になる」はあんまりでしょう。
そこで、視点を変えてみましょう。もし、アプリケーションに対する攻撃をネットワークで防ぐことができたらどうでしょうか?
  • アプリケーションの追加リリースの度に検査する必要がなくなりますので、将来の追加コストを抑えることができます
  • 脆弱性検査などでも発見できない、未知の攻撃も防御することができます
  • セキュリティ試験などの工数を削減でき、システム開発にかかる費用の削減が期待できます
そんな理想的な話があるのでしょうか?

実は、Citrix NetScalerを使えばWebアプリケーションに対する攻撃をネットワークレベルで防ぐことができるのです!
これは酷い。何が酷いかというと、プログラマのプログラミングレベルの対処や脆弱性検査が「すべて無駄」で、WAFを導入すればWebアプリケーションに対する攻撃を防げるとしていること、「WAFを導入しさえすれば全てOK」と明示的には書いていないものの、読者がそういう印象を持つように誘導していることです。
実際には、WAFが全ての攻撃を防げるわけではなく、あくまで保険的対策です。上記の記事では、主・客が逆になるような、間違った印象を読者に与えてしまいます。

15位 CWE-79

CWE(Common Weakness Enumeration)の翻訳記事からXSSの解説です。CWEについては、IPAの解説記事から引用します。
共通脆弱性タイプ一覧CWE(Common Weakness Enumeration)は、ソフトウェアにおけるセキュリティ上の弱点(脆弱性)の種類を識別するための共通の基準を目指しています。
1999年頃から米国政府の支援を受けた非営利団体のMITREが中心となり仕様策定が行われ、2006年3月に最初の原案が公開されました。その後、40を超えるベンダーや研究機関が協力して仕様改善や内容拡充が行われ、2008年9月9日にCWEバージョン1.0が公開されました。
CWEでは、SQLインジェクション、クロスサイト・スクリプティング、バッファオーバーフローなど、多種多様にわたるソフトウェアの脆弱性を識別するための、脆弱性の種類(脆弱性タイプ)の一覧を体系化して提供しています。 
CWEは、脆弱性のハンドリングをする専門家は知っておく必要があるでしょうが、一般のWeb開発者は知らなくていいんじゃないかと思います。
XSSの説明ですが、なんか仰々しい感じで小難しいですね。例えば、以下のような箇所。
ソフトウェアにおいて信頼できない入力を受け付ける箇所を全て把握してください。
なんか、一昔前のセキュアプログラミングの教科書風です。XSS対策をする上では、入力に着目するのではなく、表示の箇所で淡々とエスケープ処理をすればよいわけで、入力の信頼できる・出来ないを分類する必要などありません。そんなことをすると、かえって対処もれ、ひいては脆弱性の原因になります。表示箇所で全てエスケープと考えた方が漏れがありません。

とりあえずのまとめ

「クロスサイトスクリプティング対策」でGoogle検索して上位15記事を検証しました。SQLインジェクションの時以上に、検索上位には良い記事が少ない状況です。上位15位の中で、開発者が読むべきXSS対策の記事は小邨さんの解説くらいでしょう。
脆弱性対処の方法をGoogleなどの検索サイトに頼るのは、賢明とは言えないというのが私の感想です。

XSS対策はどうすればよいか

それでは、XSS対策についてはどうすればよいでしょうか。
あらためて思いましたが、IPAの「安全なウェブサイトの作りかた」が脆弱性対処の規範と言えます。全てのWebアプリケーション開発者が安全なウェブサイトの作り方を学ぶべきだ思います。同書のチェックリストから、XSSの項目を引用します。

脆弱性の種類 対策の性質 実施項目
HTMLテキストの入力を許可しない場合の対策 根本的解決 ウェブページに出力する全ての要素に対して、エスケープ処理を施す。
根本的解決 URLを出力するときは、「http://」や 「https://」で始まるURLのみを許可する。
根本的解決 <script>...</script> 要素の内容を動的に生成しない。
根本的解決 スタイルシートを任意のサイトから取り込めるようにしない。
保険的対策 入力値の内容チェックを行う。
HTMLテキストの入力を許可する場合の対策 根本的解決 入力されたHTMLテキストから構文解析木を作成し、スクリプトを含まない必要な要素のみを抽出する。
保険的対策 入力されたHTMLテキストから、スクリプトに該当する文字列を排除する。
全てのウェブアプリケーションに共通の対策 根本的解決 HTTPレスポンスヘッダのContent-Typeフィールドに文字コード(charset)の指定を行う。
保険的対策 Cookie情報の漏えい対策として、発行するCookieにHttpOnly属性を加え、TRACEメソッドを無効化する。

上記に書いてない内容としては、IEのContent-Type無視問題くらいです。これも本来ブラウザ側の問題だとは思いますが、IEのシェアを考えると無視できない問題でしょう。以下を参照して下さい。
拙著「体系的に学ぶ 安全なWebアプリケーションの作り方」を読んでいただけば、上記のことは全て具体的に解説しています(PR)。

また、AjaxアプリケーションのXSSについては、基本はHTMLのエスケープとContent-Type無視問題への対処ですが、具体的には以下の記事をお読み下さい。
このAjaxアプリケーションのXSSについては、PHPカンファレンス北海道にて解説する予定です。


[PR]
WAF始めました。詳しくはHASHコンサルティング株式会社まで。
安全なWebアプリケーションの作り方DRMフリーのPDFによる電子版もあります。

読者