2010-10-11 6 views
0

Я разработал класс сеанса PHP и протестировал его с помощью нескольких примеров (см. Исходный код ниже). Кажется, все в порядке. Теперь я хотел бы сделать этот сеанс «безопасным». Я нашел пример кода, который предназначен для шифрования файла cookie (в книге Courioso Expert PHP и MySQL). Вот этот фрагмент кода.Безопасные файлы cookie на сеансах PHP

Код для зашифрованного печенья

$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 может быть встроен в мой класс сеанса (либо код выше, либо любой другой код шифрования файлов cookie). Должен ли я заменить файл cookie, который автоматически генерируется PHP (PHPSESSID), или должен генерировать новый файл cookie и шифровать этот настраиваемый файл cookie? (Мое предположение - второе, правда, но я хотел бы быть уверенным).

Как защищается с помощью зашифрованных файлов cookie? Я предполагаю следующую атаку: (1), если злоумышленник каким-то образом получит куки-файл в своей руке, он просто отвечает тем же файлом-печеньем. Хорошо. у него нет пароля, но у него есть зашифрованный пароль. Позже я проверяю, только если зашифрованный пароль в порядке. Так что если у атакующего есть файл 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 
+0

Вы сохраняете 'sessionID' в базе данных, это можно получить с помощью sql-инъекции и использовать для входа в систему, таким образом побеждая цель хэширования пароля. – rook

+0

Также IP-адрес может меняться во время сеанса, если они находятся за балансировщиком нагрузки. Например, если они находятся в школьной или крупной корпоративной сети. – rook

ответ

1

Если я могу отвлекся от вашего первоначального вопроса. Вы должны не хранить пароли в cookie. Файл cookie хранится на стороне клиента. Не важно, что такое шифрование, гораздо более безопасным вариантом было бы сохранить ваши данные аутентификации пользователя в сеансе и просто сохранить токен в cookie стороне клиента, который будет вызывать соответствующий сеанс.

+0

Согласитесь, что он должен, вероятно, поместить пароль в сеанс, но это не всегда «гораздо более безопасный вариант». Например, на некоторых настройках общего хоста информация о сеансе читается всем пользователям на машине. –

2

Причина использования сеансов : не хранить конфиденциальные данные на стороне клиента, а хранить их на стороне сервера. И единственным подключением к этим данным является идентификатор сеанса, который, как мы надеемся, периодически менялся и с каждой аутентификацией и сменой полномочий.

Если вы хотите сохранить эти данные на стороне клиента (независимо от того, в какой форме или в представлении), вы сделали бы противоположное тому, для каких сеансов предназначены для использования. Поэтому не делайте этого и сохраняйте свои конфиденциальные данные на стороне сервера.

Смежные вопросы