在我们面试的时候,面试官问及 XSS 漏洞的时候,我们常常会说比如劫持 Cookie,问及防御方法的时候,又常常会说设置
httponly
,本篇文章将从代码层面简单的普及 Session 和 Cookie 的生成过程,及防御的方法,希望看到这篇文章后,下一次遇到面试官的时候,你能够自豪的跟他说我知道防御 XSS 漏洞,能够把流程讲清楚,把原理讲明白!
先从 Cookie 讲起
什么是 Cookie 呢?简单来说,当用户访问某个网站时,该网站的服务器会生成一个Cookie并发送到用户的浏览器,**浏览器将其存储在本地计算机上。**之后,每当用户再次访问该网站时,浏览器会将Cookie发送回服务器,服务器通过这些信息来识别用户,维持用户的登录状态,或者记录用户的浏览习惯、购物车。
在 PHP 中,我们常常使用
setcookie
函数生成用户的 cookie,其函数解释如下:
setcookie()
是 PHP 中的一个函数,用于设置 cookie 的各种属性,并向客户端发送 cookie。cookie 是一种机制,允许服务器向浏览器发送少量数据,并且浏览器会存储这些数据,下次访问同一网站时会发送回服务器。
函数的基本语法如下:
setcookie(name, value, expires, path, domain, secure, httponly);
参数说明:
name
:cookie 的名称。value
:cookie 的值。expires
:cookie 过期的 Unix 时间戳。如果未设置或设置为0
,则 cookie 在浏览器会话结束时过期。path
:cookie 在哪个路径下有效。默认为当前脚本的目录以及所有子目录。domain
:cookie 在哪个域名下有效。注意,如果设置此参数,cookie 只会在指定的域下工作。secure
:如果设置为true
,cookie 只有在 HTTPS 连接下才会被发送。httponly
:如果设置为true
,cookie 将不会通过客户端脚本访问(如 JavaScript),有助于减少跨站脚本攻击(XSS)。
使用实例如下:
setcookie("user", "JohnDoe", time() + 3600, "/", "example.com", true, true);
上面的代码会设置一个名为
user
的 cookie,值为
JohnDoe
,有效期为 1 小时,在整个网站的路径下有效,仅适用于
example.com
域,并且需要通过安全的 HTTPS 连接传输,同时禁止通过客户端脚本访问。
为什么会有 Session
众所周知,Session相对于Cookie来说,由于其服务器端存储的特性,通常被认为更安全。其安全性体现在与,**Session数据存储在服务器上,这意味着它们不受浏览器设置的影响,并且不容易受到XSS攻击。**同时,Session可以在用户会话期间持续存在,而不需要每次页面加载时都重新发送Cookie。
在 PHP 中,我们常常使用
session_start()
函数来开始或继续一个现有的会话,用
session_regenerate_id()
防止会话劫持。
Session 与 Cookie 的区别如下:
Cookie
Session
存储位置
Cookie存储在用户的浏览器中,
Session数据存储在服务器上,这意味着它们不受浏览器设置的影响
安全性
如果Cookie没有设置为HttpOnly,那么JavaScript可以读取Cookie
Session通常通过一个会话ID来识别,这个ID在每次请求时都会发送到客户端。如果会话ID被窃取,攻击者可以使用它来访问用户的会话。
持久性
Cookie在每次HTTP请求和响应中都会被发送
Session可以在用户会话期间持续存在,而不需要每次页面加载时都重新发送Cookie。
跨域问题
由于同源策略(SOP),Cookie通常受到同源限制
Session不受SOP的限制,可以在不同域间使用。
01- 前端代码编写
创建文件
/session/index.html
,用以提交用户名及密码,发送数据给到后端验证,实验代码如下:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>登录示例</title>
</head>
<body>
<form action="login.php" method="post">
用户名:<input type="text" name="username" required>
密码:<input type="password" name="password" required>
<input type="submit" value="登录">
</form>
</body>
</html>
前端页面反馈如下,麻雀虽小,五脏俱全:
02-后端 Session 生成
创建后端处理 php 代码
login.php
,用以在通过验证的用户名和密码后,创建 Session 会话 ID,实验代码如下:
<?php
// 模拟用户数据库
$users = array(
'user1' => 'password1',
'user2' => 'password2'
);
// 从表单中获取用户名和密码
$username =$_POST['username'];
$password =$_POST['password'];
// 验证用户名和密码
if (isset($users[$username]) && $users[$username] === $password) {
// 生成安全的会话ID
session_start();
session_regenerate_id();
$_SESSION['loggedin'] = true;
$_SESSION['username'] =$username;
// 设置 session ID 到 Cookie
setcookie(session_name(), session_id(), time() + 3600, '/', '', true, true);
echo '<pre style="color: green; font-size: 18px;">';
echo '登录成功,您的会话信息如下:';
echo '<br><code>' . htmlspecialchars($_COOKIE[session_name()]) . '</code>';
echo '</pre>';
} else {
echo '<pre style="color: red; font-size: 18px;">';
echo '登录失败,用户名或密码错误。';
echo '</pre>';
}
?>
03-Session 会话使用
在我们后端
login.php
生成完 Session 会话后,我们访问目标网站下的其他页面,比如
info.php
,需要通过 Session 去验证我们的身份,其后端代码如下:
<?php
// 检查会话是否已启动
if (!isset($_COOKIE[session_name()])) {
// 如果会话未启动,重定向到登录页面
header('Location: login.php');
exit;
}
// 开始会话
session_start();
// 检查用户是否已登录
if (!isset($_SESSION['loggedin']) || !$_SESSION['loggedin']) {
// 如果用户未登录,重定向到登录页面
header('Location: login.php');
exit;
}
// 显示用户信息
echo '<pre style="color: green; font-size: 18px;">';
echo '欢迎,' . htmlspecialchars($_SESSION['username']) . '!';
echo '</pre>';
?>
04-实验会话使用
首先我们通过表单数据,构造 POST 型请求,将用户名
user1
和密码
password1
以 POST 型提交,服务器端返回数据包如下:
此时当后端验证完成后,会发出
set-cookie
的命令,将
sessionID
进行设置后发送给前端浏览器。
如果我们发送多次请求,会发现每次进行登录的请求时,都会重新设置
sessionID
,此时我们有多个
sessionID
,都是指向用户
user1
。
经过测试,这些
sessionid
都是指向用户
user1
,因此会发现这种重复性的登陆行为,并没有保障用户数据的安全性。
旧的
sessionid
并未销毁,仍旧可被识别:
这是因为我们在设置的过程中,并没有使用的相应识别机制,在重复提交登录表单的时候进行旧的 ID 的销毁,但是由于
sessionID
的爆破难度较高,因此安全性并不会受到较大的影响。
如何设置 httponly 来保证
**sessionID**
的安全性:
在之前的后端代码中,有这样一行内容:
// 设置 session ID 到 Cookie
setcookie(session_name(), session_id(), time() + 3600, '/', '', true, true);
最后两个参数
true
,保证了首先数据包只有在
https
下才能传送,保障了
cookie
不会被恶意的监听到,比如在防御中间人攻击上起到了一定的保护作用,其次第二个
true
,设置了
httponly
这样即使网站出现了 XSS 漏洞,也能保障我们的
cookie
不被黑客窃取,两者结合保障了会话的安全性。
总结
在本篇文章中,我们首先从
cookie
讲起,理解了
session
和
cookie
的不同,
session
为什么比
cookie
安全,以及如何去设置
http-only
及其设置的效果,希望对大家理解
cookie
和
session
有所帮助。
版权归原作者 颠勺厨子 所有, 如有侵权,请联系我们删除。