Home > PHP

PHP Archive

CakePHP vendors.phpにセキュリティホール

この記事の所要時間: 144

cakebakerCakePHP Users in JapanにもあるようにCakePHPにて任意のファイルが読み込めるセキュリティホールが見つかっています。

問題となるファイルは[app/webroot/js/vendors.php]です。このファイルはvendors/javascript/以下にあるjsファイルを読み込むものなのですが、is_file()やreadfile()がバイナリセーフではないため%00をファイル名に挿入することにより任意のファイルを読めてしまいます。

対応策は以下になります。

  1. 修正済みファイルを適用する。
  2. 使用していないならvendors.phpを削除してしまう。
    そもそも[app/vendors/javascript]が無い場合はvedors.phpは使用していないはずのですので。(デフォルトでは[app/vendors/javascript])はありません。
  3. magic_quotes_gpcをOnにする。
    文字化けの問題があるので日本語圏ではこれは無いでしょうね。

ただ現時点ではbake.phpで使用するテンプレートが修正されてないため、bake.phpで新規プロジェクトを作るとまた同じ問題が発生してしまいます。その場合は再度対策が必要となるためご注意を。

追記:
bake用テンプレートも修正されました。(Thanks dho!)

あとちょっと気になるのはjsファイルかどうか正規表現の部分です。

if(is_file('../../vendors/javascript/'.$file) && (preg_match('/(\/.+)\\.js/', $file))) 

ここは後方一致になるように’/(\/.+)\\.js$/’にしておいた方が良いかと。あとこれは純粋に疑問なのですが\/はなぜ必要なのでしょうか。
まあこのファイル自体使いどころが良く分からなかったりするのですが。:P

CakePHP 環境に応じてDBの設定を変える

この記事の所要時間: 350

本番環境や開発環境など環境に応じてDBの設定を変える方法です。

1.AppModelを書き換える

withcakeで紹介されている方法です。

AppModelのコンストラクタで切り替えるアイデアは分かりやすくて良いと思います。ちなみに記事のコメントにもあったのですが、記事のコードだとコンストラクタの引数がModelへ渡されませんので、修正版を以下に書いておきます。

[app/app_model.php]

class AppModel extends Model {
  function __construct($id = false, $table = null, $ds = null) {
    $this->useDbConfig = $_SERVER['HTTP_HOST'] == 'devserver'?'test':'default';
    parent::__construct($id, $table, $ds);
  }
}

2.database.phpを書き換える

NoswaDで紹介されている方法です。

cakebakerでも書かれていますが、database.phpは設定ファイルなので、これにコードを入れるのは若干抵抗を感じます。(まあdatabase.phpがなぜクラスになっているのか?という考えもありますが。)

3.Subversionで切り替える

cakebakerで紹介されている方法です。

I try to avoid to add code to configuration files because those files shouldn’t contain any logic. Instead I use Subversion to manage different configurations. In my repository I have at least two folders for each project: a “trunk” folder where the development happens, and a “live” folder which contains the code (and configurations) for the live application. So if I put something online I just export the content of the “live” folder from the repository, and with it the “live” configuration.

cakebaker » An alternative to “hacking” config files (2006-09-17)

「Subversion使えよ。なんでハックなんかやってるの?」と言ったところでしょうか。:)詳しい実践方法の記述が無いので的外れの可能性大ですが、これだとtrunk/とlive/でコードが別々になるような気がするのですが、どうなんでしょうか。

4.環境変数で切り替える

1.の変形版です。開発環境ではIPが変わる事があるので、環境変数で切り替える方法を考えてみました。これなら実行環境のIPがどうなろうと影響を受けません。

[httpd.conf]


SetEnv CAKE_DB_CONFIG test

[app/app_model.php]

< ?php
class AppModel extends Model {
  function __construct($id = false, $table = null, $ds = null) {
    $this->useDbConfig = empty($_SERVER['CAKE_DB_CONFIG']) ? 'default' : $_SERVER['CAKE_DB_CONFIG'];
    parent::__construct($id, $table, $ds);
  }
}
?>

httpd.confで環境変数CAKE_DB_CONFIGを定義しておけば、その値をuseDbConfigに使用し、定義がなければ’default’を使用します。使い方としては本番環境が’default’で、開発環境等の他の環境は’dev’等を定義する形を考えています。

正規表現 早見表

  • 2006-09-17 (日)
  • PHP
