PHP 防止会话固定/劫持

Posted

技术标签:

【中文标题】PHP 防止会话固定/劫持【英文标题】:PHP Protecting from Session Fixation/Hijacking 【发布时间】:2012-02-20 02:15:02 【问题描述】:

我正在维护一个在数据库中存储信用卡号的低流量商店网站。这是不对的(甚至我认为是合法的),所以我正在改变数字的存储方式。

网站的结构方式,信用卡信息页面发布到自己,验证数据,将数据存储在数据库中,然后将用户重定向到cc验证页面,在该页面验证cc并下订单。之后,它们再次被重定向到订单完成页面。无论如何,要从 cc 信息页面获取 cc 号码到验证页面,我正在考虑使用会话,但我担心漏洞并试图调查它们(我正在阅读 this ref. 和 this one )。我可以在会话中存储 cc 号码,在下一页检索它,使用它,然后 unset() 它,它在几秒钟内就消失了(还要注意,这些页面使用 SSL)。比如:

抄送信息页面:

session_start();
$_SESSION['card_number'] = $_POST['cardnumber']; //please tell me if there are vulnerabilities here setting directly from $_POST
...
header(sprintf("Location: %s", $insertGoTo));

cc验证页面:

session_start();
//retrieve $_SESSION['card_number']
unset($_SESSION['card_number']);

只有 card# 被存储在 session 中,其余的 cc 信息在数据库中。虽然我不认为有人可以仅使用 cc# 做很多事情,但仍应尽可能确保它的安全。

鉴于我使用 session.use_trans_sid = 0session.use_only_cookies = 1(会话标识符仅通过 cookie 而不是 URL 处理(不知道为什么我需要两者)),并且考虑到我使用这个特定的会话变量,这段代码是否容易受到会话固定?在这种情况下,我将 cc# 设置为 session 重新生成会话 ID(之后还是之前?)是否有益?我猜是的,并且由于此时协议是 SSL,我还猜测一旦重新生成 session,我就受到 SSL 的保护?

所以,我的主要问题是,按照我的网站的这些指南,熟练的攻击者是否会相当困难地修复/劫持会话来获取用户的 cc# 存在的时间量(大约 3-15 秒) ?如果没有,如果可能的话,我怎样才能做到这一点?

【问题讨论】:

session.use_trans_sid 使 php 自动修改输出 html,将 session id 添加到某些 url。 session.use_only_cookies 使 php 只接受来自 cookie 标头的会话 ID。如果没有这个设置,php 会按照 cookie、post 或 get 的顺序查找并接受它。 另外,谷歌的 php 会话固定文章。我不认为你会在这里得到一个正确的主题的答案。 @chris 你是说我不需要session.use_trans_sid = 0 如果您担心安全问题,您通常希望将其关闭。你说你不知道为什么需要这两个指令,所以我解释了它们的区别。 @chris 我明白了,谢谢。我想我不明白为什么如果session.use_only_cookies = 1 会在url 中添加会话ID。这似乎是矛盾的。 【参考方案1】:

即使会话被劫持,如果您的脚本允许用户查看 CC 编号,或者您的站点上存在会话转储,此人也只能获取 CC 编号。

另外请记住,将抄送号码以明文形式存储在数据库中可能是非法的。如果您担心数据被盗,请务必对所有敏感数据进行编码或加密。

祝你好运!

【讨论】:

抱歉回复晚了。 “即使会话被劫持,如果您的脚本允许用户查看 CC 号码,该人也只能获得 CC 号码” - 这确实是我需要听到的,谢谢! “或者你的网站上有一个会话转储” - 你的意思是什么? 类似 var_dump($_SESSION);用户可以看到会话的内容。【参考方案2】:

您根本不应该存储卡号。默认情况下,PHP 将会话存储在您机器上的文件中。如果您的机器遭到入侵,有人可能会从会话文件中窃取信用卡号。

您应该做的是获取所有信息并将其直接传递给像 Authorize.Net 这样的信用卡处理器,或者使用允许用户在该服务托管的域上付款的服务,然后将它们返回给您一个授权码,这样你就知道他们付费了(PayPal 有这样的服务,我知道他们不是最好的,但还有其他的)

要获取信息,您至少需要具备一定程度的 PCI 合规性。存储卡信息完全需要更高的级别。

关于 PCI 的内容有很多。这是上面的维基:http://en.wikipedia.org/wiki/Payment_Card_Industry_Data_Security_Standard

【讨论】:

同意。完全不存储信用卡号码可以抵消受损系统的责任。我想知道为什么索尼 Playstation 存储它们,并在几个月前被黑客入侵时实际上承担了责任。 服务器上的会话文件是否继续保存该信息,即使在我unset() 之后?我同意你根本不存储它。最初的开发人员是这样设计的,我对此不太满意,因为他们本可以在同一页面内轻松完成。我想最好的办法就是整合这两个页面。谢谢你的回答。 @Shredder 不,在您 unset 一个 SESSION 变量之后,该信息不再在该关联的会话文件中,但最好也使用 session_destroy,它会破坏注册到会话的所有数据. 会话文件被编码......它也不是很容易解码。如果我没记错的话,PHP 在运行时会生成一个密钥,所以磁盘上的会话数据应该是安全的...... @AdamSack 太棒了!你有任何资源来支持它吗?

以上是关于PHP 防止会话固定/劫持的主要内容,如果未能解决你的问题,请参考以下文章

https如何防止会话劫持

php防止会话固定攻击

防止会话劫持

PHP安全编程

如何防止asp.net应用程序会话劫持?

使用 Kohana 避免会话劫持