【发布时间】:2010-10-11 11:48:47
【问题描述】:
我开发了一个 PHP 会话类并使用几个示例对其进行了测试(请参阅下面的源代码)。似乎没问题。现在我想让这个会话以某种方式“安全”。我找到了一些用于加密 cookie 的示例代码(在 Courioso 的书 Expert PHP and MySQL 中)。这是这段代码sn-p。
加密 cookie 的代码
$cookieData = serialize($user);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
srand();
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$encryptedData = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $secret,
$cookieData, MCRYPT_MODE_CBC, $iv);
setcookie('user', base64_encode).':'.$iv);
以及用于解密 cookie 的类似代码
我的第一个问题是:我可以信任这段代码吗? IE。真的安全吗? (我尝试了那本书的一些其他代码示例,发现它们相当有问题)。
我不完全理解如何将加密 cookie 的代码嵌入到我的会话类中(上面的代码 - 或任何其他 cookie 加密代码)。我应该替换由 PHP (PHPSESSID) 自动生成的 cookie,还是应该生成一个新的 cookie 并加密这个自定义 cookie? (我猜第二个是真的,但我想确定一下)。
如何通过加密 cookie 进行保护?我想象以下攻击: (1) 如果攻击者不知何故拿到了他手中的 cookie,他只是用相同的 cookie 回复。好的。他没有密码,但他有加密的密码。稍后我只检查加密密码是否正常。因此,如果攻击者拥有 cookie:游戏结束 - 无论 cookie 是否包含密码或“仅”加密密码。正确的? (2) 好的,这个问题可以使用像 SSL 这样的加密传输来解决。但是我想如果我使用 SLL,那么传输无论如何都会被加密。我不需要使用加密功能再次输入密码。对吗?
这是我已经拥有的会话类的代码。
谢谢
<?php
class SessionClass {
private static $_instance;
public static function getInstance()
{
if (!(self::$_instance instanceof self))
{
self::$_instance = new self();
}
return self::$_instance;
} // getInstance
public function __construct()
{
session_set_save_handler(
array($this, "open"), array($this, "close"),
array($this, "read"), array($this, "write"),
array($this, "destroy"), array($this, "gc")
);
$createTable = "CREATE TABLE IF NOT EXISTS `session`( ".
"`sessionID` VARCHAR(128), ".
"`data` MEDIUMBLOB, ".
"`timestamp` INT, ".
"`ip` VARCHAR(15), ".
"PRIMARY KEY (`sessionID` ), ".
"KEY (`timestamp`, `sessionID`))";
mysql_query($createTable);
} // construct
public function __destruct() {
session_write_close();
}
public function open ($path, $id) {
// do nothing
return (true);
}
public function close() {
// do nothing
return (true);
}
public function read($id)
{
$escapedID = mysql_escape_string($id);
$query = sprintf("SELECT * FROM session WHERE sessionID = '%s'", $escapedID);
$res = mysql_query($query);
if ((!$res) || (!mysql_num_rows($res))) {
$timestamp = time();
$query = sprintf("INSERT INTO session (sessionID, timestamp) VALUES ('%s', %s)", $escapedID, $timestamp);
mysql_query($query);
return '';
} elseif (($row = mysql_fetch_assoc($res))) {
$query = "UPDATE session SET timestamp = ";
$query .= time();
$query .= sprintf (" WHERE sessionID = '%s'", $escapedID);
mysql_query($query);
return $row['data'];
} // elseif
return "";
} // read
public function write($id, $data)
{
$query = "REPLACE INTO session (sessionID, data, ip, timestamp) ";
$query .= sprintf("VALUES ('%s', '%s', '%s', %s)",
mysql_escape_string($id), mysql_escape_string($data),
$_SERVER['REMOTE_ADDR'], time());
mysql_query($query);
return (true);
} // write
public function destroy($id)
{
$escapedID = mysql_escape_string($id);
$query = sprintf("DELETE FROM session WHERE sessionID = %s", $escapedID);
$res = mysql_query($query);
return (mysql_affected_rows($res) == 1);
} // destroy
public function gc($lifetime)
{
$query = "DELETE FROM session WHERE ";
$query = sprintf("%s - timestamp > %s", time(), $lifetime);
mysql_query($query);
return (true);
} // gc
} // SessionClass
【问题讨论】:
-
您将
sessionID存储在数据库中,这可以通过sql注入获得并用于登录,从而破坏了密码哈希的目的。 -
如果 IP 地址位于负载均衡器后面,则它们在会话期间也可以更改。比如他们在学校或大型企业网络中。
标签: php security session cookies