この記事の所要時間: 055

A4サイズの正規表現の早見表です。

The Regular Expressions cheat sheet is designed to be printed on an A4 sheet of paper and live by a designer or developer’s desk, to make life a bit easier. A description of what is on the cheat sheet follows, or if you are impatient, you can go straight to the full size Regular Expressions cheat sheet.

Regular Expressions Cheat Sheet – Cheat Sheets – ILoveJackDaniels.com (2006-09-17)

英語ですが基本的な構文がすっきりまとまっています。一枚印刷しておけば重宝しそうですね。

settypeで変数初期化

  • 2006-09-15 (金)
  • PHP
この記事の所要時間: 21

settype()で変数の初期化を行おうという記事です。

IMHO, this is much more clear. Its a standard way to set the type and default value of your variables. You see, settype() assigns a default value to the variables if they do not exist already.

Initializing & typing variables with settype() « Ramblings of a web guy (2006-09-15)

まあCやJavaでいう

int var;

という事ですね。

データ型を定義したいというのは分かるのですが、PHPではあまり意味が無いように思えます。というのも、その変数に異なる型の値を入れるとデータ型が変わってしまうんですね。

< ?php
settype($var, 'integer');
printf("\$var%s: %s\n", $var, gettype($var));

$var = 123;
printf("\$var=%s: %s\n", $var, gettype($var));

$var = 123.45;
printf("\$var=%s: %s\n", $var, gettype($var));

$var = "abc";
printf("\$var=%s: %s\n", $var, gettype($var));
?>
> php -f test.php 
$var=0: integer
$var=123: integer
$var=123.45: double
$var=abc: string

ふつうに$var=0で初期化されている方が分かりやすいです。データ型を固定したいのであれば変数を参照する際にキャストするなりsprintf()するなりで変換した方が無難です。

データ型がキッチリ決まっている方が安心という考えは分かりますけどね。このへんは普段あまり意識しないところなんでちょっと新鮮でした。

CakePHP 配列の考え方

この記事の所要時間: 035

モデルやコントローラで値の受け渡しは配列を使います。この配列はちょっとクセがあって$array[モデル名(or テーブル名)][カラム名]という形式になっています。これはちょっと抵抗がありました。1レコードの値を配列に入れるなら$array[カラム名]の方が自然だと思っていたからです。

ところが、ある事に気づいた時から「ああ、なるほど。」としっくりいくようになりました。

さてそれは何かと言うと、なんてことはない、これSQLと一緒なんですね。

select table.column from table;

これが分かってから何だかすっきりしました。

CakePHP アプリケーションの設定情報をまとめる

この記事の所要時間: 22

Amazonのアクセスキーやメールサーバホスト等、アプリケーション固有の設定情報(パラメータ)を一元的に記述する方法を考えてみました。

1.core.phpに記述する

[app/config/core.php]にはフレームワークが使用するパラメータが記述されています。これに続いてアプリケーションの設定を記述する方法です。シンプルで分かりやすいですが、フレームワーク自体の設定と一緒になってしまうので、混同しやすいかもしれません。

[app/config/core.php]

< ?php
#snip
/**
 * application config
 */
define('MAIL_SMTP', 'mail.example.com');
define('AMAZON_ACCESS_KEY', 'xxxxxxxxxx');
define('SYSTEM_PARAMETER', 'yyy');
?>

2.アプリケーション用の設定ファイルに記述する

アプリケーション用の設定は[app/config/app.php]に記述してAppControllerで読み込む方法です。これならフレームワークの設定とは切り離せますし、各controllerでは設定ファイルを意識する事なくパラメータを使用できます。

[app/config/app.php]

< ?php
define('MAIL_SMTP', 'mail.example.com');
define('AMAZON_ACCESS_KEY', 'xxxxxxxxxx');
define('SYSTEM_PARAMETER', 'yyy');
?>

[app/app_controller.php]

< ?php
#snip
config('app');
#snip
class AppController extends Controller
{
}
?>

今回は設定値をPHPの定数で定義する方法を取りました。定数はどこからでも透過的にアクセスできるので扱いが楽ですね。ただ設定値をアプリケーションで変更できないですし、もし開発者以外が設定を触るならiniファイル形式の方が良いかもしれません。いずれこちらの方法も考えてみたいと思います。

CakePHP Controller小話

この記事の所要時間: 39

