セッションフィクセーション問題

ITpro の記事で Session Fixation 問題について書かれていたので PHP での対策例を書いておきます。
 
PHP ではこの問題を解決するために、session_regenerate_id() という関数が提供されています。

<?php
 
session_start();
 
$old = session_id();
session_regenerate_id();
$new = session_id();
 
echo “$old -> $new<br>”;
// 結果:
// d4aa3b6cfaedca70dc09262dfbf8c39e -> 53c031b85fe89e00d3b151eddfd91733

具体的な利用方法はこんな感じです。

<?php
 
session_start();
 
$algo = “sha256”;
 
// パスワードは生で保存せずハッシュで持つ(5.1.2 以前は hash() 関数を使えないため mhash() または md5() で代用する)
$password_hash = “d74ff0ee8da3b9806b18c877dbf29bbde50b5bd8e4dad7a3a725000feb82e8f1”; // hash($algo, “pass”);
$bAuthorized = !empty($_SESSION[‘authorized’]);
 
if(!$bAuthorized){
        if(empty($_GET[‘p’]) || hash($algo, $_GET[‘p’]) !== $password_hash){
                // ログインページ表示
?>
                未認証(session_id = <?=session_id()?>)<br>
                <form action=”” method=”GET”>
                        <input type=”password” name=”p”>
                        <input type=”submit” value=”ログイン”>
                </form>
 
<?php
                exit;
        }
        $bAuthorized = $_SESSION[‘authorized’] = true;
        // セッションフィクセーション対策(Session Fixation)
        session_regenerate_id(); // ログインが成功した段階でセッションID を更新垢
 
}
 
?>
認証済み(session_id = <?=session_id()?>)

このサンプルを実行すると、パスワードに “pass” という文字列を入れて認証すると session_id が書き換わるのを確認できます。
 
この関数を使うと、透過的にセッションIDが書き換わるので関数呼び出し側はセッションフィクセーション対策を簡単に施すことができます。ただし当然ですが既に何かを

コマンドプロンプトで日本語入力をするには

Alt+[半角/全角キー]を押すとコマンドプロンプトでも日本語入力ができます。
Cygwin の場合も同様ですが、こちらは「cygwin で日本語入力をする方法(Windows Tips by pPoy)」にあるように、設定ファイルに以下の設定を追加する必要があります。
~/.inputrc:

set kanji-code sjis
set convert-meta off
set meta-flag on
set output-meta on

~/.bashrc

export JLESSCHARSET=japanese-sjis
alias ls=’ls –show-control-chars’

tips – Net_URL で URL を解決する

相対 URL から絶対 URL に変換するには PEAR::Net_URL が利用できます。
URL の要素を分解して取得することができるため、便利そうです。
 
インストール:

$ pear install Net_URL

HTTP_Request が依存しているので、ネットワーク関係の PEAR パッケージを入れたことがあれば既に入っていることが多いです。
 
例:とりあえず使ってみる

<?php
// http://example.com/foo/boo/file.php で実行する
 
require_once “Net/URL.php”;
 
$url =& new Net_URL(“next.html”);
echo “<PLAINTEXT>”;
var_dump($url);
echo $url->getURL();
?>

 
例: GET クエリで渡された URL が、自サービス内 URL かどうかを調べる
※外部サイトへの踏み台になるのは防ぎますが、内部のリファラチェック回避の踏み台にはなり得る事に注意。

$url =& new Net_URL($_GET[‘url’]);
if($url->host != $_SERVER[‘SERVER_NAME’]){ // 相対パスまたは同じドメインの絶対URLなら HTTP_HOST や SERVER_NAME と一致する。
echo “error!”;exit; //
}
echo “ok”;

 
参考:
PEAR::Net_URL(pear.php.net)

FreeBSD 7.0-RELEASE

昨日 7.0 がとうとうリリースされたようです。
 
– SMP 環境でのパフォーマンス向上(ベンチマークや DB 処理について FreeBSD 6.X 系の 350% 〜 1500%, Linux 2.6.24 の 115% の性能)
– ULE スケジューラの大幅な改善(ただし7.0では 4BSD スケジューラがデフォルトで選択される。7.1 以降は ULE スケジューラがデフォルトになる予定)
– ファイルシステム Sun ZFS の試験的サポート。
– ジャーナルファイルシステムのセットアップに gjournal が使えるようになり、仮想ストレージデバイスを扱うのに gvirstor が使えるようになった。
– ファイルシステム XFS で読み込みのみ(Read-only)モードをサポート。
– ファイルシステム unionfs をフィックス。
– iSCSI initiator
– いくつかのネットワークドライバで TSO, LRO をサポート
– SCTP(Stream Control Transmission Protocol)の試験的サポート
– ワイヤレス(802.11)サポートの多量な改善。
– OpenBSD のネットワークリンクアグリゲーション(lagg(4))を取り込んだ。
– メモリアロケータ(malloc(3))として新しく高性能な jemalloc を採用。
– freebsd-update(8) でセキュリティフィックス,不具合修正だけでなくリリースバージョンのアップグレードを正式にサポートするようになった。
– X.Org 7.3, KDE 3.5.8, GNOME 2.20.2 に対応
– GCC 4.2.1 に対応
– BIND 9.4.2 に対応
 
