WEB安全实战(七)会话标识未更新

上一篇文章中,我们讨论了关于“浏览器记住用户名和密码”的问题,至于这篇文章嘛,我想谈谈关于“会话标识”的漏洞。而且,这篇文章也是“Web安全实战”系列的最后一篇。为什么要拿到最后来说呢,其实,是之前一直困扰我的问题,这个问题曾一顿让我抓狂,n(n=3~5)多天一直没有解决,当时也是搜遍了各大网站,各大论坛,均未找到合适的解决方案。其中的过程就不再废话了,转到正题。

问题

先介绍一下问题是如何发现的,当然,这个不是我发现的,是我们测试部的童鞋发现的漏洞,然后她转交给我,让我去解决这个问题。刚开始也是一点思路都没有,然后就是一顿狂搜,后来慢慢发现,其实这个问题产生的根源,就是应用服务器(如 Tomcat)的 JSessionId 没有更新。只要使得旧的 Session 过期,重新生成新的 Session
即可。当然,这是理论上的解决方案,很想当然的。

曲折过程

有了思路之后,再想解决问题就容易了很多。于是,我就把范围固定在了如何让 Session 过期,当然,这样的解决方案网上有一箩筐,这里就不多说了,我拿到项目中试了试,结果你肯定能想到 —— 抛异常,异常原因是:...Session already invalidated 。这说明在程序中的某处,需要用到 Session 中的数据,但是此时
Session 已经过期了,无法取到数据。

于是,我开始找是哪里用到了 Session ,遗憾的是,我没能找到。心想,找不到 Session 我就换个思路吧,那就让 Session 过期之前,重新生成一个新的 Session ,把旧的 Session中的数据拷贝到新产生的 Session 中。这样就可以避免 Session 过期的问题了(理论上是这样)。

到这里,如果是一般的情况,就可以解决了,不过嘛,如果你的项目中还加入了安全框架 Shiro ,那么在 Session 的处理上,会有一些麻烦,因为 Shiro 也会有自己的 Session ,而且在认证的时候,Shiro 会有一些处理 Session 的操作,这就是导致 ...Session already invalidated 的原因所在。后来试了几种把旧
Session 数据转新 Session 数据的方案也不好使。

最终方案

一个偶然的机会,在网上找到了一篇《会话标识未更新》的文章,这篇文章就是介绍的在使用 Shiro 的情况下,如何解决这个漏洞,不过,情况不同的是,他使用的是应用服务器是 jBoss,而我们用的则是 Tomcat,本着试一试的态度,按照他给的思路,把自己的代码做了一下整理,把对
Session 操作的处理类封装成了一个 Filter,通过这个 Filter 对 Session 进行处理,下面请看相关代码。

代码如下

首先,增加一个新类,NewSessionFilter。

<span style="font-family:Comic Sans MS;">package com.test.web.common;

