PHP 5.4から利用できるtraitの利用例

PHP 5.4から利用できるtraitの利用例

PHP5.4からtraitが利用できるようになる事をご存知の方も多いと思います。

traitはコードの水平再利用を可能にする仕様拡張です。Rubyのmixinのような機能と言えば分り易いかも知れません。

誰でもtraitを利用したくなるようなコードをinternals@php.netのMLで見かけたので紹介しよう、と思って書いたのですがコピペしたコードをしっかり読んでなくておかしな所があった事を @sotarok さんに教えてもらいました。

元のコードは色々問題があるので書き直しました。こうやればアクセサーを沢山書く必要が無くなります。 もっと読む

Bit module for PHP

誕生日のメッセージを送ってくださった皆様ありがとうございました!

今日は誕生日ということで多少は趣味のOSSに時間を割いてもバチは当たらないだろう、という事で簡単なPHPモジュールを書きました。PHP勉強会@東京に参加してPHPerバイナリアンの方の発表に触発された事がこのモジュールを書いた動機です。BitモジュールはバイナリアンPHPerの為のモジュールです。

https://github.com/yohgaki/bit

関数は今のところ4つだけあります。

  • string byte_get(string) – バイナリをHEX文字列に変換
  • string byte_set(string) – HEX文字列をバイナリに変換
  • string bit_get(string) – バイナリを0と1の文字列に変換
  • string bit_set(string) – 0と1の文字列をバイナリに変換

PHPではバイナリを取り扱う事が面倒だったのですがこのモジュールを使えば比較的簡単にバイナリを修正する事ができます。

初めはバイナリを配列にして返そうか、とも思ったのですが効率が悪いので単純に文字列に変換することにしました。こんな機能が欲しい!こう修正して欲しい!という方はご連絡ください。対応できるかも知れません。

ちなみに現状でもPHPスクリプトだけでバイナリを取り扱えるライブラリがあります。

http://openpear.org/package/IO_Bit

さらにZlibバイナリが扱えてしまう物まであります。

http://openpear.org/package/IO_Zlib

そしてSWFファイルを修正できてしまう物も。

http://openpear.org/package/IO_SWF

これらは@yoya さんが書かれたパッケージだそうです。凄すぎです。バイナリを操作する必要がある方はこちらも是非ご利用ください。

RealIP Module for PHP

リバースプロキシの背後にあるPHP用に$_SERVER[‘REMOTE_ADDR’]をX-Real-IPやX-Forwarded-Forヘッダに設定されたIPアドレスに書き換えるRealIPを書きました。

https://github.com/yohgaki/realip

少しGoogleで検索しても見つからなかったので作ったのですが、既にありそうな気がします。

PHPスクリプトで書き換えても良いのですが、アプリをバージョンアップした時に忘れる可能性があります。プロキシ・Webサーバで何とかする方法もありますが、プロキシ・Webサーバの仕様に合わせた設定が必要だったり、と不便な所もありモジュールの方が便利なので書きました。同じ事をするには他の方法がありますが、必要な方はどうぞ。

多分、PHP5.2でもコンパイルできると思います。コンパイル出来なかったら教えてください。

PHPセッションアダプションをスクリプト側で修正する方法

PHPのスクリプトを使ってアダプティブなPHPセッションをアダプティブにしない方法を紹介します。

このブログで紹介していたかどうか覚えていないですが、セッションアダプション対策としてsession_regenerate_id()が導入された時に議論・紹介されているので知っている方も多いと思います。(というより、PHPerの常識ですよね?)

まずはセッションアダプションの原理と対策の復習をしておきます。 もっと読む

PHP 5.4の文字エンコーディング設定