アナウンスに従い freebsd-update-upgrade.tgz を取得後

sh freebsd-update.sh -f freebsd-update.conf -r 7.0-RELEASE upgrade

としたら

Looking up update.FreeBSD.org mirrors… 1 mirrors found.
Fetching metadata signature for 6.3-STABLE from update1.FreeBSD.org… failed.
No mirrors remaining, giving up.

と怒られてしまった。
たしかに http://update1.freebsd.org/ には STABLE がない。
同じバージョンであれば(uname -r とか sysctl kern.version では) RELEASE = STABLE だったと思うので

$ cat freebsd-upgrade.sh.patch
534a535
> sed -E ‘s,-STABLE,-RELEASE,’ |

とパッチをあててやり、マニュアルどおり

$ uname -r
6.2-STABLE
$ su
# sh freebsd-update.sh -f freebsd-update.conf -r 7.0-RELEASE upgrade
# sh freebsd-update.sh -f freebsd-update.conf install
# shutdown -r now
(リブート後 root でログイン)
# portmanager -u -f
(ports リビルド)
(※他自分でビルドしていたものがあれば個別にリビルドする)
# sh freebsd-update.sh -f freebsd-update.conf install # もういちど。
# shutdown -r now
(リブート後 一般ユーザでログイン)
$ uname -r
7.0-RELEASE

と、これでいけました。
ただし、jail 環境がある場合、freebsd-update-upgrade スクリプトは jail 環境を考慮してないのか

# ./freebsd-update.sh -f freebsd-update.conf -r 7.0-RELEASE -b /path/to/jail upgrade
freebsd-update.sh: Cannot upgrade from 7.0-RELEASE to itself

と jail 環境を更新するときも uname -r を見てカーネルが既にアップグレード済みだから更新の必要がない、といわれてしまいました。
 
このため jail 環境を更新するのに結局 /usr/src からいつもの手順を踏んで更新しました。

# cat /etc/supfile
  
 *default host=cvsup1.jp.FreeBSD.org
 *default base=/usr
 *default prefix=/usr
 *default release=cvs tag=RELENG_7
 *default delete use-rel-suffix
 *default compress
 src-all
 
# csup /etc/supfile
# cd /usr/src
# make buildworld
# JAILDIR=/path/to/jail
# make installworld DESTDIR=$JAILDIR
# mergemaster -D $JAILDIR
 
# shutdown -r now

あとはホストと同様に portmanager -u -f で ports を更新します。

$ su
# mount_null /usr/ports /path/to/jail/usr/ports
# jls
   JID IP Address Hostname Path
     1 192.168.2.11 myjail /path/to/jail
# jexec 1 bash # jail に接続
# cd /usr/ports/ports-mgmt/portmanager/
# make install
# portmanager -u -y -f
# exit # jail から切断
# /etc/rc.d/jail restart

 
追記(2008-03-21):
portmanager では更新もれがある場合、Shared Library まわりで色々エラーが出ます。
たとえば、FreeBSD 6.2 のとき ports インストールした emacs を FreeBSD 7.0 にしてから実行しようとすると libz.so.3 がないと怒られる。あるいは新しく ports からプログラムをインストールしようとしたら lib*.so.* という共有ライブラリがないためにコンパイル中に色々エラーがでてインストールできなかった。というような現象です。
 
この場合の対策は

portupgrade -rf “問題のあるport”

でリビルドしてみる。それでだめなら

pkg_deinstall -r “パッケージ名”

でいったん該当のパッケージと依存パッケージを削除して

portinstall -r “パッケージ名”

で削除したものを再び入れなおすと解決します。

CAcert.org のセキュリティ上の問題点

いまさらネタですが、最近になってようやく CAcert.org を使ってみました。
 
しかし少し触ってみた結果、CAcert.org をルート証明書に入れるように人に勧めることはとてもできないという結論に至りました。
気をつけるべき箇所を把握した上でルート証明に加えるなら問題はないのですが。。
 
大事な点は、身分証明や本人確認を
「電子メール証明なら対象メールアドレス、サーバ証明なら対象ドメインのwhois の Administrative Contact に書かれたメールアドレスへのメールを読めるかどうか?」
だけで判断しているため、少なからず第三者がサーバ証明書を作る危険性がある点(ただし既に CAcert.org で誰かに登録されたメールアドレス/ドメインは不可)と、
「誰でも無料で登録、即時証明書発行ができる」
という点。
CAcert.org では第三者に保証人になってもらいポイントを増やすことで信頼を重ねたりもできますが、実際のところはそんなものがなくても、(CAcert.org がルート証明機関に入ったブラウザであれば) https 通信で警告が出ないサーバ証明書を作ることができます。
 
CAcert.org に限りませんが、たとえば g00gle.com みたいな、ターゲットドメインに類似した名前のドメインを正規にとり、そのサーバ証明書を作ってフィッシングサイトを作る、なんてこともありえます。
 
