カテゴリー: Programming

セッションのクッキーを設定する場合のベストプラクティス

HTTPセッションは通常クッキーを利用して行います。クッキーを利用したセッションの場合、お薦めする設定は以下の通りです。

  1. ドメイン名は指定しない
  2. パスはルート(/)を指定する
  3. セッション管理用のクッキーはセッションクッキー(有効期間0)にする
  4. httponly属性を付ける
  5. 可能な場合は必ずsecure属性をつける
  6. 複数アプリケーションを利用する場合はsession.nameまたはsession_name()でセッションクッキー名で指定する (アプリケーションの固有名デフォルトで設定し、設定項目として変更できるようにする)

もっと読む

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

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

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

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

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

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

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

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

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イメージも用意しているので試してみてください。

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

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

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

 

OSC Tokyo – 今更聞けないSQLインジェクションの現実と対策

明日のOSC東京Fallでは「SQLインジェクション”ゼロ”のPostgreSQL利用法 – 今更聞けないSQLインジェク ションの現実と対策」と題したセッションを日本PostgreSQLユーザ会の講師として話をさせて頂きます。

SQLインジェクションはとうの昔に枯れた話題と思われていますが、古くても今の問題です。何年か前、日本PostgreSQLユーザ会のセミナーで手作業でのブラインドSQLインジェクションのデモをした事がありますが今回はツールを使ったデモもあります。書いている間に当初作ろうと思っていたプレゼンとは異なる物なってしまいました。多少紹介から期待する内容とは異なっているかも知れません。既にSQLインジェクションについては十分知っている方でも、それなりに(?)楽しめる内容になっていると思います。おかげ様で満員だそうですが、飛び込みでも少しは入れるのかな?

45分なのに60枚もスライドがある上、デモもあります。かなりハイペースで話すことになります。ネットで直ぐに見つかるような基本的な事はあまり書かなかったのですが、無いようで書くとSQLインジェクションについて色々在る物です。多少スライドは飛ばす事になります。

ほぼ同じ内容でOSC高知でも話をさせて頂く予定です。
来たくても来れなかった方は是非高知でお会いしましょう。

PHPが文字エンコーディング攻撃に強い理由 – HTMLエスケープ

PHPが文字エンコーディング攻撃に比較的強い理由は入出力の文字エンコーディングのバリデーション(サニタイズ)が行えるだけではありません。PHPが提供するHTMLエスケープ関数が文字エンコーディング攻撃に対して強い事も理由の一つです。

PerlでHTMLエスケープと言えば、<,>,&,”,’をエンティティ変換するコードが一番に見つかります。

「perl html escape」でググると一番に見つかったページは次のページです。このページではまだ3バイトEUCの場合の例、CGIモジュールを使った例も載っているので良い方でしょう。

http://saboten009.blogspot.com/2008/04/perlhtml-xss.html

少し前にPerl, Ruby,Pythonユーザは検索で有用なセキュリティ情報を得られるのか?と疑問に思い調べました。これだけ知っていれば取り合えず十分というページはそう簡単には見つかりませんでした。

いつも問題になるのは PHP だけど Perl は問題ないのか、すでに議論し尽くされた問題なのか、PHPer のモラルが低いせいか。

Perl,Ruby, Pythonで議論し尽くされ対策が浸透している、とは到底思えません。Railsで文字エンコーディングを利用したXSS脆弱性が話題になっていることからも明らかです。PHPがいつも問題になるのはよく使われていて、初心者も多く、公開されているWebアプリも圧倒的に多いからです。モラルの問題ではありませんし、このページで紹介されているPerlのエスケープ方法だけではPHPのhtmlentities()やhtmlspecialchars()よりも脆弱です。文字エンコーディングを考慮するようになっていないからです。 もっと読む

セキュリティ専門家でも間違える!文字エンコーディング問題は難しいのか?

一見徳丸さんのブログは分かりやすいように思えますが、それは単純な実験により分かりやすいように見えるだけで複数の間違いがあります。

その間違いとは

  • 意図の取り違い – 誤読
  • 言語の仕様と実装の理解不足
  • HTTPやPHP仕様の理解不足
  • セキュリティ対策をすべき場所の理解不足

