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 に採用される予定です。