クライアントが証明書を適切にチェックするようになればこういった問題を考える必要はないのですが、現実にはそうもいきません。
今日日数十ドルで証明書を発行してくれるルート証明機関もいますが、CAcert.org のような無料で証明書を発行できる組織が、そういうユーザが使うブラウザのルート証明機関に入るのはリスクの増大に他ならないかなという結論に至ったわけです。
 
参考:
CAcert.org は Windows のルート証明書に含まれるようになるのか?(yamk 日記)

作業中のプロセスを残したまま端末を終了する

何かをビルドしていて、時間が予想外にかかってしまい、nohup もしていないためになかなか端末を閉じることができずに予定が狂って結局残業時間がのびる、なんてことありませんか?
 
そういうときは disown を使うと実行中のジョブを端末から切り離すことができます。
(以下は bash の例です)

$ make # 何か時間のかかる作業
## 出力は略。途中で端末接続を切りたくなった(Ctrl-Z) ##
^Z
[1]+ Stopped make
 
$ bg # バックグラウンドで実行を再開
## 略。出力再開 ##
 
$ disown # 端末を切ってもプロセスが残るようにカレントジョブ( %1 )を端末から切り離す
$ exit # 終了

nohup と違い端末を切ると標準出力、エラー出力はどこにも出力されなくなりますが、これで端末を切断してもプロセスが実行されたままになります。
 
参考:
一度 tty から起動したプロセス(PBD)
一度 tty から起動したプロセス (csh/ksh 版)(にぽたん研究所)

公式マニュアルの場所

http://svnbook.red-bean.com/
オライリー本「Subversion によるバージョン管理」(原題: `Version Control with Subversion’)をオンラインで読むことができます。
 
公式サイトの Documentation が最終更新2004年なため、ちゃんとした公式ドキュメントがないのかとてっきり思っていたら、Additional Resources の Subversion Book が正式なマニュアルなんですね。
man svn して初めて気づいた。。

tips – キャッシュあれこれ

– キャッシュの中身を見るには?
Firefox の場合, IE の Temporary Internet Files のようにキャッシュディレクトリに直接ファイルが置かれないためエクスプローラからはキャッシュの中身を見ることができません。

about:cache

を URL に指定するとメモリキャッシュ、ディスクキャッシュ両方の中身を見ることができます。
 
– キャッシュフォルダの場所を変更するには?

about:config

を URL に指定して設定画面を開き、「右クリック→新規作成→文字列」を選択して

設定名: browser.cache.disk.parent_directory
文字列: c:\path\to\cache

のように設定すると次回起動時からこの指定先がキャッシュフォルダとして利用されるようになります。
 
参考:
about:mozilla(Mozilla Page by Yotti)
about: からはじまる擬似 URL の一覧。

/tmp を自動で削除するには

FreeBSD は標準では /tmp の中身は削除されないようになっていますが、FreeBSD には削除処理を自動で行ってくれる二つの手段が提供されています。
 


– 起動時に中身をクリアする
 
/etc/rc.conf に以下の設定を追加すると FreeBSD の起動時に /tmp の中身を削除するようになります。

clear_tmp_enable=”YES” # Clear /tmp at startup

 
この機能は /etc/rc.d/tmp で実装されており、/etc/rc.d/rc.conf にデフォルト設定があります。

clear_tmp_enable=”NO” # 起動時に /tmp をクリアする
clear_tmp_X=”YES” # /tmp 内の X11 関連のディレクトリをクリアして再構築する


– 定期的に古いファイルを削除する
/etc/periodic.conf に以下の行を設定することで /tmp の中身のうち一定期間アクセスがないファイルを削除するようになります。

daily_clean_tmps_enable=”YES”

 
rc.conf の clear_tmp_enable を YES にすると起動時に /etc/rc.d/tmp が実行されて /tmp のすべてのファイルを削除します。
 
この機能は /etc/periodic/daily/110.clean-tmps で実装されており、/etc/default/periodic.conf にデフォルトの設定があります。

daily_clean_tmps_enable=”NO” # 不要ファイルを毎日削除する
daily_clean_tmps_dirs=”/tmp” # このディレクトリ以下を削除する
daily_clean_tmps_days=”3″ # 指定期間アクセスがないもののみ対象
daily_clean_tmps_ignore=”.X*-lock quota.user quota.group” # 削除対象外のファイル
daily_clean_tmps_ignore=”$daily_clean_tmps_ignore quota.user quota.group”
 
daily_clean_tmps_verbose=”YES” # 削除したファイル名を出力する

ruby でランダムな文字列を生成

“ランダムなパスワードを生成する” の ruby バージョン。
[2005-04-25] (JavaScript 版)
[2005-05-31] (PHP 版)

# ランダムな文字列を生成する。
# 引数 _length_ を指定すると生成桁数を指定することができます(デフォルト 8 桁)。
def getRandomString (length = 8)
  source=(“a”..”z”).to_a + (“A”..”Z”).to_a + (0..9).to_a + [“_”,”-“,”.”]
  key=””
  length.times{ key+= source[rand(source.size)].to_s }
  return key
end
 
# 10 桁の文字列を取得
p getRandomString 10