ホーム » ブログ » 2007年07月の記事

2007年07月の記事

« 2007年6月 | 2007年8月 »

idea * idea CakePHP修行 に重大なセキュリティホールが!

2007-07-30 | このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

久しぶりのi d e a * i d e a CakePHP修行! への返信です。

MAX_FILE_SIZEをhtmlヘルパーで書けないのか?

画像のアップロード処理をつくる【I】(CakePHP修行 #26) | i d e a * i d e aより。

さてまずはedit.htmlを変更したいのですが・・・MAX_FILE_SIZEの指定ではまりました。これってhtml helperでできないのかしらん?

<?= $html->hidden('MAX_FILE_SIZE', array('value'=>'30000')); ?>

現状では書けません。この話題についてはCakePHPでDBに関連しないパラメータはヘルパーで書くべきか? (Re:CakePHP修行! | idea*idea) : akiyan.comをどうぞ。

画像をアップロードするディレクトリのPermissionは777でよいのか?

画像のアップロード処理をつくる【I】(CakePHP修行 #26) | i d e a * i d e aより。

次にファイルアップ先の/webroot/picsを作り、Permissionを与えます(777にしたけどいいのかな?)。

アリともいえるしナシともいえます。ディレクトリのPermissionの問題は「上位のディレクトリの権限がどうなっているか」「グループ設定はどうなっているか」「サーバーを自分以外が使用するか」「セキュリティホールがあった場合、影響範囲をどこまでにおさえるか」などを考える必要がありますので、一概には言い切れません。

ポイントは自分以外の人間が正規の方法以外でそのディレクトリにファイルを作れてしまうかどうかです。これが無ければ、とりあえずはOKです。

しかし重大なセキュリティーホールが

しかし、このアップロード処理のコードには重大なセキュリティホールがあります。このセキュリティホールを利用すると任意のコードを実行できてしまいます。原因は、アップロードされたファイルの拡張子を変えずにDocumentRootの下に移動しているからです。

$ext = strtolower(preg_replace("!.*\.!", null, $this->data['User']['pic']['name']));
$filename = sprintf("%05d.%s",$this->User->id, $ext);
move_uploaded_file($this->data['User']['pic']['tmp_name'], APP."webroot/pics".DS.$filename);
$this->data['User']['pic'] = $filename;

攻撃用のコードを含んだ「attack.php」や「getcookie.html」といったファイルをアップロードされてしまった場合、phpであれば中身がそのまま実行され、htmlであれば埋め込まれたJavaScriptが動作してしまいます。要するに「何でもアップローダー」になってしまっているのですね。

このエントリを書いている時点の最新のコード(画像のアップロード処理をつくる【III】(CakePHP修行 #31) | i d e a * i d e a)ではファイルを移動せずにgd関数で画像を出力するようになりましたが、以前としてファイル名がそのままなので画像データに細工を施せば何らかのコードを埋め込むことができます。詳しくは画像へのPHPコマンド挿入 - T.Teradaの日記をどうぞ。

解決策の一つとして、アップロードされたファイルの画像形式を調べて、その形式にあった拡張子に変更してpicsディレクトリに配置することです。画像でなければアップロード処理はキャンセルしてしまいましょう。

ファイルというのは「ユーザーからのとても大きな入力値」ですので、普段の入力値と同じように入力値チェックやエスケープが必要です。今回の解決策として例示した拡張子の変更は、エスケープ処理のファイル版といえます。

皆さんもファイルのアップロード処理を実装する場合は、十分に注意して開発しましょう :)

2007-07-30 written by akiyan | 記事 | 固定リンク | コメント (0) | トラックバック (0) | このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

ここはおさえておきたい,CakePHP情報サイトリンク集

2007-07-03 | このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

gihyo.jpでCakePHPの連載中のCakePHPで高速Webアプリ開発の第3回目の記事を書かせていただきました。

今回は『ここはおさえておきたい,CakePHP情報サイトリンク集|gihyo.jp』と題して、よりすぐりのCakePHP情報サイト・ブログをご紹介させていただきました。Cakeに触れる前にブログから読み始めるのもいいと思いますので、よろしければどうぞ。

以下、バックナンバー一覧です。

2007-07-03 written by akiyan | お知らせ | 固定リンク | コメント (0) | トラックバック (0) | このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

[CakePHP] ログイン認証まとめ・レイアウトの切り替え方とsetLayout関数

2007-07-02 | このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

今回もCakePHPの話題です。1.1系を前提にしています。

ログイン認証まとめ

日本語のCakePHP情報ブログの老舗のひとつであるCakePHP のおいしい食べ方さんで、Webアプリケーションにおけるログイン認証まわりの考察がまとめられています。

  • (1)そもそも$this->redirectを使わない
  • (2)DBやセッションに、“今、ログイン作業をはじめたよ”と情報を書き込んでおき、その場合にはリダイレクトしない。
  • (3)今現在、ログインアクション中ならば、リダイレクトしない
  • (4)user_controller(=ログインをチェックするコントローラ)内に自分がいるかどうかをチェックする

ログイン周りをどうしようか迷っている方は非常に参考になると思いますのでぜひ。

» CakePHP のおいしい食べ方: redirect()で困ったら~"Don't redirect directly!"

レイアウト切替は$layoutで。setLayout関数はコントローラーには定義されていない

画面をカスタマイズしたい(CakePHP修行 #014) | i d e a * i d e aで、setLayoutを使うとエラーになることに戸惑っている様子です。

わからないのはsetLayout()の使い方。マニュアル上ではレイアウトファイルを複数作って切り替えることが可能、とあります。そこでLogin中は/app/views/layout/login.thtmlを使いたいと思い、次のように記述しました。

  function login()
  {
    $this->setLayout('login');
    $this->pageTitle = 'Welcome to CODE*CODE!';
    $this->set('error', false);

すると・・・。

↑ なんかエラー・・・なぜだ?

参考にしたというマニュアルのCakePHP Manual - Views(英語)の該当箇所を読んでみましょう。

You can create as many layouts as you wish for your Cake site, just place them in the app/views/layouts directory, and switch between them inside of your controller actions using the controller's $layout variable, or setLayout() function.

要約します。

  • 好きなだけレイアウトを作れるよ。
  • レイアウトはapp/views/layoutsディレクトリに置くだけ。
  • 切り替えるときはControllerクラスの$layout変数を使うか、setLayout関数を使ってね。(←ココが変)

確かにsetLayout関数を使うように書かれていますが、実はこのsetLayout関数はControllerクラスには定義されていません。ここはちょっとマニュアルの書き方がまぎらわしいですね。setLayout関数はViewクラスで定義されており、設計的にもControllerから呼ばれることは想定されていないと思われます。

ひょっとするとコントローラーにsetLayout関数が存在するバージョンが存在したのかもしれませんが、cake/libs/controller.phpの2006年6月14日のリビジョン(@3084)を見た限りではsetLayout関数は存在しませんでした。

というわけで、$layoutを使えばよいと思います。

ちなみに、$this->render('テンプレート名', 'レイアウト名'); でレイアウトを指定することもできます。

1.2系ではView::setLayoutは廃止

今日現在の1.2の最新版ではsetLayout関数は廃止されています。非推奨状態から廃止に至ったようですね。廃止時のchangesetは以下からどうぞ。

» Changeset 4981 for branches/1.2.x.x/cake/libs/view/view.php - CakePHP : The Rapid Development Framework for PHP - Trac

2007-07-02 written by akiyan | 記事 | 固定リンク | コメント (0) | トラックバック (0) | このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

« 2007年6月 | 2007年8月 »