Cookie key を暗号化
2007年3月28日
Nucleus では、ログインキーは md5 で暗号化されて MySQL データベースに保存されているが、クッキー認証キーは生のまま保存されている。これだと、万一、何かしらの脆弱性(SQL injection など)でクッキー認証キーが洩れた場合に、セッションハイジャックが起きる。
md5 で暗号化すれば、万一クッキー認証キーが洩れても、暗号解読が必要なので、セッションハイジャックは難しい。ついでに、md5 による暗号化の前に$_SERVER['REMOTE_ADDR']の情報も加えておけば、XSS でクッキー認証キーが洩れても、別のIP address からの接続はほとんど不可能である。
先日、MEMBER.php の改造でこれを実現しようとしたのであるが、なかなか改造コードが完成しなかった。改めてコアのコードを見てみると、globalfunctions.php の改変だと、比較的簡単にこれが実現できることが分かった。
globalfunctions.php 180行目付近
235 行目付近
これで、クッキー認証キーが、接続元の IP アドレス付きで暗号化されて MySQL データベースに格納される。
これをプラグインにしようとすると少し厄介で、やはり、コアの書き換えが必要になる。
この場合は、globalfunctions.php の『$member =& new MEMBER();』の前に、
を書き加える必要がある。同様のコードを config.php に持ってくることも可能だが(その場合は、コアの書き換えは要らない)、その場合はクッキープレフィックスにうまく対応できない。
追記:
この機能は、Nucleus 3.3 に採用される予定です。
md5 で暗号化すれば、万一クッキー認証キーが洩れても、暗号解読が必要なので、セッションハイジャックは難しい。ついでに、md5 による暗号化の前に$_SERVER['REMOTE_ADDR']の情報も加えておけば、XSS でクッキー認証キーが洩れても、別のIP address からの接続はほとんど不可能である。
先日、MEMBER.php の改造でこれを実現しようとしたのであるが、なかなか改造コードが完成しなかった。改めてコアのコードを見てみると、globalfunctions.php の改変だと、比較的簡単にこれが実現できることが分かった。
globalfunctions.php 180行目付近
if ($member->login($login, $pw) ) {
$member->newCookieKey();
$member->setCookies($shared);
$member->setCookieKey(md5($member->getCookieKey().serverVar('REMOTE_ADDR'));
$member->write();235 行目付近
} elseif (cookieVar($CONF['CookiePrefix'] . 'user') ) {
// Cookie Authentication
$res = $member->cookielogin(cookieVar($CONF['CookiePrefix'] . 'user'), md5(cookieVar($CONF['CookiePrefix'] . 'loginkey').serverVar('REMOTE_ADDR')) );
// renew cookies when not on a shared computer
if ($res && (cookieVar($CONF['CookiePrefix'] . 'sharedpc') != 1) && (!headers_sent() ) ) {
$member->setCookieKey(cookieVar($CONF['CookiePrefix'] . 'loginkey'));
$member->setCookies();
}これで、クッキー認証キーが、接続元の IP アドレス付きで暗号化されて MySQL データベースに格納される。
これをプラグインにしようとすると少し厄介で、やはり、コアの書き換えが必要になる。
<?php
class NP_SecureCookieKey extends NucleusPlugin {
function getName() { return 'NP_SecureCookieKey'; }
function getMinNucleusVersion() { return 220; }
function getAuthor() { return 'Katsumi'; }
function getVersion() { return '0.1'; }
function getURL() {return 'http://hp.vector.co.jp/authors/VA016157/';}
function supportsFeature($what) { return (int)($what=='SqlTablePrefix'); }
function getEventList() { return array('PreAuthentication','LoginSuccess','PostAuthentication'); }
var $disabled=true;
var $LoginSuccess=false;
function getDescription() {
return $this->getName().' plugin. ' . ($this->disabled ?
'This plugin is now disabled. Please edit globalfunctions.php and add '.
'"$manager->notify (\'PreAuthentication\',array());" just before the '.
'"$member =& new MEMBER();".':'');
}
function event_PreAuthentication(){
global $CONF,$HTTP_COOKIE_VARS;
$this->disabled=false;
if (cookieVar($CONF['CookiePrefix'] . 'loginkey')) {
$CONF['NP_SecureCookieKey']=cookieVar($CONF['CookiePrefix'] . 'loginkey');
$HTTP_COOKIE_VARS[$CONF['CookiePrefix'] . 'loginkey'] =
$_COOKIE[$CONF['CookiePrefix'] . 'loginkey'] =
md5($CONF['NP_SecureCookieKey'] . $_SERVER['REMOTE_ADDR']);
}
}
function event_LoginSuccess(&$data){
if ($this->disabled) return;
$member=&$data['member'];
$member->setCookieKey(md5($member->getCookieKey().$_SERVER['REMOTE_ADDR']));
$member->write();
$this->LoginSuccess=true;
}
function event_PostAuthentication(&$data){
global $member,$CONF;
if ($this->disabled || $this->LoginSuccess) return;
if (!$data['loggedIn']) return;
if (!cookieVar($CONF['CookiePrefix'] . 'user')) return;
if (cookieVar($CONF['CookiePrefix'] . 'sharedpc')) return;
if (headers_sent()) return;
$member->setCookieKey($CONF['NP_SecureCookieKey']);
$member->setCookies();
}
}
?>この場合は、globalfunctions.php の『$member =& new MEMBER();』の前に、
$manager->notify ('PreAuthentication',array());を書き加える必要がある。同様のコードを config.php に持ってくることも可能だが(その場合は、コアの書き換えは要らない)、その場合はクッキープレフィックスにうまく対応できない。
追記:
この機能は、Nucleus 3.3 に採用される予定です。