Session Fixation Security Issue(5)Security Token

Session Fixation Security Issue(5)Security Token

I discuss this with my collegue, and he figures out another way. To use addtional information, for example, security token to validate this.
1. Generate Random String with SecurityRandom
package com.sillycat.easywebflow.util;

import java.security.SecureRandom;

import org.apache.log4j.Logger;

public class SecurityTokenUtil {

private static final Logger log = Logger
.getLogger(SecurityTokenUtil.class);

private static final SecureRandom sr = new SecureRandom();

/**
* generate random number
*
* @param length
* @return
*/
public static String getRandomIntNum(int length) {
sr.setSeed(sr.nextLong());
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
sb.append(Math.abs(sr.nextInt(10)));
}
log.debug("gen randomIntNum=" + sb.toString());
return sb.toString();
}

/**
* generate random string
*
* @param length
* @return
*/
public static char[] getRandomCharArray(int length) {
sr.setSeed(sr.nextLong());
char[] ca = new char[length];
for (int i = 0; i < ca.length; i++) {
ca[i] = (char) (((Math.abs(sr.nextInt())) % 26) + (sr.nextBoolean() ? 65
: 97));
}
return ca;
}

/**
* get a random String
*
* @param length
* @return
*/
public static String getRandomString(int length) {
String returnstr =  new String(getRandomCharArray(length));
log.debug("gen randomIntNum=" + returnstr);
return returnstr;
}

public static String getRandomIntNumCharacter(int length) {
sr.setSeed(sr.nextLong());
StringBuffer sb = new StringBuffer();

for (int i = 0; i < length; i++) {
if (sr.nextBoolean()) {
sb.append(Math.abs(sr.nextInt(10)));
} else {
char c = (char) (((Math.abs(sr.nextInt())) % 26) + (sr
.nextBoolean() ? 65 : 97));
    sb.append(c);
}
}
log.debug("gen getRandomIntNumCharacter=" + sb.toString());
return sb.toString();
}
}

And the verify test case is as follow:
package com.sillycat.easywebflow.util;

import junit.framework.Assert;

import org.junit.Test;

public class SecurityTokenUtilTest {

@Test
public void getRandomIntNum(){
String num1 = SecurityTokenUtil.getRandomIntNum(10);
String num2 = SecurityTokenUtil.getRandomIntNum(10);
Assert.assertNotSame(num1, num2);
}

@Test
public void getRandomString(){
String str1 = SecurityTokenUtil.getRandomString(30);
String str2 = SecurityTokenUtil.getRandomString(30);
Assert.assertNotSame(str1,str2);
}

@Test
public void getRandomIntNumCharacter(){
String str1 = SecurityTokenUtil.getRandomIntNumCharacter(30);
String str2 = SecurityTokenUtil.getRandomIntNumCharacter(30);

Assert.assertNotSame(str1, str2);
}

}

2. Use a SessionCookieUtil to deal with Session and Cookie things
package com.sillycat.easywebflow.util;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class SessionCookieUtil {
public static final String COOKIE_SECURITY_TOKEN_NAME = "cookie_security_token";
public static final String SESSION_SECURITY_TOKEN_NAME = "session_security_token";
public static void writeValueToCookie(String key, String value,
HttpServletRequest request, HttpServletResponse response) {
Cookie cookie = new Cookie(key, value);
cookie.setMaxAge(-1);
String contextPath = null;
if (request != null) {
contextPath = request.getContextPath();
}
if ((contextPath != null) && (contextPath.length() > 0)) {
cookie.setPath(contextPath);
} else {
cookie.setPath("/");
}
if (response != null) {
response.addCookie(cookie);
}
}
public static String getValueFromCookie(String key,
HttpServletRequest request) {
String sessionId_fromCookie = "";
Cookie[] cookies_array = null;
if (request != null) {
cookies_array = request.getCookies();
}
if (cookies_array != null && cookies_array.length > 0) {
for (int i = 0; i < cookies_array.length; i++) {
Cookie cookie = cookies_array[i];
if (cookie.getName().equalsIgnoreCase(key)) {
sessionId_fromCookie = cookie.getValue();
break;
}
}
}
return sessionId_fromCookie;
}
public static void putValueinSession(String key, String value,
HttpServletRequest request) {
HttpSession session = null;
if (request != null) {
session = request.getSession();
}
if (session != null) {
session.setAttribute(key, value);
}
}
public static String fetchValuefromSession(String key,
HttpServletRequest request) {
String tokenValuefromSession = "";
HttpSession session = null;
if (request != null) {
session = request.getSession();
}
if (session != null) {
if (session.getAttribute(key) != null) {
tokenValuefromSession = (String) session.getAttribute(key);
}
}
return tokenValuefromSession;
}
}

3. Once our login action or other actions are taken, we will modify cookie and session
String token = SecurityTokenUtil.getRandomIntNumCharacter(30);
SessionCookieUtil.writeValueToCookie(SessionCookieUtil.COOKIE_SECURITY_TOKEN_NAME,token,request,response);
SessionCookieUtil.putValueinSession(SessionCookieUtil.SESSION_SECURITY_TOKEN_NAME, token, request);

4. Use filter to validate the token in every important steps
package com.sillycat.easywebflow.filter;
import java.io.IOException;
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.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.sillycat.easywebflow.util.SessionCookieUtil;

public class SessionFixationProtectionFilter implements Filter {
private final Log log = LogFactory
.getLog(SessionFixationProtectionFilter.class);
public void doFilter(ServletRequest servletRequest,
ServletResponse serlvetResponse, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) serlvetResponse;

String tokenValuefromCookie = SessionCookieUtil.getValueFromCookie(
SessionCookieUtil.COOKIE_SECURITY_TOKEN_NAME, request);
String tokenValuefromSession = SessionCookieUtil.fetchValuefromSession(
SessionCookieUtil.SESSION_SECURITY_TOKEN_NAME, request);
log.debug("COOKIE tokenValue = " + tokenValuefromCookie);
log.debug("SESSION tokenValue = " + tokenValuefromSession);
if (tokenValuefromSession != null
&& !"".equals(tokenValuefromSession)
&& !tokenValuefromSession
.equalsIgnoreCase(tokenValuefromCookie)) {
// there is token in session, and it is not equals from cookie
request.getSession().invalidate();
}
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
}
public void destroy() {
}
}

I verified, this should be working.

references:
http://en.wikipedia.org/wiki/Session_fixation
https://www.owasp.org/index.php/Session_Fixation_Protection

http://www.exampledepot.com/egs/java.security/CreateSecureRandom.html
http://www.exampledepot.com/egs/java.security/ListSecureRnd.html

http://xiongjiajia.iteye.com/blog/1461424

猜你喜欢

转载自sillycat.iteye.com/blog/1570253
今日推荐