「EximのGHOST脆弱性の影響とバリデーションの関係」への疑問

徳丸さんが日記で以下の記事を公表されました。

いつも緻密な記事を書かれる徳丸さんですが、この記事には少々疑問が残りましたので、疑問点をあげておきたいと思います。

誤りなどありましたら、どなたでも根拠とともにご指摘ください。

(2015-02-05 追記) 大垣さんは自身のブログで以下のようにコメントされていました。

徳丸さんは私がIPアドレスと書いたので間違っているかのような書き方をしていましたが、RFCで明確にドメイン名形式またはIPアドレス形式と書いており、gethostbynameもこの仕様にそった実装になっているのでドメイン名形式とIPアドレス形式を明確に区別することにあまり意味はありません。
http://blog.ohgaki.net/how-to-validate-ipv4-host-names

疑問点

まず、この記事の核となる主張に以下があります。

攻撃経路となる入力値はIPアドレスではなくホスト名である

そして、大垣さんが「これをIPv4形式のIPアドレスと誤認」しているが「これは間違い」と断定しています。

果たしてこのように単純に間違いと言いきれるのでしょうか?以下の疑問が生じました。

本当に攻撃経路となる入力値はIPアドレスではなくホスト名と言えるのか?

以下に理由を述べます。

(1) gethostbyname()はIPアドレスも受け取る

記事では、

gethostbyname()が受け取る引数もbynameとあるようにホスト名

と説明されています。確かにgethostbyname()はホスト名から情報を取得するものですが、ホスト名以外にもIPアドレスを受け取ることも想定されています。manページには「ドット区切りのIPv4アドレス」も明記されています。

gethostbyname() 関数は与えられたホスト名 name に対応する構造体 hostent を返す。 name にはホスト名、ドット区切りの IPv4 アドレス (inet_addr(3) 参照)、コロン区切りの IPv6 アドレス (おそらくドット区切りでも大丈夫) のいずれかを指定する (IPv6 アドレスの記述方法については RFC 1884 を参考にしてほしい)。name が IPv4 か IPv6 のアドレスだった場合、 名前解決 (lookup) は行われない。
http://linuxjm.sourceforge.jp/html/LDP_man-pages/man3/gethostbyname.3.html

(2) SMTPのHELOコマンドもIPアドレスを受け取る

こちらもホスト名でなくIPアドレスが入力される場合があります。ただし、SMTPの仕様ではIPアドレスの場合、[ ]で囲む必要があります(アドレスリテラル)が。

EHLO コマンド内で与えられるドメイン名は、主要なホスト名(アドレス RR を決定するドメイン名)か、ホストが名前を持たない場合にはアドレスリテラル(セクション 4.1.3 で説明され、セクション 4.1.4 の EHLO の考察においてさらに議論されている)か、どちらかでなければならない(MUST)。
http://srgia.com/docs/rfc5321j.html#p2.3.5

(3) そもそもホスト名にはIPアドレスも入力できる

RFC1123によれば、

Whenever a user inputs the identity of an Internet host, it SHOULD be possible to enter either (1) a host domain name or (2) an IP address in dotted-decimal ("#.#.#.#") form. The host SHOULD check the string syntactically for a dotted-decimal number before looking it up in the Domain Name System.

参考訳:

ユーザがインターネットホストの身元を入力する場合は常に、次のいずれかの入力を可能にすべきである (SHOULD)。(1) ホストドメイン名、(2) ドット付き 10進数字 ("#.#.#.#") 形式の IP アドレス。ホストは、ドット付き 10進数字番号の文字列をドメイン名システムで検索する前に、シンタックス上のチェックを行うべきである (SHOULD)。
http://www2s.biglobe.ne.jp/~hig/tcpip/HostReq_Appl.html#HREQAPP_2_1

とあります。「ホストドメイン名」または「ドット付き10進数字形式のIPアドレス」を入力可能にすべきとされています。

(4) 数字のみのドメイン名は存在しない

現在、数字とドットのみのドメイン名は存在しません。トップレベルドメインには必ずアルファベットが含まれています。

存在しないものを「ホスト名」と呼ぶのは少々疑問が残ります。

(5) 攻撃経路となる入力値はIPアドレスと考えるべきではないか?

Qualysの発表したEximに対する攻撃手法によると、脆弱性があった関数の目的はすでにIPアドレスである引数の場合にコストの高いDNS検索をしないことです。

The purpose of this function is to avoid expensive DNS lookups if the hostname argument is already an IPv4 or IPv6 address.

攻撃条件の「数字とドットのみ」というのは、少なくとも脆弱性があったこの関数の中では、それがIPアドレスかどうかを判定するための条件と考えられます。

結論

以上(1)~(5)のように、攻撃経路となる入力値はホスト名ではなくIPアドレスではないか?という疑問が生じます。

これを「IPアドレス」であると考えるならば、その場合にIPアドレスとしての入力値に対してIPアドレスとしての形式をチェックするバリデーションを実施するというアプリケーション仕様も考えられます。