9月に入りましたが、まだまだ暑い日が続きますね。アイスコーヒーとエアコンが欠かせません。さてここでbakerの皆さんに涼しくなる小話でも。

CakePHPでは1アクションがcontrollerの1メソッドになっています。アクション名(メソッド名)はリクエストのあったURLから決定されます。つまり外部からcontrollerのメソッドを実行できてしまうわけです。ただフレームワークがアクションメソッドだけをアクションとして実行するようにしてくれれば問題は無いはずです。ではURLで指定されたアクション(メソッド)がアクションメソッドかどうかどのように判断しているのでしょうか。

これが実は通常のメソッドとアクションメソッドとの区別は無いんですね。フレームワークはURLで指定されたアクション(メソッド)を単に呼んでいるだけなのです。つまりcontroller内のメソッドは外から呼び放題なわけです。

 

ちょっと涼しくなってきましたか?

 

こりゃいけないって事でアプリケーションのcontrollerではアクションメソッドだけを書きましょう、という話になるのですが、それだけではダメなんです。そう親クラスのControllerには多くのメソッドがあるんですね。それを継承しているんで、当然Controllerクラスのメソッドも呼び放題なわけです。

 

背中がゾクッとしてきましたね。

 

さらに付け加えるとURLの指定でメソッドに引数を与えることもできてしまいます。

 

 

怖いですねー。ホラーですねー。

 

 

で、どうしましょ。という話です。

まず以下に該当するメソッドはアクションとしては実行されません。

  1. メソッド名が[_](アンダースコア)ではじまるもの
  2. beforeFilter,beforeRender,afterFilterメソッド
  3. アクセス制御子がprivateのメソッド(PHP5のみ。これはPHP自身がFatal errorを出す)

これを見るとAppControllerや各controllerでは1.か3.のルールでメソッドを書けば大丈夫なようです。

ただControllerクラスのメソッドで上記のルールに該当しないものはやはり呼ばれてしまいます。とりあえずの実害は(おそらく)無いのでしょうけど、根本的に任意のメソッドを外部から呼ばれてしまうのは気持ち悪いです。そこでまたパッチ[cakephp_action_method.patch]を作りました。

このパッチではaction_~ではじまるメソッドのみをアクションとして実行します。アクションのメソッド名は[action_ + アクション名]になります。例えば/post/indexに対応するメソッド名は[action_index]になります。(ビューファイル名は従来とおりアクション名のみで良いです。)

[app/controllers/post_controller.php]
< ?php
class PostController extends AppController
{
  function action_index() {
    // indexアクションとして呼ばれる
  }

  function other_method() {
    // これはアクションとして外部から呼ばれない
  }
}
?>

これで外部からはcontrollerのaction_~以外のメソッドは呼べなくなります。精神衛生上はこの方が良いかと。無保証ですがよろしければどうぞ。

CakePHP URLマッピング修正パッチ

この記事の所要時間: 053

CakePHP 管理者用アクションに書いた/admin以下をApacheのBasic認証やIP制限でアクセス制限する方法ですが、CakePHP1.1.7.3363ではApache側のアクセス制限を回避されてしまう可能性があります。

この現象はURLのQUERY_STRINGにurl=を指定した場合に発生します。具体的には

http://www.example.com/post/index?url=/admin/user/index

でアクセスするとPostController#index()が呼ばれるのではなく、UserController#admin_index()が呼ばれてしまいます。

Apache側の設定(LocationMatch等)を上手く使う手もあるのですが、そもそもコントローラとアクションが上書きされてしまう事自体が問題だと思うので、修正パッチを書きました。気になる方はどうぞ。

[cakephp_url_mapping.patch]

php.iniの書き方

  • 2006-09-06 (水)
  • PHP
この記事の所要時間: 350

PHPの設定は記述する箇所に応じて書き方が異なります。わりと忘れがちなのでまとめてみました。

php.iniでの記述

; 引用符をつけないセミコロン(;)の後のテキストは、すべて無視されます
; セクションマーカ (角括弧の中のテキスト) は無視されます
; 論理値は、次のいずれかで指定します
; true, on, yes
; または false, off, no, none
register_globals = off
magic_quotes_gpc = yes

; 文字列を二重引用符で括ることも可能です
include_path = “.:/usr/local/lib/php”

; バックスラッシュは他の文字と同様に処理されます
include_path = “.;c:\php\lib”

from: PHPマニュアル-実行時設定