PHP 5.4 RC1が公開されています。PHP 5.4のリリースが近いです。PHP 5.3の–enable-zend-multibyeの問題でバグレポートをした関係でinternals MLでメールのやり取りをして分った事とその他をまとめておきます。主にSJISを使う場合の注意点です。間違い・勘違いもあるかも知れないので気が付いたらコメントを下さい。

  • PHP 5.4はデフォルトの内部エンコーディングがISO-8859-1になる
  • SJISでコードを書く場合はzend.script_encoding=SJISを書く
  • SJISでコードを書く場合は内部エンコーディングをSJIS(mbstring.internal_encoding=SJIS)に設定する
  • SJISで出力する場合はmbstring.http_output=SJIS (output_handler=mb_output_handlerなどが必要)を設定する
  • SJISでページを書いている場合、SJISが入力になるのでmbstring.http_input=SJISを設定する
  • Zend Multibyteサポートがコンパイルオプションからランタイムオプション(zend.multibyte=On)になる
  • Zend Multibyteサポートにはmbstringが必須
  • mbstringがモジュールとしてビルドされている場合でもZend Multibyteサポートを有効にできる
  • declare(encoding=…)でスクリプト中からスクリプトのエンコーディングが指定できる

php  -c php.ini-development -d zend.multibyte=1 SJIS_script.phpとしてSJISが含まれるスクリプト(例えば、echo “表”)を実行するとSJISの文字が?に変換されてしまいます。正しく処理するには-d mbstring.internal_encoding=UTF-8などを追加し

php  -c php.ini-development -d zend.multibyte=1 -d mbstring.internal_encoding=utf-8 SJIS_script.php

などとしなければなりません。

全般的にマルチバイト文字エンコーディングのサポートが改良されていますが、以前と多少異なる部分があるので注意が必要です。

DOMベースXSSの検出ツール

久しぶりにブログを更新すると色々書きたくなるものですね。ということでまだこのブログでは紹介したことがないDOMベースXSSのオープンソースツール、DOMinatorを紹介します。最近の商用ツールも類似の機能をサポートしています。

http://code.google.com/p/dominator/

DOMベースXSS: JavascriptはDOMを利用してHTMLを動的に変更できます。この機能を利用するとブラウザ側のJavascriptで動的に変化するWebサイトを構築できます。HTMLなどを修正するとデータにユーザが入力が含まれているとプログラマが意図しないJavascriptが実行できます。

要はクライアントサイドのJavascriptインジェクション攻撃の事です。

Javascriptは非常に柔軟な言語で便利な反面、セキュリティチェックが非常に難しい言語でもあります。DOMinatorはJavascriptの柔軟性を上手く利用して、DOMベースのXSSを検出します。Javascriptの入出力を監視し、DOMベースXSSが可能である箇所を見つけ出します。百聞は一見に如かず。デモ動画を見ればDominatorを使ったDOMベースXSSチェックがどのように便利であるのか分かります。

http://www.youtube.com/watch?v=f_It469LUFM

(動画に音声はありません。説明はTEXTエディタに書いてあるのでHDにして最大画面にして見てください)

どうですか?ソースコードを読んで解析するより何倍、いえ何十倍も楽にDOMベースのXSSを検出できました。

簡単そうに見えますが、使いこなすには色々コツと知識が必要です。既に情報が古くなっていますが

http://code.google.com/p/domxsswiki/

http://code.google.com/p/domxsswiki/wiki/LocationSources

などを利用してJavascriptインジェクションが可能か調べると、サイトが脆弱であるか分かります。あまり使いこなし方が分からなくても有用なツールです。Javascriptで動的なサイトを構築している方、特にユーザがコントロールできる情報使いJavascriptでページを操作している方は一度DOMinatorを使ってみると良いでしょう。

ところで、PROVE for PHPのマイナーバージョンアップをしました。PDOなどの内部オブジェクトの対応はまだですが、Webコンソールを改善しました。(まだまだ改善が必要で、どんどん改善します)PROVEもDOMinatorに似ていると言えば似ていると言えます。PHPの内部動作を詳細に記録し、差分を取ることでPHPやアプリが正しく動作している事が確認できます。サイトにはVMwareイメージもあるので試してみてください。バグを見つけたら教えてください!

