我注意到發佈的手動解碼 session 的解決方案並不完美,所以我貢獻了一個更穩健的解決方案。
preg_match 解決方案永遠行不通。找到可能破壞反序列化的案例並不難。
在 jason-joeymail 的情況下,它會在
<?php
$_SESSION["test"] = ";oops|";
?>
以下是我的解決方案。它不使用正規表示式,而是使用序列化運算的可逆性以及序列化認為完成時會忽略所有後續輸入的「功能」。它絕不是一個美觀或特別快速的解決方案,但它是一個更穩健的解決方案。
我已為 "php" 和 "php_binary" 新增了一個反序列化程式。為 "wddx" 新增一個反序列化程式應該是微不足道的。
<?php
class Session {
public static function unserialize($session_data) {
$method = ini_get("session.serialize_handler");
switch ($method) {
case "php":
return self::unserialize_php($session_data);
break;
case "php_binary":
return self::unserialize_phpbinary($session_data);
break;
default:
throw new Exception("不支援的 session.serialize_handler: " . $method . ". 支援:php, php_binary");
}
}
private static function unserialize_php($session_data) {
$return_data = array();
$offset = 0;
while ($offset < strlen($session_data)) {
if (!strstr(substr($session_data, $offset), "|")) {
throw new Exception("無效資料,剩餘: " . substr($session_data, $offset));
}
$pos = strpos($session_data, "|", $offset);
$num = $pos - $offset;
$varname = substr($session_data, $offset, $num);
$offset += $num + 1;
$data = unserialize(substr($session_data, $offset));
$return_data[$varname] = $data;
$offset += strlen(serialize($data));
}
return $return_data;
}
private static function unserialize_phpbinary($session_data) {
$return_data = array();
$offset = 0;
while ($offset < strlen($session_data)) {
$num = ord($session_data[$offset]);
$offset += 1;
$varname = substr($session_data, $offset, $num);
$offset += $num;
$data = unserialize(substr($session_data, $offset));
$return_data[$varname] = $data;
$offset += strlen(serialize($data));
}
return $return_data;
}
}
?>
用法
<?php
Session::unserialize(session_encode());
?>