关于session反序列化的个人理解

 什么是 php session

谈 `PHP session`之前,必须要知道什么是`session`,那么到底什么是`session`呢?

`Session`一般称为“会话控制“,简单来说就是是一种客户与网站/服务器更为安全的对话方式。一旦开启了 `session` 会话,便可以在网站的任何页面使用或保持这个会话,从而让访问者与网站之间建立了一种“对话”机制。不同语言的会话机制可能有所不同,这里仅讨论`PHP session`机制。

`PHP session`可以看做是一个特殊的变量,且该变量是用于存储关于用户会话的信息,或者更改用户会话的设置,需要注意的是,`PHP Session` 变量存储单一用户的信息,并且对于应用程序中的所有页面都是可用的,且其对应的具体 `session` 值会存储于服务器端,这也是与 `cookie`的主要区别,所以`seesion` 的安全性相对较高。


对我个人理解就是,session和cookie很相似都是用来认证信息的,但是session是存放在服务器端,cookie是存放在客户端

PHP Session 的工作流程主要包括以下几个步骤:
1. ‌**启动Session**‌:
    - 使用`session_start()`函数启动Session。如果当前不存在Session,则会创建一个新的Session,并且这个Session可以访问超全局变量`$_SESSION`数组。
2. ‌**生成Session ID**‌:
    - 当客户端首次访问服务器时,服务器会生成一个唯一的Session ID,用于标识这个客户端。
3. ‌**存储Session ID**‌:
    - Session ID通常存储在客户端的Cookie中,或者通过URL进行传递。如果浏览器禁用了Cookie,那么Session将无法正常工作。
4. ‌**存储Session数据**‌:
    - Session数据被存储在服务器上,而不是客户端。默认情况下,Session数据是以文件的形式保存在服务器上。
5. ‌**Session的使用与销毁**‌:
    - 在Session期间,服务器会持续维护该Session ID,并在每次请求中检查是否存在有效的Session ID。如果存在,则继续使用该Session ID来访问和更新Session数据;如果不存在,则创建一个新的Session并生成新的Session ID。当客户端关闭浏览器或Session超时后,服务器会销毁该Session数据。‌


`session.serialize_handler`定义的引擎有三种,如下表所示:

| 处理器名称         | 存储格式                                              |
| ------------- | ------------------------------------------------- |
| php           | 键名 + 竖线 + 经过`serialize()`函数序列化处理的值                |
| php_binary    | 键名的长度对应的 ASCII 字符 + 键名 + 经过`serialize()`函数序列化处理的值 |
| php_serialize | 经过serialize()函数序列化处理的**数组**                       |

**注:自 PHP 5.5.4 起可以使用 _php_serialize_**

上述三种处理器中,`php_serialize`在内部简单地直接使用 `serialize/unserialize`函数,并且不会有`php`和 `php_binary`所具有的限制。 使用较旧的序列化处理器导致`$_SESSION` 的索引既不能是数字也不能包含特殊字符(`|` 和 `!`)


用于处理序列化最常见的三个处理器
## php 处理器

首先来看看`session.serialize_handler`等于 `php`时候的序列化结果,demo 如下:
```php
error_reporting(0);
ini_set('session.serialize_handler','php');
session_start();
$_SESSION['session'] = $_GET['session'];
```


序列化的结果为session|s:3:"111";
`session` 为`$_SESSION['session']`的键名,`|`后为传入 GET 参数经过序列化后的值

## php_binary处理器

再来看看`session.serialize_handler`等于 `php_binary`时候的序列化结果。

```php
highlight_file(__FILE__);
error_reporting(0);
ini_set('session.serialize_handler', 'php_binary');
session_start();
$_SESSION['sessionsessionsessionsessionsession'] = $_GET['session'];
```


序列化的结果为:#sessionsessionsessionsessionsessions:6:"123456";

`#`为键名长度对应的 ASCII 的值,`sessionsessionsessionsessionsessions`为键名,s:6:"123456";为传入 GET 参数经过序列化后的值

## php_serialize 处理器

最后就是`session.serialize_handler`等于 `php_serialize`时候的序列化结果,同理,demo 如下:

```php
highlight_file(__FILE__);
error_reporting(0);
ini_set('session.serialize_handler','php_serialize');
session_start();
$_SESSION['session'] = $_GET['session'];
```

序列化的结果为:a:1:{s:7:"session";s:6:"123456";}

`a:1`表示`$_SESSION`数组中有 1 个元素,花括号里面的内容即为传入 GET 参数经过序列化后的

例题

创建两个文件
第一个能输输入session值 命名为1.php
```php
highlight_file(__FILE__);  
ini_set('session.serialize_handler', 'php_serialize');  
session_start();  
  
$_SESSION['username'] = $_GET['username'];  
echo "<pre>" . session_id();
``` 
这个处理器是php_serialize

第二个用来执行恶意代码  命名为2.php
```php 
highlight_file(__FILE__);  
session_start();  
class cmd  
{  
    public $code;  
    public function __destruct()  
    {  
        eval($this->code);  
    }  
}  
```
这个处理器虽然没有明说,但是默认就是php处理器

我们的思路是,这两个页面的session是公用的,而php_serialize处理器和php处理器在
对相同数据进行序列化的结果是不一样的,而我们就可以利用这个区别来构造恶意代码
先对执行恶意代码的页面进行序列化

O:3:"cmd":1:{s:4:"code";s:10:"phpinfo();";}
而我们回头看php处理器序列化的规则,`|`后为传入 GET 参数经过序列化后的值
所以我们只需要在序列化的结果前面加上一个|就可以了


在1.php传参useranme=|O:3:"cmd":1:{s:4:"code";s:10:"phpinfo();";}
在2.php刷新页面就发现可以执行恶意代码了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值