import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class NewSessionFilter implements Filter {

	private String url;
	private static final Logger logger = LoggerFactory.getLogger(NewSessionFilter.class);
	public static final String NEW_SESSION_INDICATOR = "com.cacss.sc.web.common.NewSessionFilter";

	public static void newSession(){
		HttpSession session = (HttpSession) SecurityUtils.getSubject().getSession(true);
		session.setAttribute(NEW_SESSION_INDICATOR, true);
	}

	@Override
	public void destroy() {
		System.out.println("NewSessionFilter destory");
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		System.out.println("NewSessionFilter doFilter");

		if (request instanceof HttpServletRequest) {
			HttpServletRequest httpRequest = (HttpServletRequest) request;

			//取的url相对地址
	        String url = httpRequest.getRequestURI();
	        System.out.println(url);
	        if (httpRequest.getSession() != null) {
	        	System.out.println("NewSessionFilter doFilter httpRequest.getSession().getId()"+ httpRequest.getSession().getId());
				//--------复制 session到临时变量
				HttpSession session = httpRequest.getSession();
				HashMap old = new HashMap();
				Enumeration keys = (Enumeration) session.getAttributeNames();

				while (keys.hasMoreElements()){
					String key = (String) keys.nextElement();
					if (!NEW_SESSION_INDICATOR.equals(key)){
						old.put(key, session.getAttribute(key));
						session.removeAttribute(key);
					}
				}

				if (httpRequest.getMethod().equals("POST") && httpRequest.getSession() != null
						&& !httpRequest.getSession().isNew() && httpRequest.getRequestURI().endsWith(url)){
					session.invalidate();
					session=httpRequest.getSession(true);
					logger.debug("new Session:" + session.getId());
				}

				//-----------------复制session
				for (Iterator it = old.entrySet().iterator(); it.hasNext();) {
					Map.Entry entry = (Entry) it.next();
					session.setAttribute((String) entry.getKey(), entry.getValue());
				}
			}
		}

		chain.doFilter(request, response);
		System.out.println("NewSessionFilter doFilter end");
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		System.out.println("NewSessionFilter init");
		System.out.println("NewSessionFilter init end");
	}

}</span>

然后,在 web.xml 中配置 Filter。

<span style="font-family:Comic Sans MS;"><filter>
	<filter-name>NewSessionFilter</filter-name>
	<filter-class>com.cacss.sc.web.common.NewSessionFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>NewSessionFilter</filter-name>
	<url-pattern>/login</url-pattern>
</filter-mapping>

</span>

这样处理完之后,再启动应用服务器,登录前后的 JSessionId 就已经不一样了,也就是说,会话标识未更新的问题也就解决了。

结束语

这个问题困扰了我 n 多天,直到看到这个解决思路之后,通过跟测试部的童鞋协商,测试通过之后,才算是真正的解决了。这也算是这个系列的最后一篇了,写到现在已经把大部分的 Web 安全方面的漏洞都提到过了,而且也都给出了一些解决方案。

通过这近一个多月的漏洞修复,我在 Web 安全方面真的是恶补了一番,也接触了很多安全方面的技术,这对于我以后的开发、设计都是很有好处的,在开发、设计的时候,就会考虑到会不会产生安全漏洞,怎样做会避免这样的问题。这样,就不会在测试的时候出现很多不必要的漏洞了。

时间: 2024-08-04 02:38:17

WEB安全实战(七)会话标识未更新的相关文章

java或者jsp中修复会话标识未更新漏洞

用IBM Rational AppScan扫描该漏洞部分描述: [1 / 2] 会话标识未更新 严重性: 高 测试类型: 应用程序 有漏洞的URL: *** 修复任务: 不要接受外部创建的会话标识. 会话标识未更新 应用程序 WASC 威胁分类 授权类型:会话定置 http://www.webappsec.org/projects/threat/classes/session_fixation.shtml CVE 引用 不适用 安全风险 可能会窃取或操纵客户会话和cookie,它们可能用于模仿合

会话标识未更新

会话标识未更新 可能会窃取或操纵客户会话和 cookie,它们可能用于模仿合法用户,从而使黑客能够以该用户身份查看或变更用户记录以及执行事务 可能原因Web 应用程序编程或配置不安全技术描述 在认证用户或者以其他方式建立新用户会话时,如果不使任何现有会话标识失效,攻击者就有机会窃取已认证的会话.通常在以下情况下会观察到这样的场景: [1] Web 应用程序在没有首先废除现有会话的情况下认证用户,也就是说,继续使用已与用户关联的会话 [2] 攻击者能够强制对用户使用已知会话标识,这样一旦用户进行认

会话标识未更新(AppScan扫描结果)

最近工作要求解决下web的项目的漏洞问题,扫描漏洞是用的AppScan工具,其中此篇文章是关于会话标识未更新问题的.下面就把这块东西分享出来. 原创文章,转载请注明 -----------------------------------------正题------------------------- 测试类型:应用程序级别测试 威胁分类:会话定置 原因:Web 应用程序编程或配置不安全 安全性风险:可能会窃取或操纵客户会话和cookie,它们可能用于模仿合法用户,从而使黑客能够以该用户身份查看

