0x01:Session 简介
Session 是在 Cookie 的基础上发展的,其主要功能和 Cookie 一样,都是为了解决 HTTP 无状态的痛点,和 Cookie 不同的是,它是将大部分数据存储在了服务端,而只给用户一个 SESSID,解决了 Cookie 存放在客户端造成的两大问题:
-
占用客户端过大的存储空间。 -> 浏览器在客户端存放的 Cookie 过大。
-
增加 HTTP 通信的成本。 -> 客户端每次请求都要带上大量 Cookie。
就安全而言,其实还解决了 Cookie 可以在本地修改的问题(Cookie 放在服务端,你怎么改?)。不过伴随而来的也有缺点,Session 会消耗服务端的存储资源(不过一个文件都很小,可以忽略)。
0x02:Session 的工作原理
0x0201:Session 的工作原理 — 理论篇
-
创建 Session: 当用户首次访问网站时,服务器会为该用户创建一个唯一的 Session ID,并将其通过 Cookie(或其他机制,如 URL 重写)发送给用户的浏览。这个 Session ID 是服务器用来识别不同用户会话的关键。
-
存储 Session 数据: 服务器会在其内存中(如数据库、文件系统等持久化存储中,取决于具体实现)为该 Session ID 关联一个存储空间,用于存储该用户会话期间的所有数据。
-
会话管理: 在用户与服务器进行后续交互时,浏览器会自动将 Session ID 包含在请求头中发送给服务器。服务器通过解析这个 Session ID,就可以从对应的存储空间中检索出用户的会话数据,从而实现状态的持续跟踪。
-
Session 超时与销毁: 为了安全起见,Session 通常会有一个超时时间限制。如果用户一定时间内没有与服务器进行任何交互,Session 就会被视为过期并被销毁,相应的存储空间也会被释放。此外,用户也可以主动注销登录,此时服务器也会销毁对应的 Session。
0x0202:Session 的工作原理 — 实验篇
实验工具准备
PHP 运行环境:phpstudy_x64_8.1.1.3.zip(Apache2.4.39 + PHP 5.3.29nts)
Session 实验源码包(附配置流程):SessionLab01.zip
实验环境的搭建流程我一起放在了 SessionLab01.zip 中了,这里就不多说了,下面直接开始实验。
首先,访问实验环境,并打开 ”开发者工具“ 进行抓包:
可以看到,一进入站点,服务端就给我们分配了一个 SESSID 并通过 Cookie 发送到了我们的浏览器上。
接下来,我们尝试进行登录,看看发送的请求包会发生什么变化:
可以看到,页面成功跳转到了登录成功的样式。但是发送给服务端的 Cookie 中依旧只存在一个 PHPSESSID 字段。在前面的理论篇中,我们了解到,Session 的值是存储在服务端的,接下来我们去服务端看看这个存储 Session 的文件。
服务端,即提供服务的终端嘛,在上面的实验中,我们访问的是 127.0.0.1 这个服务端,说白了,就是本机(本次实验是在主机上通过 PhpStudy 中的 Apache 服务运行的)。
从上面的实验中得知服务端分配给我们的 Session ID 是 ujaf4rqfopkoi4i6e08s04skk5
,我们利用 EveryThing(一款本地资源搜索工具) 这款工具搜索一下:
可以看到,服务端果然存储了这么一个 Session 文件,该 Session 文件中保存了用户传递过来的登录信息。
接下来我们使用相同的浏览器打开一个新页面,并重新访问实验环境:
可以发现,服务端依旧认为我们处于登录状态,且我们发送给服务端的依旧只是 SessionID。
至此,我们已经见识到了创建 Session、存储 Session 、会话管理,这几个部分。在销毁 Session 前,再做一个小实验:
我们用一个新的浏览器,打开实验环境,因为浏览器之间 Cookie 是不通的,所以服务端肯定认为我们未登录,如下(Chrome 浏览器):
这个时候我们打开 ”开发者工具“,并将之前获得的 Session ID 手动添加进去:
刷新页面,可以看到,原本未登录的浏览器,其状态也变成了登录:
OK,这个小实验完成了,算是一个引子吧( XSS 攻击 了解一下)。
最后是销毁 Session,点击一下页面中的 ”Destruction Of Account" 即可:
可以看到,两个客户端都显示了退出登录的状态。
0x03:关于 Session 的几个知识点
0x0301:Session 和 Cookie 工作流程对比:
Cookie:当用户访问目标服务器时,每次的访问都会带上username
和password
,表明自己是已经登录过的用户,而且随着操作的变多,Cookie 的字段可能会越来越长,导致 HTTP 通信成本和本地存储空间都增大。
Session:用户第一次登录时,服务器会给用户分配一个随机的 SESSID,后面用户只要拿着这个 SESSID,服务器就可以知道你是谁,你做了什么,而且随着操作变多,数据都是存放在服务器那边,你本地保存的依旧只是那短短的一个 SESSID。