PHP防止会话固定/劫持

3
我正在维护一个低流量的商店网站,该网站将信用卡号存储在数据库中。这不是正确的做法(我甚至认为这是非法的),因此我正在改变存储方式。
网站的结构是这样的,信用卡信息页面会提交到自己,验证数据,将数据存储在数据库中,然后将用户重定向到cc验证页面,在那里进行cc验证并下单。之后,他们再次被重定向到订单完成页面。无论如何,为了将cc号码从cc信息页面传递到验证页面,我考虑使用session,但我担心存在漏洞,并正在研究它们(我正在阅读这个参考资料这个)。我可以将cc号码存储在session中,在下一页上检索它,使用它,然后unset()它,几秒钟后它就消失了(还要注意,这些页面使用SSL)。例如:
cc信息页面:
session_start();
$_SESSION['card_number'] = $_POST['cardnumber']; //please tell me if there are vulnerabilities here setting directly from $_POST
...
header(sprintf("Location: %s", $insertGoTo));

信用卡验证页面:

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

只有信用卡号被存储在session中,其余的信用卡信息存储在数据库中。虽然我认为仅凭信用卡号可能无法做太多事情,但应该尽可能保护其安全性。
假设我使用了“session.use_trans_sid = 0”和“session.use_only_cookies = 1”(其中会话标识符仅通过cookie处理而不是URL(不确定为什么需要两者)),并且考虑到我正在使用此特定的会话变量,在这种情况下,这段代码是否容易受到会话固定攻击?如果在设置cc#之前或之后重新生成会话ID是否有益?我猜想是的,并且由于此时协议为SSL,一旦会话已被重新生成,我也会得到SSL保护?
因此,我的主要问题是,遵循这些指南,对于一个熟练的攻击者来说,是否很难固定/劫持会话以获取用户的信用卡号码,至少存在3-15秒的时间?如果不行,如有可能,我该如何达到这个目标?

session.use_trans_sid 让 PHP 自动修改输出的 HTML,将会话 ID 添加到特定的 URL 中。 session.use_only_cookies 只让 PHP 接受来自 cookie 标头的会话 ID。如果没有这个设置,PHP 会按照 cookie、post 或 get 的顺序寻找和接受它。 - goat
如果安全是一个问题,通常情况下您希望它关闭。您说您不知道为什么需要这两个指令,所以我解释了它们的区别。 - goat
@chris 我明白了,谢谢。我想我不明白为什么如果 session.use_only_cookies = 1,它会将会话 ID 添加到 URL 中。这似乎是矛盾的。 - Nick Rolando
你说得对,同时打开两个选项的情况确实很少见,但也可能有特殊情况需要这样做。你可能不想在当前请求中接受url会话id,但可能希望为当前响应的url添加一个id。此外,您可以通过session_start($session_id_from_wherever_you_want);手动告诉php sess id,也许您从url中获取了它,但需要在使用该url id恢复会话之前实现自己的自定义验证逻辑和环境。 - goat
@chris 哦,好的。谢谢你为我澄清这个问题 :) - Nick Rolando
显示剩余2条评论
2个回答

2
即使会话被劫持,只有在您的脚本允许用户查看信用卡号码或者在您的网站上存在会话转储时,才会有人获取到信用卡号码。
同时,请注意以明文形式存储信用卡号码可能是非法的。如果您担心数据盗窃,请确保对所有敏感数据进行编码或加密。
祝好运!

抱歉回复晚了。"即使会话被劫持,只有在您的脚本允许用户查看信用卡号码时,该人才能获取信用卡号码" - 这真的是我需要听到的,谢谢! - Nick Rolando
“或者您的网站上有会话崩溃的转储” - 这是什么意思? - Nick Rolando
类似于 var_dump($_SESSION); 这样的代码可以让用户可见会话内容。 - Adam Fowler

0

您绝不能将信用卡号存储在任何地方。默认情况下,PHP会将会话存储在您机器上的一个文件中。如果您的机器遭到攻击,某人可能会从会话文件中窃取信用卡号。

您应该做的是将所有信息直接传递给信用卡处理器,如Authorize.Net,或使用允许用户在由服务托管的域上支付,然后返回带有授权代码的用户至您那里以便您知道他们已经付款(PayPal有这样的服务,我知道它们不是最好的,但还有其他选择)

捕获信息需要您具备至少一定程度的PCI合规性。而要存储卡片信息则需要更高级别的合规性。

有关PCI的信息很多。以下是关于PCI的维基百科链接:http://en.wikipedia.org/wiki/Payment_Card_Industry_Data_Security_Standard


同意。根本不存储信用卡号码可以消除系统被攻击的责任。我想知道为什么索尼Playstation存储了它们,并实际承担了责任,当他们在几个月前被黑客攻击时。 - Mike Purcell
服务器上的会话文件是否会在我使用 unset() 后继续保留该信息?我同意你不要将其存储。原始开发人员是这样设计它的,我对此并不满意,因为他们本可以在同一页内轻松完成。我想最好的方法就是将两个页面整合起来。感谢你的回答。 - Nick Rolando
@Shredder 不,当您使用 unset 删除 SESSION 变量后,该信息将不再存在于相关的会话文件中,但最好还是使用 session_destroy,它可以销毁与会话注册的所有数据。 - Josh
会话文件是经过编码的...而且也不像可以轻易地解码。如果我没记错的话,PHP会在运行时生成一个密钥,因此磁盘上的会话数据应该是安全的... - Adam Fowler
@AdamSack 非常棒!你有任何支持这个观点的资源吗? - Nick Rolando
生成时的密钥意味着在服务器重启之前它将具有相同的密钥,这将使攻击者有充足的时间来解密该密钥。但至少它是加密的。但无论如何,我在使用信用卡号后立即使用unset()函数使其失效,所以应该没问题。 - Nick Rolando

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接