解决shiro会话标识未更新问题

要解决会话标识未更新的安全问题,就需要在做登录验证时生成新的session,所以需要先将原来的session失效. 一般的解决方法如下: public void login(HttpServletRequest request, ...){ // 让旧session失效 request.getSession(true).invalidate(); //登录验证 } 但是,如果使用了shiro框架,这样做会报错:...Session already invalidated.原因是shiro对Htt

会话标示未更新解决方案

JSF项目,用appscan检测,报"会话标示未更新"漏洞,漏洞详情:用户在登陆应用程序前后,其会话标识一样,未进行更新,从而可以窃取或操作客户会话和Cookie,进行查看.变更用户信息及执行事务等操作. 推理: 测试结果似乎指示存在脆弱性,因为"原始请求"和"响应"中的会话标识相同.这些标志应该已在响应中更新. JSF页面在打开时,就会生成一个sessionid,登录后的sessionid未发生变化.解决方案:后台登陆方法,加入强行销毁sess

2014-07-09 Java Web的学习(5)-----会话管理(Cookie和Session)

1.什么是会话 会话,牛津词典对其的解释是进行某活动连续的一段时间.从不同的层面看待会话,它有着类似但不全然相同的含义.比如,在web应用的用户看来,他打开浏览器访问一个电子商务网站,登录.并完成购物直到关闭浏览器,这是一个会话.而在web应用的开发者开来,用户登录时我需要创建一个数据结构以存储用户的登录信息,这个结构也叫做会话.因此在谈论会话的时候要注意上下文环境.而本文谈论的是一种基于HTTP协议的用以增强web应用能力的机制或者说一种方案,它不是单指某种特定的动态页面技术,而这种能力就是保

Android切近实战(七)

边看世界杯,边写博客.记得小时候,去山上玩,翻了两座山,到了一个叫克劳的地方.那里每到六月份,桃子,杏多的很,有时候你坐在树上吃一下午都不会有人来,自然了,那里也就人烟稀少.我当时渴急了,在玉米地边上的牛踩出的蹄窝里喝了一口水,那水真是甘甜哪,忽然觉得脚底下什么在动,抬脚一看,一只螃蟹被我踩到了泥土中.那时候吃野枣,自制枪打野鸡,用套套野兔,在河里捉螃蟹,钓鱼,在洪水中游泳,上山挖药,在山上烤红薯,烤玉米,到了冬天,可以点荒,一盒火柴去见识燎原,这都是经常的事.不知道现在我再去那地方还能不能可以

web安全实战

前言 本章将主要介绍使用Node.js开发web应用可能面临的安全问题,读者通过阅读本章可以了解web安全的基本概念,并且通过各种防御措施抵御一些常规的恶意攻击,搭建一个安全的web站点. 在学习本章之前,读者需要对HTTP协议.SQL数据库.Javascript有所了解. 什么是web安全 在互联网时代,数据安全与个人隐私受到了前所未有的挑战,我们作为网站开发者,必须让一个web站点满足基本的安全三要素: (1)机密性,要求保护数据内容不能泄露,加密是实现机密性的常用手段. (2)完整性,要求

Android -- 与WEB交互在同一个会话Session中通信

Session与Cookie Cookie和Session都为了用来保存状态信息,都是保存客户端状态的机制,它们都是为了解决HTTP无状态的问题而所做的努力. Session可以用Cookie来实现,也可以用URL回写的机制来实现. Cookie和Session有以下明显的不同点: 1)Cookie将状态保存在客户端,Session将状态保存在服务器端: 2)Cookies是服务器在本地机器上存储的小段文本并随每一个请求发送至同一个服务器.网络服务器用HTTP头向客户端发送cookies,在客户