PHPのSession Adoption脆弱性

PHPのセッションモジュールはセッションアダプションに脆弱なのですが、開発者の理解が得られず何年間も放置されています。

セッションアダプション脆弱性: 未初期化のセッションIDを受け入れてセッションを確立する脆弱性。

PHPのセッションIDはデフォルトでドメイン指定無し、パスは/に設定されています。専用サイトならこれであまり困ることは無いのですが、複数のアプリケーションやユーザが利用するようなサイトでは問題になります。

例えば、Chromeはパスよりドメインが優先されるのでドメインを利用したセッションIDの固定化などが起きます。IEではドメインよりパスが優先されるのでパスを利用したセッションIDの固定化などが起きます。

session_regenerate_id()を使えばOK、と考えている人も多いようですが既に設定済みのクッキーのうちどれが優先されてしまうか?が問題であるためsession_regenerate_id()を利用してもセッションIDは変わりません。優先されないクッキーを設定しても意味がないからです。

対策としては、すべてのドメイン、パスのセッションIDと同じクッキー名のクッキーを削除(空のクッキーを設定すると削除)する事ですがあまり多くの人がやっているとは思えません。根本的な解決策は「厳格なセッション管理」を行うことです。未初期化のセッションIDは受け入れないようにすれば完璧です。

セッションIDの固定化が可能な状況では、セッションアダプションに脆弱な場合はセッションを盗まれますが、厳格なセッション管理ならセッションIDを毎回振り直そうとする事になり、セッションは盗まれません。つまり、セッションが盗まれる代わりに「ログインできない」というDoS攻撃になります。セッションを盗まれるより、DoSの方が比べる必要がないくらいマシです。「ログインできない!」というユーザが居たら「ブラウザのクッキーを削除してください」と対応すれば良いだけです。

数年前にそろそろ直したら?とsecurity@php.netにメールしたのですが、開発者の問題だと勘違いしていて修正されませんでした。今日、またphp-internal@list.php.net internals@lists.php.net に再度メールをしておきました。さて、今回はどうなることでしょう?

PROVE for PHP Ver 1.0

まだまだ完成度を高める必要がありますが、PHPのリグレッションテストツールのPROVE for PHPのダウンロードを開始しました。

http://www.provephp.com/

PHPのテストスイートの設定を忘れていてPDOオブジェクトのサポートできてない事に直前に気がついたのでPDOには対応していません。これは出来るだけ早急に対応します。

Dokuwikiなどでは普通に使えます。VMwareイメージも用意しているので試してみてください。

非常用の個人利用は無料です。商用利用はご購入ください。開発に役立ちます!

PROVE for PHP 0.4.0-dev リリース

PROVE for PHP 0.4.0をリリースしました。

  • IOをプラグイン化(将来PostgreSQLなどに対応)
  • prove_seek_function_call()を追加
  • ハードリンクによるコピーに対応(高速化)
  • prove_rename_function()の無効化(PHP 5.3のZend Engineの仕様変更により関数名変更はメモリエラーが発生するため)
  • ログフォーマットを更新。バージョン情報を追加。

もともとIO部分はプラグイン化するつもりだったのですが、ファイルに最適化し過ぎていた部分があったため大幅にリファクタリングしました。機能追加よりも今後の機能拡張を容易にするための変更がメインです。内部構造をかなり変更したのでバグが残っているかも知れません。もし見つけたら教えて頂けると助かります。

もうバージョンアップで困らない – PROVE for PHP

昨年のPHPカンファレンスで紹介したPORVE for PHP 開発版の公開を始めました。PROVE for PHPはこんなテストが出来ます。

  • PHPをアップデートしてアプリに影響が無い事を検証する
  • PHPアプリをアップデートしても以前と同じように動作する事を検証する

