【问题标题】:The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,'会话 id 太长或包含非法字符,有效字符为 a-z、A-Z、0-9 和 '-,'
【发布时间】:2011-03-12 06:38:01
【问题描述】:

如何解决:

警告: session_start() [function.session-start]: session id太长或包含非法字符,有效字符为az, AZ, 0-9 和'-,' in .....在线3

警告:session_start() [function.session-start]:无法发送会话 cookie - 标头已由第 3 行 ..... 中的(输出开始于......:3)发送

警告:session_start() [function.session-start]:无法发送会话缓存限制器 - 第 3 行的 ..... 中已发送标头(输出开始于.....:3)

【问题讨论】:

  • 会话 ID 中没有非法字符?

标签: session php


【解决方案1】:

这是一个信息漏洞:恶意攻击者可能会更改cookie并将非法字符分配给PHPSESSID以暴露此PHP警告,其中实际上包含文件路径和用户名等多汁信息!

【讨论】:

  • 我的会话似乎处于这种“调查”之下,我很欣赏这是一个旧答案,但是您对如何锁定此信息有任何指示吗?我的错误日志只对服务器端开放,而不是更广泛的网络,我需要/应该做更多吗?
  • @Martin 要锁定此错误或保护您的脚本,您必须在 session_start() 之前检查 cookie,检查变量 $_COOKIE['PHPSESSID']) 是否包含非法字符,如果它那么你的脚本应该重新加载页面或者只是删除它们,如果没有,那么你可以安全地继续。
  • 值得一提的是owasp.org docs只需关闭错误报告功能,您的代码就不会出现错误,即可防止此漏洞。
【解决方案2】:

查看此session_start() discussion 以获得解决方法:

session_start() 如果 PHPSESSID 包含非法字符,则生成警告

警告:session_start() [function.session-start]:会话id包含非法字符,有效字符是/home/para/dev/mon_site/header中的az、AZ、0-9和'-,'。 php 在第 17 行

为了避免我写了这个:

   <?php
        function my_session_start()
        {
            if (ini_get('session.use_cookies') && isset($_COOKIE['PHPSESSID'])) {
                $sessid = $_COOKIE['PHPSESSID'];
            } elseif (!ini_get('session.use_only_cookies') && isset($_GET['PHPSESSID'])) {
                $sessid = $_GET['PHPSESSID'];
            } else {
                session_start();
                return false;
            }

           if (!preg_match('/^[a-z0-9]{32}$/', $sessid)) {
                return false;
            }
            session_start();

           return true;
        }
    ?>

【讨论】:

  • 你如何在PHPSESSID 中得到非法字符?不是PHP自动生成的吗?
  • 它们是,但是将您链接到生成的会话 ID 的 cookie 是客户端。如果该 cookie 更改为无效格式(有人试图利用某些东西)PHP 会注意到它。
  • 很好的提示,但是如果有人依赖 session_autostart 功能...如何用您在此处建议的功能覆盖 session_start() 功能?
  • 您是否在正则表达式中缺少-,因为这是一个有效字符。
  • 原始答案引入了一个潜在的安全漏洞 - 我已经编辑修复它。
【解决方案3】:

有针对此问题的错误报告 (https://bugs.php.net/bug.php?id=68063)

您可以检查您的 session_start 是否成功并在需要时生成 id:

$ok = @session_start();
if(!$ok){
session_regenerate_id(true); // replace the Session ID
session_start(); 
}

【讨论】:

  • 它对我有用,让我知道脚本是保存还是 melicious?
  • 我试过这个并得到:session_regenerate_id(): Cannot regenerate session id - session is not active in FILE on line X 后跟与问题标题相同的错误...
  • @conner_bw 这似乎是另一个问题,但请检查此问题:stackoverflow.com/questions/31436949/… 这似乎相似并且有一个可接受的答案。
【解决方案4】:

我编辑了 Andron's previous solution! (修复返回值)并添加了 my_session_start() 的评估输出。以前的解决方案解决了错误消息的问题,但我需要启动会话。

/**
 * @return boolean return TRUE if a session was successfully started
 */        
function my_session_start()
{
      $sn = session_name();
      if (isset($_COOKIE[$sn])) {
          $sessid = $_COOKIE[$sn];
      } else if (isset($_GET[$sn])) {
          $sessid = $_GET[$sn];
      } else {
          return session_start();
      }

     if (!preg_match('/^[a-zA-Z0-9,\-]{22,40}$/', $sessid)) {
          return false;
      }
      return session_start();
}

if ( !my_session_start() ) {
    session_id( uniqid() );
    session_start();
    session_regenerate_id();
}

【讨论】:

    【解决方案5】:

    我建议使用“更正确”版本的函数。

    几个注意事项:

    1. 更正确的正则表达式(允许 a-z A-Z 0-9 、(逗号)和 -(减号)范围内的字符)如 here 所述。
      正则表达式取决于 php ini 设置,如 herehere 所述。
    2. 使用会话名称方法

    所以更新后的版本是这样的:

    <?php
        function my_session_start()
        {
            $sn = session_name();
            if (isset($_COOKIE[$sn])) {
                $sessid = $_COOKIE[$sn];
            } else if (isset($_GET[$sn])) {
                $sessid = $_GET[$sn];
            } else {
                session_start();
                return false;
            }
    
           if (!preg_match('/^[a-zA-Z0-9,\-]{22,40}$/', $sessid)) {
                return false;
            }
            session_start();
    
           return true;
        }
    ?>
    

    【讨论】:

    • 这应该检查 PHP ini 设置。在大多数健全的配置中,会话永远不会在 GET 参数中进行,因此无需检查它们。
    【解决方案6】:

    如果您不关心其他用户(例如:如果它是私有接口),只需检查您的浏览器,找到 cookie PHPSESSID(或您给它的名称),删除它,然后刷新。

    【讨论】:

      【解决方案7】:

      我想出了这个简单的方法,只需尝试捕获会话开始,如果有问题重新生成会话。

      try {
         session_start();
      } catch(ErrorExpression $e) {
         session_regenerate_id();
         session_start();
      } 
      

      【讨论】:

      • 您无法使用 try-catch 捕获警告。
      猜你喜欢
      • 2011-06-13
      • 1970-01-01
      • 1970-01-01
      • 2019-11-22
      • 1970-01-01
      • 1970-01-01
      • 2012-08-05
      • 2010-12-16
      • 1970-01-01
      相关资源
      最近更新 更多