J'ai développé une classe de session PHP et l'ai testée en utilisant quelques exemples (voir le code source ci-dessous). Cela semble aller bien. Maintenant, je voudrais que cette session soit "sécurisée". J'ai trouvé un exemple de code qui est destiné à crypter un cookie (dans le livre de Courioso Expert PHP et MySQL). Voici cet extrait de code.Sécuriser les cookies dans les sessions PHP
Code pour cookie crypté
$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);
et un code similaire pour déchiffrer le cookie
Ma première question est: puis-je faire confiance à ce code. C'est à dire. est-ce vraiment sécurisé? (J'ai essayé d'autres exemples de code de ce livre et les ai trouvés plutôt bogués).
Je ne comprends pas bien comment le code pour chiffrer un cookie pourrait être intégré dans ma classe de session (soit le code ci-dessus - ou tout autre code de chiffrement des cookies). Dois-je remplacer le cookie généré automatiquement par PHP (PHPSESSID) ou générer un nouveau cookie et chiffrer ce cookie personnalisé? (Ma conjecture est la seconde est vraie, mais je voudrais être sûr).
Comment la protection via des cookies cryptés est-elle destinée à fonctionner? J'imagine l'attaque suivante: (1) si l'attaquant obtient en quelque sorte le cookie dans sa main il répond simplement avec le même cookie. D'accord. il n'a pas le mot de passe mais il a le mot de passe crypté. Plus tard, je vérifie seulement si le mot de passe chiffré est correct. Donc, si l'attaquant a le cookie: game over - peu importe si le cookie contient le mot de passe ou "seulement" le mot de passe crypté. Correct? (2) D'accord, ce problème peut être résolu en utilisant une transmission chiffrée comme SSL. Mais alors je pense que si j'utilise SLL que la transmission est de toute façon chiffrée. Je n'ai pas besoin de chiffrer le mot de passe une seconde fois en utilisant la fonction de cryptage. Correct?
Voici le code de la classe de session que j'ai déjà.
Merci
<?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
Vous stockez le 'sessionID' dans la base de données cela peut être obtenu avec l'injection sql et utilisé pour vous connecter, ce qui annule le but du hachage d'un mot de passe. – rook
L'adresse IP peut également changer pendant une session si elle se trouve derrière un équilibreur de charge. Tels que s'ils sont dans une école ou un grand réseau d'entreprise. – rook