使い方もとても簡単です。

  • テストケースの作成はブラウザからアプリを利用するだけ
  • ロードバランサを用いて実運用サーバからのテストケースも作成可能
  • テストの実行はプログラムを実行するだけ
  • 違いが在った場所はプログラムの何処か確実&簡単に判明

http://www.provephp.com/

もっと読む

error: unable to index file – 初めてのGitエラー

Gitを使っていて初めてエラーらしいエラーに合いました。検索してもコレという物がヒットしなかったので書きます。

error: unable to index file aaa
fatal: updating files failed

などと出るエラーですが

  • 既にファイルとしてコミットしているパスを、ディレクトリにしてコミットしようとする

と出るエラーのようです。簡単に再現します。

(git version 1.7.3.3)

[yohgaki@dev git-test]$ git init .
Initialized empty Git repository in /home/yohgaki/tmp/git-test/.git/
[yohgaki@dev git-test]$ touch aaa
[yohgaki@dev git-test]$ git add aaa
[yohgaki@dev git-test]$ git commit -m 'add' .
[master (root-commit) ff6f5d2] add
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 aaa
[yohgaki@dev git-test]$ rm aaa
rm: remove 通常の空ファイル `aaa'? y
[yohgaki@dev git-test]$ mkdir aaa
[yohgaki@dev git-test]$ touch aaa/bbb
[yohgaki@dev git-test]$ git add aaa/
[yohgaki@dev git-test]$ git commit -m 'add dir' .
error: unable to index file aaa
fatal: updating files failed

他のケースでも出るようですが私の場合はこれでした。コミットしたいディレクトリに移動してコミットすればコミットできましたが、私の場合は何か他の問題(?)もあったようでdetachした状態となったのでマージして直しました。

[yohgaki@dev git-test]$ git commit -m 'add dir' .
error: unable to index file aaa
fatal: updating files failed
[yohgaki@dev git-test]$ cd aaa/
[yohgaki@dev aaa]$ git commit -m 'commit dir' .
[master 5b63843] commit dir
 1 files changed, 0 insertions(+), 0 deletions(-)
 rename aaa => aaa/bbb (100%)
[yohgaki@dev aaa]$ cd ..
[yohgaki@dev git-test]$ git branch
* master

 

phpのescapeshellcmdの余計なお世話を無くすパッチ

徳丸さんのブログでescapeshellcmdの余計なお世話の件が指摘されていたのでパッチを作りました。これmagic quoteと同じレベルの余計なお世話なのですが放置されています。個人的にはどのような関数にも全てバリデーション済みの文字列しか渡さないのでセキュリティ問題は発生しないのですが、UNIX系OSではペアとなる”と’はエスケープしない仕様に気が付いていないプログラマも多いかもしれません。

もっと読む

php – 短縮URLを一行で展開する

perl – 短縮URLを一行で展開する

という記事があったのでPHPでやるとどうかなと作ってみた。(と言うほどの物ではありませんけど)本当に一行にするには無理があったのでの実際には2行です。他に良い方法があるかな?

$ php -r '$h=get_headers($argv[1], 1);echo $h["Location"];' http://j.mp/dankogai

専用関数があるので面白くもなんともありませんね。

 

gihyo.jpのRasmusさんインタビューの補足

私がインタビューアーと執筆を担当させて頂いたRasmusさんへのインタビュー記事は好評だったようです。

http://gihyo.jp/news/interview/2010/rasmus

この記事の中で「美しいツールは美しい問題を解決するためには非常に効果的かも知れませんが,多くの場合は必要がありません。さまざまなルールを作り,フレームワークを使い,モデルやビューを使って解決できない問題があるのです。」の部分は解説が無いと理解できないかも知れません。Rasmusさんなら私と同じようにこう思っているハズという補足なので外している可能性もありますが、この部分の意図を補足します。

もっと読む