Answers:
加密会话值将产生零影响。会话cookie已经是一个任意值,对其进行加密只会生成另一个可以嗅探的任意值。
唯一真正的解决方案是HTTPS。如果您不想在整个站点上使用SSL(也许您有性能方面的顾虑),则仅SSL保护敏感区域就可以摆脱困境。为此,请首先确保您的登录页面为HTTPS。当用户登录时,除了常规会话cookie外,还设置一个安全cookie(这意味着浏览器将仅通过SSL链接传输它)。然后,当用户访问您的“敏感”区域之一时,将其重定向到HTTPS,并检查该安全cookie的存在。真正的用户会拥有它,会话劫持者则不会。
编辑:此答案最初写于2008年。现在是2016年,没有理由不在整个站点上使用SSL。不再需要纯文本HTTP!
SSL仅有助于嗅探攻击。如果攻击者可以访问您的计算机,我将假定他们也可以复制您的安全cookie。
至少,请确保旧的Cookie会在一段时间后失去其价值。当cookie停止工作时,即使成功的hijaking攻击也将受到挫败。如果用户有一个多月前登录的会话中的cookie,请重新输入密码。确保每当用户单击您站点的“注销”链接时,就永远不能再次使用旧的会话UUID。
我不确定这种想法是否行得通,但是可以解决:在您的会话cookie中添加一个序列号,也许是这样的字符串:
SessionUUID,序列号,当前日期/时间
加密此字符串并将其用作您的会话cookie。定期更改序列号-可能是Cookie的使用时间为5分钟,然后重新发出Cookie。如果愿意,您甚至可以在每个页面视图上重新发布它。在服务器端,保留您为该会话发布的最后一个序列号的记录。如果有人发送了序列号错误的cookie,则意味着攻击者可能正在使用他们较早拦截的cookie,因此使会话UUID无效并要求用户重新输入密码,然后重新发出新的cookie。
请记住,您的用户可能有多台计算机,因此他们可能有多于一个活动会话。不要执行强迫他们每次在计算机之间切换时再次登录的操作。
您是否考虑过阅读有关PHP安全性的书?强烈推荐。
对于非SSL认证的网站,以下方法取得了很大的成功。
禁止在同一帐户下进行多个会话,请确保您不是仅通过IP地址进行检查。而是通过登录时生成的令牌(与用户会话一起存储在数据库中)以及IP地址,HTTP_USER_AGENT等进行检查
使用基于关系的超链接生成链接(例如,http : //example.com/secure.php?token=2349df98sdf98a9asdf8fas98df8),该链接后面附加有x-BYTE(首选大小)随机腌制的MD5字符串,在页面重定向时会随机生成令牌对应于请求的页面。
短寿命会话认证cookie。如上所述,一个包含安全字符串的cookie是一个好主意,它是对会话有效性的直接引用之一。使它每x分钟过期一次,重新发出该令牌,然后将会话与新数据重新同步。如果数据不匹配,请注销用户,或让他们重新验证其会话。
我绝不是这个主题的专家,我在这个特定主题上已有一些经验,希望其中一些可以帮助任何人。
// Collect this information on every request
$aip = $_SERVER['REMOTE_ADDR'];
$bip = $_SERVER['HTTP_X_FORWARDED_FOR'];
$agent = $_SERVER['HTTP_USER_AGENT'];
session_start();
// Do this each time the user successfully logs in.
$_SESSION['ident'] = hash("sha256", $aip . $bip . $agent);
// Do this every time the client makes a request to the server, after authenticating
$ident = hash("sha256", $aip . $bip . $agent);
if ($ident != $_SESSION['ident'])
{
end_session();
header("Location: login.php");
// add some fancy pants GET/POST var headers for login.php, that lets you
// know in the login page to notify the user of why they're being challenged
// for login again, etc.
}
它的作用是捕获有关用户会话的“上下文”信息,这些信息在单个会话的生存期内不应更改。用户不会同时在美国和中国使用计算机,对吗?因此,如果IP地址在同一会话中突然更改,这强烈暗示着会话劫持尝试,那么您可以通过结束会话并强制用户重新进行身份验证来保护会话。这阻止了黑客尝试,攻击者还被迫登录,而不是获得对会话的访问权限。通知用户该尝试(将其略微增加一点),然后咯咯地烦了+消息灵通的用户及其会话/信息受到保护。
我们加入了用户代理和X-FORWARDED-FOR,以尽最大努力为代理/网络背后的系统捕获会话的唯一性。这样一来,您也许可以使用更多的信息,随时保持创造力。
它不是100%,但是非常有效。
当用户离开网站并返回时,您可以采取更多措施来保护会话,使会话过期,或者强迫他们再次登录。您可以通过捕获空白的HTTP_REFERER(在URL栏中键入域)来检测用户离开并回来,或者检查HTTP_REFERER中的值是否等于您的域(用户单击了外部/精心制作的链接以转到您的域现场)。
终止会话,不要让它们无限期保持有效。
不要依赖Cookie,它们可能会被盗,这是会话劫持的攻击手段之一。
$_SESSION['ident'] = $aip . $bip . $agent;
一样安全。
无法阻止会话100%激越会话,但是通过某种方法,我们可以减少攻击者激越会话的时间。
防止会话干扰的方法:
1-始终使用带有ssl证书的会话;
2-仅在httponly设置为true的情况下发送会话cookie(防止JavaScript访问会话cookie)
2-在登录和注销时使用会话重新生成ID(请注意:请勿在每个请求中使用会话重新生成,因为如果您有连续的ajax请求,则有机会创建多个会话。)
3-设置会话超时
4-将浏览器用户代理存储在$ _SESSION变量中,并在每次请求时与$ _SERVER ['HTTP_USER_AGENT']进行比较
5-设置令牌cookie,并将该cookie的过期时间设置为0(直到关闭浏览器)。为每个请求重新生成cookie值。(对于ajax请求,请不要重新生成令牌cookie)。例如:
//set a token cookie if one not exist
if(!isset($_COOKIE['user_token'])){
//generate a random string for cookie value
$cookie_token = bin2hex(mcrypt_create_iv('16' , MCRYPT_DEV_URANDOM));
//set a session variable with that random string
$_SESSION['user_token'] = $cookie_token;
//set cookie with rand value
setcookie('user_token', $cookie_token , 0 , '/' , 'donategame.com' , true , true);
}
//set a sesison variable with request of www.example.com
if(!isset($_SESSION['request'])){
$_SESSION['request'] = -1;
}
//increment $_SESSION['request'] with 1 for each request at www.example.com
$_SESSION['request']++;
//verify if $_SESSION['user_token'] it's equal with $_COOKIE['user_token'] only for $_SESSION['request'] > 0
if($_SESSION['request'] > 0){
// if it's equal then regenerete value of token cookie if not then destroy_session
if($_SESSION['user_token'] === $_COOKIE['user_token']){
$cookie_token = bin2hex(mcrypt_create_iv('16' , MCRYPT_DEV_URANDOM));
$_SESSION['user_token'] = $cookie_token;
setcookie('user_token', $cookie_token , 0 , '/' , 'donategame.com' , true , true);
}else{
//code for session_destroy
}
}
//prevent session hijaking with browser user agent
if(!isset($_SESSION['user_agent'])){
$_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
}
if($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']){
die('session hijaking - user agent');
}
注意:不要使用ajax请求重新生成令牌cookie。注意:上面的代码是示例。注意:如果用户注销,则cookie令牌以及会话都必须销毁
6-使用用户ip防止会话干扰不是一个好办法,因为有些用户ip随每个请求而变化。影响有效的用户
7-我个人将会话数据存储在数据库中,由您决定采用哪种方法
如果您发现我的方法有误,请纠正我。如果您还有其他方法可以防止会话中断,请告诉我。
有很多方法可以防止会话劫持,但是所有这些方法都在降低用户满意度或不安全。
IP和/或X-FORWARDED-FOR检查。这些工作非常安全,但是可以想象用户的痛苦。他们来到带有WiFi的办公室,获得了新的IP地址,并丢失了会话。再次登录。
用户代理检查。与上述相同,新版本的浏览器已退出,您丢失了会话。另外,这些确实很容易“破解”。对于黑客来说,发送伪造的UA字符串是微不足道的。
localStorage令牌。登录时生成令牌,将其存储在浏览器存储中,并将其存储到加密的cookie(在服务器端加密)。这对用户没有副作用(localStorage在浏览器升级后仍然存在)。它不那么安全-只是模糊不清的安全性。另外,您可以向JS添加一些逻辑(加密/解密)以进一步使其模糊。
重新发布Cookie。这可能是正确的方法。诀窍是一次只允许一个客户端使用cookie。因此,活跃用户将每小时或更短时间重新发布一次Cookie。如果发布了新的cookie,则旧的cookie将失效。骇客仍然是可能的,但要困难得多-骇客或有效用户都会被拒绝访问。
AFAIK会话对象无法在客户端访问,因为它存储在Web服务器上。但是,会话ID被存储为Cookie,它使Web服务器可以跟踪用户的会话。
为防止使用会话ID进行会话劫持,您可以在会话对象内部存储一个哈希字符串,该字符串是使用远程属性和远程端口这两个属性组合而成的,可以在请求对象内部的Web服务器上进行访问。这些属性将用户会话绑定到用户登录的浏览器。
如果用户从同一系统上的其他浏览器或隐身模式登录,则IP地址将保持不变,但端口将不同。因此,当访问该应用程序时,Web服务器将为用户分配不同的会话ID。
下面是我通过将会话ID从一个会话复制到另一个会话而实现和测试的代码。效果很好。如果存在漏洞,请让我知道您是如何模拟的。
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
String sessionKey = (String) session.getAttribute("sessionkey");
String remoteAddr = request.getRemoteAddr();
int remotePort = request.getRemotePort();
String sha256Hex = DigestUtils.sha256Hex(remoteAddr + remotePort);
if (sessionKey == null || sessionKey.isEmpty()) {
session.setAttribute("sessionkey", sha256Hex);
// save mapping to memory to track which user attempted
Application.userSessionMap.put(sha256Hex, remoteAddr + remotePort);
} else if (!sha256Hex.equals(sessionKey)) {
session.invalidate();
response.getWriter().append(Application.userSessionMap.get(sessionKey));
response.getWriter().append(" attempted to hijack session id ").append(request.getRequestedSessionId());
response.getWriter().append("of user ").append(Application.userSessionMap.get(sha256Hex));
return;
}
response.getWriter().append("Valid Session\n");
}
我使用了SHA-2算法,使用baeldung的SHA-256 Hashing中给出的示例对值进行哈希处理
期待您的评论。
为了降低风险,您还可以将原始IP与会话相关联。这样,攻击者必须在同一专用网络中才能使用会话。
检查引荐标头也可以是一种选择,但是更容易被欺骗。