論理値のtrue(false),on(off),yes(no)は大文字・小文字を区別していないようなので、TrueやYesでも認識されます。

httpd.conf / .htaccessでの記述

php_value name value

指定した設定オプションに値を設定します。変更の可否が、 PHP_INI_ALL もしくは PHP_INI_PERDIR である設定オプションに対し利用できます。 セット済みの値をクリアしたい場合は、none を 値として使用してください。

注意: 論理値を設定する場合には php_value を使用しないでください。代わりに、php_flag (下記参照)を使用する必要があります。

php_flag name on|off

設定オプションに論理値を設定するために使用します。変更の可否が、 PHP_INI_ALL もしくは PHP_INI_PERDIR である設定オプションで利用できます。

php_admin_value name value

指定した設定オプションに値を設定します。このディレクティブは、.htaccess ファイルでは利用できません。また、 php_admin_value で設定された設定オプションの値は、.htaccess や VirtualHost ディレクティブ内から上書きできません。 セット済みの値をクリアしたい場合は、none を 値として使用してください。

php_admin_flag name on|off

設定オプションに論理値を設定するために使用します。 このディレクティブは、.htaccess ファイルでは利用できません。 php_admin_value で設定された設定オプションの値は、.htaccess や VirtualHost ディレクティブ内から上書きできません。

from: PHPマニュアル-設定を変更するには

httpd.conf / .htaccess内ではPHPの定数(error_reportingのE_ALL等)は使用できません。

設定変更可能な箇所

各設定項目は記述できる箇所が決まっています。項目ごとの詳細はPHPマニュアルに記載されているのですが、記述できる箇所(PHPマニュアルでは「変更の可否」)がPHP定数で書かれおり、いざ使う時に定数の意味を忘れてしまいがちです。(PHP_INI_SYSTEM / PHP_INI_PERDIRは良く「?」になります。。。)そこでPHP定数の定義をメモしておきます。

PHP_INI_USER	ユーザスクリプトまたはWindowsレジストリ  で設定可能なエントリ
PHP_INI_PERDIR	php.ini, .htaccess または httpd.confで設定可能なエントリ
PHP_INI_SYSTEM	php.ini または httpd.confで設定可能なエントリ
PHP_INI_ALL	どこでも設定可能なエントリ

from: PHPマニュアル-php.ini ディレクティブ

>>

あらためて見るとhttpd.confあたりは適当に書いていたなーという印象です。論理型の設定でもphp_valueを使っていましたし(値を[0 or 1]にすれば動作します)、php_admin~は使っていませんでした。(専用サーバでの運用がほとんどなので第三者に設定を上書きされる心配が無かったので。。。)ただ設定の意味合いをはっきりさせるためにもきっちり書いておいた方が良いですね。

CakePHPでDBアクセスなしのModelを作る

この記事の所要時間: 139

CakePHPのmodelはDBのテーブルと1対1になる事が想定されています。ただシステムを構築する際はこのような単純なmodelだけでは使い勝手が悪い場合があります。そこでDBアクセス無しのmodelの作成方法を模索してみました。

フレームワークのソースを見たところmodelの$useTableにfalseをいれておけば良いようです。

[app/models/no_db.php]

<?php
class NoDb extends AppModel
{
  $useTable = false;
}
?>

では、modelなしのcontrollerはというと・・・フレームワークを見る限りでは方法は無さそうですね。ただcontrollerの$nameでmodel名を指定する事ができるので、これにダミーのmodelを指定すれば、modelを新たに作らずにcontroller・ビューファイルを追加する事が可能です。

[app/controllers/no_my_model_controller.php]

<?php
class NoMyModelController extends AppController
{
  var $name = 'NoDb';

  function index() {
    $this->viewPath = 'no_my_model'; // ビューファイルディレクトリを指定
  }
}
?>

index()内のviewPathの設定を行わないと$nameの値でビューファイルディレクトリ名が決定されてしまうので注意が必要です。(ビューファイルもmodel同様に共通で良ければこの行は必要ありません。)

修正:2006/09/15
modelなしのcontrollerも作れますね。controllerの$usesをarray()かnullにすれば良いようです。

class MyController extends AppController
{
    // var $uses = null; works too
    var $uses = array();

    function index()
    {
    }
}

from: cakebaker » A controller without a model

ホーム > PHP

検索
フィード
メタ情報

Return to page top