2016-10-05 44 views
7

我发现了一些奇怪的行为 - 我很感兴趣 - 任何人都可以在这个问题上找到答案。

概述

花了一些时间今晨找到其产生的$_SESSION阵列清空中的错误的原因。最终发现它的底部,发现当为$_SESSION变量之一定义索引时,&被用于连接而不是.。它只在两个特定字符串为& ed时破坏,其他字符串导致无意义键,但$_SESSION未空。

这是运行在PHP5.5.9-1ubuntu4.20和本地PHP5.6.15。

亲自试一试!

使用下面的示例代码,

  1. 运行设置session.php文件
  2. 运行检查session.php文件 - 所有的好
  3. 运行突破session.php文件 - 至今仍然不错...
  4. 运行check-session.php再次 - $_SESSION现在是空的!

实施例代码

设定session.php文件

session_start(); 

$_SESSION = [ 
    'colour' => 'blue', 
    'shape' => 'round', 
    'size' => 'medium' 
]; 

检查session.php文件

session_start(); 

echo '<pre>'; 
print_r($_SESSION); 

破裂session.php文件

session_start(); 

$killer_string = 'Admin_CH_1_' & '101_'; 
$_SESSION[$killer_string] = null; 

echo '<pre>'; 
print_r($_SESSION); 

我的猜测

我猜位运算结果在一个字符串,在这种情况下$killer_string的结果,导致PHP上火当它试图存储$_SESSION阵列在服务器上。奇怪的是,$killer_string不再是作为$_SESSION中的子数组的键的杀手。

想法?

我知道代码实际上没有意义,所以PHP没有错。然而,我很好奇幕后究竟发生了什么,以及这是什么造成的......

干杯!

+1

您是否var_dump($ killer_string);'?产量'☺!I' – AbraCadaver

+2

您使用的是什么PHP版本?我只用5.6.25进行了测试,'$ killer_string'被设置为一个类似于@AbraCadaver的字符串的数组键' –

+1

我的结果与@MichaelBerkowski在php-7中的结果相同 – arkascha

回答

5

这里有一个简单的测试案例(see it in action):

<?php 
header('Content-Type: text/plain'); 
ob_start(); 

session_start(); 
$_SESSION = [ 
    'colour'    => 'blue', 
    'shape'    => 'round', 
    'size'     => 'medium', 
    //'Admin_CH_1_' & '101_' => 'Gone', 
    chr(0x01) . chr(0x20) . chr(0x21) . chr(0x49) => 'Gone', 
]; 
var_dump($_SESSION); 
session_write_close(); 

session_start(); 
var_dump($_SESSION); 
ob_end_flush(); 

如果检查会议文件,你可以看到它具有零个字节。

到目前为止,我的最佳猜测(直到某个人更聪明地与具有特定内部结构的PHP github库共享链接)是您无意中推动了会话序列化代码的限制。这样的代码假定键是非二进制字符串。有一定的验证(纯数字键触发跳过数字键通知),但它不包括所有可能的格式错误的输入。在某个时候它只是崩溃。

这得到由事实的支持改变修复问题上的序列化方法:

ini_set('session.serialize_handler', 'php_serialize'); 

session.serialize_handler documentation我们可以看到:

较早的序列化处理不能存储的数字指标,也没有串索引 在$_SESSION中包含特殊字符(|和!)。使用 php_serialize可以在 脚本关闭时避免数字索引或特殊字符错误。默认为php

+0

感谢您的回复。原来,这种行为已经存在,只是一个棘手的事情来搜索! – Steve

相关问题