そして、そのようなバリデーションを実施していれば、今回のEximのGHOST脆弱性は防げていたという主張にとくに問題はないように感じました。

Tags: security, validation

FuelPHPの継続的インテグレーション環境をVagrantとJenkinsを使って構築する

今日は、FuelPHPのプロジェクトのためのJenkinsサーバを構築してみます。

この設定で完璧というわけではないですが、いろいろなものが一通り動くレベルにはなってます。

FuelPHPプロジェクトを作成する

FuelPHPのプロジェクトとして、ここでは、『はじめてのフレームワークとしてのFuelPHP 第2版(改訂版)』のコンタクトフォームを使います。

はじめてのフレームワークとしてのFuelPHP第2版(3) 実践編 はじめてのフレームワークとしてのFuelPHP第2版(2) 入門編 はじめてのフレームワークとしてのFuelPHP第2版(1) 環境構築編

develop-2ブランチをgit cloneします。

$ git clone --depth=5 -b develop-2 https://github.com/kenjis/fuelphp1st-2nd-contact-form.git

以下は、プロジェクトがGitで管理されていることを前提としています。

Vagrantを使いサーバを構築する

Vagrant CentOS6 PHP Development Environment(vagrant-centos6-php)を使います。

FuelPHPプロジェクトのトップフォルダでgit cloneします。

$ cd fuelphp1st-2nd-contact-form
$ git clone -b develop https://github.com/kenjis/vagrant-centos6-php.git

vagrant-centos6-php/Vagrantfileを変更し、Jenkins、FuelPHPを使うようにします。

--- a/Vagrantfile
+++ b/Vagrantfile
@@ -23,7 +23,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
   # mailcatcher web
   config.vm.network :forwarded_port, guest: 1080, host: 1080
   # (optional) jenkins
-  #config.vm.network :forwarded_port, guest: 8080, host: 8080
+  config.vm.network :forwarded_port, guest: 8080, host: 8080

   # Create a private network, which allows host-only access to the machine
   # using a specific IP.
@@ -91,14 +91,14 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
      #chef.add_recipe "mongodb"
      #chef.add_recipe "redis"
      #chef.add_recipe "elasticsearch"
-     #chef.add_recipe "jenkins"
+     chef.add_recipe "jenkins"

      chef.add_recipe "phpunit"
      chef.add_recipe "php-project"

      # (optional) Framework of your choice
      #chef.add_recipe "codeigniter"
-     #chef.add_recipe "fuelphp"
+     chef.add_recipe "fuelphp"
      #chef.add_recipe "phalcon"

      # (optional) Update all yum packages

仮想マシンを構築します。

$ cd vagrant-centos6-php
$ vagrant up

これで、PHP開発環境を兼ねたJenkinsサーバが構築されました。

▼Jenkinsのダッシュボード Jenkinsのダッシュボード

Webアプリケーションの設定をする

仮想マシンにSSHして、Webアプリケーションの設定をします。

$ vagrant ssh

ホストOSでのfuelphp1st-2nd-contact-formフォルダが、仮想マシン内では~/fuelphp(実体は/mnt/project)になっています。

composer installし、MySQLにrootでログインします。

[vagrant@localhost ~]$ cd fuelphp
[vagrant@localhost fuelphp]$ php composer.phar self-update
[vagrant@localhost fuelphp]$ php composer.phar install
[vagrant@localhost fuelphp]$ mysql -u root -proot

データベースとユーザを作成します。

mysql> CREATE DATABASE `fuel_dev` DEFAULT CHARACTER SET utf8;
mysql> CREATE DATABASE `fuel_test` DEFAULT CHARACTER SET utf8;
mysql> GRANT ALL PRIVILEGES ON fuel_dev.* TO username@localhost IDENTIFIED BY 'password';
mysql> GRANT ALL PRIVILEGES ON fuel_test.* TO username@localhost;
mysql> exit

マイグレーションでテーブルを作成します。

[vagrant@localhost fuelphp]$ oil refine migrate:current
[vagrant@localhost fuelphp]$ FUEL_ENV=test oil refine migrate:current
[vagrant@localhost fuelphp]$ oil refine migrate:current --packages=auth
[vagrant@localhost fuelphp]$ FUEL_ENV=test oil refine migrate:current --packages=auth

Jenkinsでのジョブを作成する

FuelPHPプロジェクト用のジョブを作成します。

http://localhost:8080/にアクセスし、左のメニューから「新規ジョブ作成」をクリックします。

「ジョブ名」を「contact-form」とし、「既存ジョブのコピー」を選択し「コピー元」に「fuelphp-template」を入力し、「OK」を押します。

新規ジョブ作成

「fuelphp-template」はvagrant-centos6-phpに用意されているFuelPHP用のひな形です。

Jenkinsのジョブを設定する

プロジェクト「contact-form」の「設定」をクリックします。

まず、「ビルド無効化」のチェックを外します。

ビルド無効化のチェックボックス

「ソースコード管理」の「Git」の「Branches to build」を「*/develop-2」に変更します。ビルドに使用するブランチの設定です。

