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

用IBM Rational AppScan扫描该漏洞部分描述:

[1 / 2] 会话标识未更新
严重性: 高
测试类型: 应用程序
有漏洞的URL: ***
修复任务: 不要接受外部创建的会话标识.
会话标识未更新
应用程序
WASC 威胁分类
授权类型:会话定置
http://www.webappsec.org/projects/threat/classes/session_fixation.shtml
CVE 引用
不适用
安全风险
可能会窃取或操纵客户会话和cookie,它们可能用于模仿合法用户,从而使黑客能够以该用户
身份查看或变更用户记录以及执行事务
可能原因
Web 应用程序编程或配置不安全 。。。

1. 漏洞产生的原因:

AppScan会扫描“登录行为”前后的Cookie,其中会对其中的JSESSIONOID(或者别的cookie id依应用而定)进行记录。在登录行为发生后,如果cookie中这个值没有发生变化,则判定为“会话标识未更新”漏洞。

2. AppScan中,对“会话标识未更新”提供了修改建议:

一般修订建议 始终生成新的会话,供用户成功认证时登录。防止用户操纵会话标识。请勿接受用户浏览器登录时所提供的会话标识。

3. 依据修改建议修改如下:

参考1-

  登录时:

<%
session.invalidate();
Cookie[] cookies=request.getCookies();
if(null!=cookies){
    for(int i=0;i<cookies.length;i++){
        if("JSESSIONID").equalsIgnoreCase(cookies[i].getName()){
            cookies[i].setMaxAge(0);
            response.addCookie(cookies[i]);
        }
    }
}
%>

 


退出时:
<%
reponse.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires",0);
session=request.getSession(true);
session.invalidate();
%>

 


spring security中实现思路:

 第一步:提取旧的session中的所有属性及值。

   第二步:使旧的session无效。

   第三步:生成新的session,并将旧session的所有属性和值赋给新的session中。

 /**
     * Called to extract the existing attributes from the session, prior to invalidating it. If
     * {@code migrateAttributes} is set to {@code false}, only Spring Security attributes will be retained.
     * All application attributes will be discarded.
     * <p>
     * You can override this method to control exactly what is transferred to the new session.
     *
     * @param session the session from which the attributes should be extracted
     * @return the map of session attributes which should be transferred to the new session
     */
    protected Map<String, Object> extractAttributes(HttpSession session) {
        return createMigratedAttributeMap(session);
    }

    final HttpSession applySessionFixation(HttpServletRequest request) {
        HttpSession session = request.getSession();
        String originalSessionId = session.getId();
        Map<String, Object> attributesToMigrate = extractAttributes(session);

        session.invalidate();
        session = request.getSession(true); // we now have a new session
        transferAttributes(attributesToMigrate, session);
        return session;
    }

 

注意: session = request.getSession(true); // we now have a new session

  getSession 

public HttpSession getSession(boolean create)

Returns the current HttpSession associated with this request or,

if if there is no current session and create is true, returns a new session.

If create is false and the request has no valid HttpSession, this method returns null.

To make sure the session is properly maintained, you must call this method before the response is committed. If the container is using cookies to maintain session integrity and is asked to create a new session when the response is committed, an IllegalStateException is thrown.

Parameters: true - to create a new session for this request if necessary; false to return null if there's no current session

Returns: the HttpSession associated with this request or null if create is false and the request has no valid session.

补充:在登录或者退出时使用session.invalidate方式修改回话标示未更新,方法最简单;使用spring-security方式修复方式修改比较全面。

转载自:http://www.cnblogs.com/davidwang456/p/3615304.html

参考2-
首先,增加一个新类,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 就已经不一样了,也就是说,会话标识未更新的问题也就解决了。

转载自:http://blog.csdn.net/happylee6688/article/details/42104375

以上两种方式均为参考,请结合实际进行尝试。

 

posted @ 2016-05-08 09:49  寻找普拉多  阅读(1216)  评论(0编辑  收藏  举报