csrfToken校验机制
最近集团进行安全检查,自己接手的老应用被扫出了很多安全隐患,最主要的安全隐患是csrfToken校验隐患。趁着这次机会,熟悉一下webx的csrfToken校验机制。 新的csrfToken(com.alibaba.webx3.migration.china.csrf.pull.ChinaCsrfToken)校验的做法是:
1、从HttpServletRequest中拿到TurbineRunData
public static TurbineRunData getTurbineRunData(HttpServletRequest request, boolean create) {
TurbineRunData rundata = (TurbineRunData) request.getAttribute(TURBINE_RUNDATA_KEY);
if (rundata == null && create) {
rundata = new TurbineRunDataImpl(request);
request.setAttribute(TURBINE_RUNDATA_KEY, rundata);
}
return assertNotNull(rundata, "TurbineRunData not found in request attributes");
}
2、拿到TurbineRunData之后,先根据DEFAULT_TOKEN_KEY从request中获取的csrfToken(fromRequest),并判空,如果为空,则csrfToken失效,返回false。
HttpSession session = httpServletRequest.getSession();
String fromSession = StringUtil.trimToNull((String) session.getAttribute(DEFAULT_TOKEN_KEY));
if (fromSession == null) {
printLogger(securityLogger, LoggerType.SESSION_IS_NULL, httpServletRequest.getRemoteAddr(), null, null);
return false;
}
3、接下来从session中获取csrfToken,判断session中的csrfToken是否存在切是否过期,超过24小时则过期,返回false。
private static boolean isExpire(Logger logger, String tokenOfSession) {
long longValue = 0L;
try {
longValue = Long.parseLong(tokenOfSession);
} catch (NumberFormatException e) {
if (logger.isInfoEnabled()) {
logger.info("parse long error! tokenOfSession=" + tokenOfSession);
}
return true;
}
long nowValue = System.currentTimeMillis();
long tmp = nowValue - longValue;
//当前时间小于token的时间,过期
if (tmp < 0L) {
return true;
}
//当前时间大于token 24小时,过期
return tmp > 24L * 60 * 60 * 1000;
}
4、接下来对session中获取的csrfToken(fromSession)进行MD5加密
private static String hex(String value) {
if (value == null) {
return null;
}
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] bytes = md5.digest(value.getBytes());
return new String(Hex.encodeHex(bytes));
} catch (NoSuchAlgorithmException e) {
return value;
}
}
5、接下来比较从session中获取的加密后的csrfToken与从requst中获取的csrfToken的值,如果相等,则返回true,反之则返回false。
boolean result = fromRequest.equals(fromSession);
总结:这种csrfToken机制,是在页面渲染时,将时间戳md5加密,渲染到页面,同样的时间戳在session中保存一份。请求时,带上csrfToken,跟session中的csrfToken比较,session中保存的是时间戳,在验证session中的时间戳没有过期的前提下,md5加密session中的时间戳,对比request中的csrfToken和session中的csrfToken,并返回结果。 这种属于longlive token,还有一个种unique token。