です。(※0)

もっと読む

Drupal勉強会とその時の資料

Linux Foundationは全面的にDrupalと呼ばれるCMSに移行したそうです。日本のLinux Foundationも当然、Drupalに移行しています。そこでLinux Foundationの小薗井さんから一度講師をして欲しい、と頼まれていました。PHPカンファレンスにいったので、その次の日の日曜日、9月6日の勉強会に参加してきました。

外国人の方が多い、と聞いていたのですが本当に外国人の方の割合が多かった。20名弱(?)ほどのうち4名くらい(?)は外国人の方、日本人の方(?)でも帰国したばかりで日本語がたどたどしいと言われている方もいました。とてもインターナショナルな感じで学生のころを思い出しました。

ユーザ会のURL: http://groups.drupal.org/japan

勉強会の様子は次のような感じです。

その時に使った資料を公開します。

テーマはPHPを使った安全なWebプログラミングの概要です。

クリックしてSecure-PHP-Programming.pdfにアクセス

かなり古い資料をリフレッシュさせたのですが、時代の流れを感じました。昔は「まあ、いいか」と判断していた部分も今でもは「絶対ダメ」になっていたりしました。とは言っても「Webアプリセキュリティ対策入門」はこれより新しく書いたもなので今でも十分通用します。ちょうど良い時期に出版したといえるのかも知れません。

資料にタイポや概要の説明であっても分かり辛い点と思える箇所などありましたら、ぜひ教えて下さい。

DrupalなどのCMSは興味の対象外だったのですが、NetCommonsといい個人的にはブーム(遅すぎ?)になっています。ToDoリストにやりたいことが山積みです…

第3回 はじめてのZendFrameworkアプリケーション

第3回 はじめてのZendFrameworkアプリケーション がgihyo.jpで公開されています。

http://gihyo.jp/dev/serial/01/zf-ajax/0003

コメント、質問、不具合など、気づかれた事がございましたらコメントを頂けると助かります。

次回はこのダメダメな初めてアプリケーションを少しマシにします。
その次は4/30にリリースされたZend Framework 1.8の紹介をします。

Zend_Toolの使い方 – パスに入れない

Zend_ToolのzfコマンドがZendFrameworkのバージョンによって使えたり、使えなかったりする問題で困っていたのですが原因が分かりました。

Zend_Toolのzfコマンドでプロジェクトを作成すると

$ zf create project

ZendFrameworkのファイルをカレントディレクトリのlibraryに全てコピーします。プロジェクトの雛形にはapplication/boostrap.phpが含まれ、ここでinclude_pathが設定されます。boostrap.phpは、エントリポイントとなるpublic/index.php

// @see application/bootstrap.php
$bootstrap = true;
require ‘../application/bootstrap.php’;

から毎回必ず呼ばれるので

// you may wish to add other paths here, or keep system paths: set_include_path(‘../library’ . PATH_SEPARATOR . get_include_path()
set_include_path(‘../library’);

ZendFrameworkのアーカイブはどこに展開しても構わないようになっています。

この事は知っていたのですが、zfコマンドを使わないでZendFrameworkを使えるよう、PEARをインストールしたディレクトリにlibrary/Zendディレクトリをコピーし、デフォルトのphp.iniでinlcude_pathに設定してZendFrameworkを使うようにしていました。

これがどうもダメだったようです。Zend_Toolのディレクトリ構成を見て、似通った構成だったのでもしかして、と思いinclude_path設定を変えて試してみました。すると動かないと思っていたバージョンでもzfコマンドが動作するようになりました。インクルードパスにZendFrameworkのライブラリをパスにいれると、意図しないスクリプトが読み込まれてエラーになったりしていたようです。中途半端に動く物もあったりしたのでですが「previrew版だから仕方ないか」と思って詳しく調べていませんでした。これで一つすっきりしました。

Zend_Toolを試す場合、ZendFrameworkのZendディレクトリはinclude_pathに入れないようにした方が良いようです。基本的な事ですが、探しても情報が見つからなかったので書いておきます。