ソースコード管理の設定

設定が完了したら、下の「適用」ボタンを押します。

ビルドを実行する

プロジェクト「contact-form」の「ビルド実行」をクリックすると、ビルドが実行されます。

ビルド実行

▼ビルド中のコンソール出力 コンソール出力

たまに、PHPのメモリ不足でビルドが失敗することがあります。もう一度ビルドを実行するとたぶん成功します。

うまくいかない場合は、PHPのメモリ割当を増やしてください。

▼プロジェクトcontact-form プロジェクトcontact-form

Gitにコミットしたら自動的にビルドを実行する

.git/hooks/post-commitファイルを作成します。

#!/bin/sh

curl -s http://localhost:8080/job/contact-form/build?token=triggerString
echo "run Jenkins build."

triggerStringは認証トークンですが、今は設定されていないので必要(関係)ありません。

「Jenkinsの管理」→「グローバルセキュリティの設定」で「セキュリティを有効化」すると、ジョブの設定の「ビルド・トリガ」の選択肢に「リモートからビルド」が追加され、「認証トークン」を設定できるようになります。

フックファイルに実行権限を設定します。

$ chmod +x .git/hooks/post-commit

これで、Gitリポジトリにコミットすると、ビルドが実行されるようになります。

push時にビルドを実行したい場合は、.git/hooks/post-updateを作成します。

関連

参考

Tags: fuelphp, jenkins, vagrant, database, continuous-integration

最強の英会話学習サイトVerblingがスゴすぎて紹介せざるを得ない

英会話学習サイト「Verbling」があまりにスゴいので紹介します。

何がそんなにスゴいのか?

このサイトは、なんと 無料でクラス(グループレッスン)を視聴し放題 なのです。

どういう仕組みかというと、レッスンがGoogleハンズアウトで行われており、ライブのレッスンも録画されたレッスンも視聴するだけなら無料なのです。

レッスン(Googleハンズアウト)に参加するのは有料です。つまり、自分から話すことはできないが聴いてるだけならずっとタダという太っ腹なのです。

英会話のクラスがどんなものか全く知らなかったり、いきなり参加してついていけなかったらどうしよう?なんて心配な人もいると思いますが、ここでは聴くだけならタダなので気兼ねなく時間の許す限り聴いていることができます。

なんかすごい日本人向きな感じがしますね。まあ、無料ユーザがいくら増えてもVerblingの収入は1円も増えないのでそれだけだと困るでしょうが。

料金など

ちなみに、クラス(グループレッスン)はチケット購入の場合、現在1クラス(1時間)3ドルです。サブスクリプションだと月額19ドルで10クラスと45ドルで無制限があります。

グループレッスン以外にもプライベート(1対1)レッスン(Tutoring)もあります。こちらは、1時間20~30ドル、20ドル前半が多いようです(先生によりレートが異なる)。講師はみんな英語ネイティブの人のようです。

以下のリンクからサインアップすると、5ドルのクーポンがもらえます。いわゆる紹介プログラムです。

Verbling

▼公式サイト

▼サインアップ

Facebook、Google認証およびユーザ登録してのサインアップが可能です。クレジットカードは不要です。

以下のリンクからサインアップすると、5ドルのクーポンがもらえます。

ライブクラスの視聴

サインアップしてサイトにログインします。

▼「Classes」を押すと 現在のクラスおよびこれからのクラスの一覧が表示されます。

▼クラスの一覧 「Live classes」に今やっているクラスが表示されています。「Live now!」ボタンを押します。

▼ライブクラスの視聴 ウィンドウが表示されるので「Go to class」を押すと、今やっているクラスが視聴できます。

YouTubeを見るだけなので、カメラやマイクも全く不要です。

過去のクラスを視聴する

(2016-03-07 追記) Verblingの「クラス」はどうやらなくなってしまったようです。Tandemというのに変わり、過去のレッスンを視聴することはできなくなったみたいです。

今のところ、過去のクラスは https://www.verbling.com/classes?past_present=past&class_languages=en からまだ視聴できます。

▼「Recorded」を押すと、過去のクラスの一覧が表示されます。

▼言語の選択 言語を「English」にしましょう。

▼クラスの難易度 クラスの難易度でフィルタすることもできます。

▼英語のビギナーのクラス 英語のビギナーのクラスだけで4000クラス(4000時間)以上あります。

他の難易度も含めると過去の英語のクラスは2万以上です。

すべて無料で視聴し放題です。しかも、過去のクラスは完全にYouTubeを見るだけなので、途中で止めることも、繰り返し聴くこともできます。

以下のリンクからサインアップすると、5ドルのクーポンがもらえます。

まとめ

  • Verblingでは、現在(ライブの)および過去(録画)2万時間以上の英会話のグループレッスンを無料で視聴し放題です。
  • 視聴するだけなら、クレジットカード、カメラやマイクも不要です。
  • レッスンに参加するのは有料で、また、有料のプライベートレッスンもあります。

参考