PHP 4.4.0 Released

The PHP Development Team would like to announce the immediate release of PHP 4.4.0. This is a maintenance release that addresses a serious memory corruption problem within PHP concerning references. If references were used in a wrong way, PHP would often create memory corruptions which would not always surface and be visible. The increased middle digit was required because the fix that corrected the problem with references changed PHP’s internal API. PHP 4.4.0 does not have any new features, and is solely a bugfix release.

PHP 4.4.0がリリース。バグ修正だそうです。

PHP: PHP 4 ChangeLog

Fixed bug #32685, Fixed bug #29423 (Segfault when using assignment by reference within function).

ChangeLogではこの「関数内で参照代入するとsegfault」ってやつが一番でかそうです。

・・・ぐらいに思ってたのにMojavi2動かすと、

PHP Notice:  Only variable references should be returned by reference(略
PHP Notice:  Only variable references should be returned by reference(略
PHP Notice:  Only variable references should be returned by reference(略
PHP Notice:  Only variable references should be returned by reference(略

mojavi-all-classes.phpでNotice出まくり。原因はまさにコレ。参照返ししてるのに値で代入したり、値返ししてるのに参照代入すると注意されるようになったためです。たしかに注意してくれるとありがたいですが、Mojavi2のエラーハンドリングの仕組みが動く前(Controller::dispatchの中でset_error_handler)なので止めようが無し。

とにかく困ってる人はこうすればとりあえずは凌げるっぽいです。

mojavi-all-classes.php

// this is an uncommented, auto-generated file
// for full source, please view the Mojavi lib directory

//error_reporting(E_ALL);
error_reporting(E_ALL & ~E_NOTICE);

あとでがんばってNOTICE元を全部修正したパッチを作りたいです。

2006/03/07追記: 修正版はこちら

引き続きセッションIDかぶっちゃう問題

p0t: PHPのセッションID3

一度session_id()を取得するんじゃなくて、

session_id(md5($_SERVER[‘SERVER_ADDR’].uniqid(rand(),1)));

とかやるのはどうですか?
某所でこんなコードを書いたことがあって、正解かどうか激しく気になります。正解でしょうか?教えてください。

あと、$_SERVERの値って、php.iniやらの設定で取れないことあるよね。そんな時どうしよう。どうしよう・・・

投稿者 kかべ : 2005年07月12日 14:16

kかべさんのこの案が素敵な感じがします。
調べてみるとセッションID発行md5(uniqid(””””,1))はほぼ等価っぽいので正解なのではないでしょうか!

php-4.3.11/ext/session/session.c

sprintf(buf, "%ld%ld%0.8f", tv.tv_sec, tv.tv_usec, php_combined_lcg(TSRMLS_C) * 10);
PHP_MD5Update(&context, buf, strlen(buf));

php-4.3.11/ext/standard/uniqid.c

if (more_entropy) {
    sprintf(uniqid, "%s%08x%05x%.8f", prefix, sec, usec, php_combined_lcg(TSRMLS_C) * 10);
} else {
    sprintf(uniqid, "%s%08x%05x", prefix, sec, usec);
}

$_SERVERはどういうとき使えないんでしたっけ。その場合は、どうしよう・・・。

ref: PHPのセッションID3

黄昏流星群 (23)
  • 黄昏流星群 (23)
  • 小学館(2005-03-30)
  • (著)弘兼 憲史
  • 定価:¥ 530
  • 新品価格:¥ 530
  • ASIN:4091873138

TGRGの23巻。
ドラマのプロットをそのまま読んでる感じ。
難しいビジネスや政界の話と違ってこういう話に物事を凄まじく解り易く説明する能力を適用するとこうなるのか!
そんな違和感がいちいち引っかかりになって楽しい。

複数Webサーバ、単一セッション管理でセッションかぶっちゃう問題ですが、調べたら5人日ぐらいかかりそう・・・とか思ってましたが、この間の勉強会で聞いたら、

「session_id()でセッションID設定できる。」

一瞬で解決しました。

解決策をまとめると、

「セッション維持してくれるロードバランサーを使う」 OR 「セッションIDにアドレスをくっ付ける」

となりました。
実装はこんな感じか!?

session_id(str_replace(".", "a", $_SERVER["SERVER_ADDR"]).session_id());

Mojavi2で使うためにIPでユニークなセッションIDを使うコンテナ、IpUniqueSessionContainerを作ってみました。

<?php
require_once (USER_DIR."SessionContainer.class.php");

class IpUniqueSessionContainer extends SessionContainer {
    function load(& $authenticated, & $attributes, & $secure) {
        if (ini_get("session.auto_start") != 1) session_start();
        session_id(str_replace(".", "a", $_SERVER["SERVER_ADDR"]).session_id());
        if (!isset($_SESSION["attributes"])) {
            $authenticated = false;
            $attributes = array();
            $secure = array();
        } else {
            $authenticated = $_SESSION["authenticated"];
            $attributes = $_SESSION["attributes"];
            $secure = $_SESSION["secure"];
        }
        $_SESSION["authenticated"] =& $authenticated;
        $_SESSION["attributes"] =& $attributes;
        $_SESSION["secure"] =& $secure;
    }
}
?>

IpUniqueSessionContainer-0.1.zip

index.phpのUSER CONTAINER SETTINGSのところでこんな感じで使う。

require_once(BASE_DIR."opt/user/IpUniqueSessionContainer.class.php");
$user =& $controller->getUser();
$user->setContainer(new IpUniqueSessionContainer());

ref: PHPのセッションID2

この間のおざきさんの話がすごい気になってたんですが、対策できました!

Mojaviのすべての基本となるSCRIPT_PATH定数をこんな感じで設定してやれば、この間つくったURIUtil::redirect()もSmartyプラグインのmojavi_uriも絶対URIを吐いてくれます。

/**
* An absolute web path to the index.php script.
*/
define('SCRIPT_PATH', strtolower(trim(array_shift(split("/", $_SERVER["SERVER_PROTOCOL"]))))."://".$_SERVER["HTTP_HOST"].dirname($_SERVER["PHP_SELF"])."/index.php");

きもちー。

ref: リダイレクト面倒

2005/07/08追記:

こっちの方がよい(via MugeSo)

/**
* An absolute web path to the index.php script.
*/
define('SCRIPT_PATH', strtolower(trim(array_shift(split("/", $_SERVER["SERVER_PROTOCOL"]))))."://".$_SERVER["HTTP_HOST"].$_SERVER["PHP_SELF"]);

CSRF(クロスサイトリクエストフォージェリ)の対策を自分の中で決めてみましたが、根本的に間違った理解をしてることがわかりました

CSRFはそのユーザ自身(のクライアント)がアクセスする(させる)ことを利用する攻撃なんですな!

高木浩光さんの記事(via ファイさん)を元にPHPでのサンプルを作ってみました。

ログインページ(index.php):

<?php
session_start();
?>
<?="<?xml version=\"1.0\" encoding=\"utf-8\"?>"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<title>ログイン</title>
</head>
<body>
<h1>ログイン</h1>
<p>ログインしました。</p>
<p><a href="confirm.php">退会</a></p>
</body>
</html>

確認ページ(confirm.php):

<php
session_start();
?>
<?="<?xml version=\"1.0\" encoding=\"utf-8\"?>"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<title>退会処理 確認画面</title>
</head>
<body>
<h1>退会処理 確認画面</h1>
<p>本当に退会しますか?</p>
<form method="post" action="resign.php">
<strong>&lt;input type="hidden" name="sessionid" value="&lt;?=session_id()?&gt;" /&gt;</strong>
&lt;input type="submit" value="退会する" /&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;

処理ページ(resign.php):

&lt;?php
session_start();
if (<strong>session_id() == $_POST["sessionid"]</strong>) {
    $message = "退会しました。";
} else {
    $message = "退会・・・するかよ!";    
}
?&gt;
&lt;?="&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;"?&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
&lt;meta http-equiv="Content-Style-Type" content="text/css" /&gt;
&lt;meta http-equiv="Content-Script-Type" content="text/javascript" /&gt;
&lt;title&gt;退会処理 完了画面&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;退会処理 完了画面&lt;/h1&gt;
&lt;p&gt;&lt;?=$message?&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;

動いてるサンプル:http://p0t.jp/anti-csrf/

ソース:anti-csrf-0.2.zip

外部サイトでは(本人がアクセスしたとしても)対象サイトのクッキーを取ることができないっていうのがミソ・・・だと思う。
あってるのかどうか気になります!

それほど面倒ではないのでコンシューマサイトは全部これで行くことにします!

ref: CSRF対策俺ルール

2005/07/08追記:

$_COOKIE[””PHPSESSID”“] から session_id() に変更しました。(via ishinao

PEAR :: PEPr :: Details :: Linux_Debian_Apt

This package works as a wrapper of the famous apt utilities under Debian. It lets user search for packages or files, it uses packages.debian.org to fetch the content and return it in nice array structs.

PEPrにaptのラッパ。
素敵だけどProposal通らなそう!

Warning!!! 下記は全部間違ってました!
罵声を浴びせてからこちらへ → CSRF対策俺ルール2

CSRF クロスサイトリクエストフォージェリ – SpecIII – てけとうなWeb開発者の雑記

CSRFはサイトに対する正規のユーザーの権限を利用した攻撃です。
あるサイトのある処理を行うページに正規のユーザーを誘導し、強制的に望まない処理を発生させます。

CSRF(クロスサイトリクエストフォージェリ)
この間の勉強会でgorouさんとかが言っていてわかんなかったので調べました。

forgeryは偽造の意味なので「サイト横断的リクエスト偽造」でしょうか。
内容的には↓こうだそうです。

CSRFはサイトに対する正規のユーザーの権限を利用した攻撃です。
あるサイトのある処理を行うページに正規のユーザーを誘導し、強制的に望まない処理を発生させます。

具体的には記事の編集や削除といった機能を持つページのURLをダミーのリンクに埋め込んで踏ませたり、imgタグのsrcとして指定して知らず知らずのうちにアクセスさせます。特に後者の例ではユーザーが全く気がつかぬうちに攻撃が完了します。

JavaScriptでGETやPOSTができる以上、根本的な対策が難しそうです。
どう対応するか自分ルールを決めておくことにします。

CSRF対策俺ルール:

  • 本気で防ぎたい場合:CAPTCHA
  • ユーザビリティ優先の場合:全部POST&セッション&リファラーチェック(7/7追加)

Byecycle – Aesthetic Programming for Eclipse

logobyecycle.gif

Byecycle is an auto-arranging dependency analysis plug-in for Eclipse.

クラスの依存関係を表示するEclipseプラグイン。
可視化してくれると依存関係を減らすのが楽しくなっていいかも!こんな風に小ネタをすぐにEclipseプラグイン化できるようになりたい。

PECL :: Package :: ssh2

Provides bindings to the functions of libssh2 which implements the SSH2 protocol. libssh2 is available from http://www.sourceforge.net/projects/libssh2

libssh2のPHPバインディング。これ知っておくと仕事で要件を意外な方法で片付けたりできる場面がある・・・気がする!