很明显,我们大多数PHP程序员都不希望我们发布的作品被黑客以我们不希望的方式攻击或利用。因此,在询问如何对抗会话劫持时,我会格外小心。我知道有session_regenerate_id()函数来部分对抗会话劫持,但我更好奇的是我遇到的另一种方法:
作为一个用户登录到网站,你采取他们的user_id(或另一个更秘密,预定义的加密字符串)(这是未知的普通用户)作为一个字符串,你用随机预定义的符号,md5()字符串,并设置它为$_SESSION['user_code'] = $that_string;当这个用户进入一个页面时,如果不匹配,你可以重复这个过程,用$_SESSION['user_code']匹配它;销毁会话
所以在代码中它看起来像这样(例如): //user credentials are correct, user data is fetched from db
$_SESSION['username'] = $row[3]; //username
$_SESSION['password'] = $row[2]; //password
$_SESSION['user_id'] = $row[4]; //user_id
$salt1 = 'uNs819';
$salt2 = 'J2i';
$user_code = $salt1 . $row[4] . $salt2;
$user_code = md5($user_code);
$_SESSION['user_code'] = $user_code;
然后在每个可用页面的开头用:
检查这是否正确//fetch user credentials from db again
//$row4 is the user_id
if($_SESSION['user_code'] != md5($salt1 . $row[4] . $salt2){
session_destroy();
}
我不认为使用user_id作为加密的一部分是最佳的,但它只是一个例子。最好使用用户创建时的时间戳的md5字符串。但如果我没有说清楚,我的主要问题是,这种方法是否能有效地对抗会话劫持,为什么?
您不需要使用多个盐的花哨方案。
同样,如果我可以窃取用户的会话cookie,你的方案将根本不起作用。
-
登录后更改会话id以避免会话固定
-
到处使用HTTPS
-
使用httpOnly会话cookie使JavaScript无法读取它
-
验证并拒绝XSS输入,并在输出中转义用户生成的数据
-
使用长而随机的会话id
-
重要操作重新认证用户
始终检查任何表单是否存在跨站点伪造令牌,例如,在登录时创建令牌:
Session:set('token', md5(uniqid());
然后在每个表单上放置一个隐藏的表单输入,带有上述标记
<input type="hidden" name="crsf" value="<?php echo System::escape(Session::get('token'));">
然后你可以检查它们以确保:
if(Request::post('crsf') == Session::get('token'):
//do what you gotta do
确保在每次表单提交时生成一个新的令牌,无论它是否成功
我为使用方法而道歉,但是你得到了如何处理表单和不处理表单的要点。
"Another method I came across" -请注明出处
你在这里描述的对会话劫持没有任何影响。无论使用多少会话值、多少盐类和多少轮加密,结果总是匹配的。如果会话被破坏,则不能依赖它来验证会话。session_regenerate_id()函数确实增加了一点值,但只减少了现有漏洞被利用的窗口。花时间防止会话泄露-使用https, HSTS, http-only+安全cookie标志,严格的CSP,到期时会话销毁。
如果你真的觉得需要进一步增强安全性,那么使用令牌与正常交换,例如使用本地存储或设备指纹的挑战响应。