专栏链接
一、数据的校验
二、认证与授权
认证与授权:登录尝试次数限制功能失效
漏洞描述:
作为登录页面防护措施的一种,开发人员注重的是功能能不能用,而非安不安全,思维上比较常规,导致在非常规情况下这种防护却形同虚设。
检测方法:
检查程序中是否将“登录错误次数”保存在某个局部变量中。检查该功能所防护的 URL 是否正确,是否存在多个登录的URL。
不合规的代码示例:
//登录页面代码:
<form id="loginForm" method="post" action="${root}/j_security_check">
<p class="id error"><span><input id="j_username" name="j_username"
onKeyDown="onkeydownn();" type="text" autocomplete="off"/></span></p>
<p><span><input id="j_password" name="j_password" onKeyDown="onkeydownn();" type="password" autocomplete="off"/></span></p>
<p>
<span><input id="j_vc" name="j_vc" onKeyDown="onkeydownn();" type="text" autocomplete="off"/></span>
<span><img src="${ctx }/verifycode.jsp" name="verifycode" id="verifycode" onClick="javascript:randomidbetter(this)"/></span>
</p>
</form>
用户登录的拦截器代码如下:
private boolean bfaCheck(HttpServletRequest request, HttpServletResponse response) {
String requestUri = request.getRequestURI();
String query = request.getQueryString();
String ip = request.getRemoteAddr();
BruteForceAttackInfo info = bfaInfos.get(ip);
Date now = new Date();
if (info != null && info.getLockTime() != null &&
now.getTime() – info.getLockTime().getTime() <= bfaLockTime) {
logger.info("监测到登录失败次数过多,将被禁止访问5 分钟. IP:{}", ip);
request.setAttribute("err", "拒绝访问:登录失败次数过多,禁止访问 5 分钟");
response.setHeader("err", "iplock");
return false;
}
if (!Util.isEmpty(requestUri) && requestUri.endsWith("/login.action") && !Util.isEmpty(query) && query.equals("error=1")) {
if (info != null) {
if (info.getTryStartTime() != null) {
if (now.getTime() – info.getTryStartTime().getTime() <= bfaTime) {
int tCount = info.getTryCount();
if (tCount <= bfaAllowNumber) {
info.setTryCount(++tCount);
bfaInfos.put(ip, info);
return true;
} else {
info.setLockTime(now);
bfaInfos.put(ip, info);
logger.info("监测到登录失败次数过多,将被禁止访问 5 分钟. IP:{}", ip);
request.setAttribute("err", "拒绝访问:登录失败次数过多,禁止访问 5 分钟");
response.setHeader("err", "iplock");
return false;
}
} else {
info.setTryStartTime(now);
info.setTryCount(1);
info.setLockTime(null);
bfaInfos.put(ip, info);
return true;
}
} else {
info.setTryStartTime(now);
info.setTryCount(1);
bfaInfos.put(ip, info);
return true;
}
} else {
BruteForceAttackInfo newTry = new
BruteForceAttackInfo(now, 1, null);
bfaInfos.put(ip, newTry);
return true;
}
}
return true;
}
不合规说明:
用户登录页面提交后台处理的 URL 为/j_security_check, 身份认证失败之后跳转的路径为/login.action。此拦截器只是针对失败之后的路径做登录尝试次数的限制,而对 /j_security_check 却未做同样的处理。导致此拦截器形同虚设。
合规的代码示例:
//登录页面代码:
<form id="loginForm" method="post" action="${root}/j_security_check">
<p class="id error"><span><input id="j_username" name="j_username"
onKeyDown="onkeydownn();" type="text" autocomplete="off"/></span></p>
<p><span><input id="j_password" name="j_password" onKeyDown="onkeydownn();" type="password" autocomplete="off"/></span></p>
<p>
<span><input id="j_vc" name="j_vc" onKeyDown="onkeydownn();" type="text" autocomplete="off"/></span>
<span><img src="${ctx }/verifycode.jsp" name="verifycode" id="verifycode" onClick="javascript:randomidbetter(this)"/></span>
</p>
</form>
//用户登录的拦截器代码如下:
private boolean bfaCheck(HttpServletRequest request,
HttpServletResponse response) {
String requestUri = request.getRequestURI();
String query = request.getQueryString();
String ip = request.getRemoteAddr();
BruteForceAttackInfo info = bfaInfos.get(ip);
Date now = new Date();
if (info != null && info.getLockTime() != null &&
now.getTime() – info.getLockTime().getTime() <= bfaLockTime) {
logger.info("监测到登录失败次数过多,将被禁止访问5 分钟. IP:{}", ip);
request.setAttribute("err", "拒绝访问:登录失败次数过多,禁止访问 5 分钟");
response.setHeader("err", "iplock");
return false;
}
if (!Util.isEmpty(requestUri) && ((requestUri.endsWith("/login.action")
&& !Util.isEmpty(query) && query.equals("error=1")) ||requestUri.endsWith("/j_security_check"))) {
if (info != null) {
if (info.getTryStartTime() != null) {
if (now.getTime() – info.getTryStartTime().getTime() <= bfaTime) {
int tCount = info.getTryCount();
if (tCount <= bfaAllowNumber) {
info.setTryCount(++tCount);
bfaInfos.put(ip, info);
return true;
} else {
info.setLockTime(now);
bfaInfos.put(ip, info);
logger.info("监测到登录失败次数过多,将被禁止访问 5 分钟. IP:{}", ip);
request.setAttribute("err", "拒绝访问:登录失败次数过多,禁止访问 5 分钟");
response.setHeader("err", "iplock");
return false;
}
} else {
info.setTryStartTime(now);
info.setTryCount(1);
info.setLockTime(null);
bfaInfos.put(ip, info);
return true;
}
} else {
info.setTryStartTime(now);
info.setTryCount(1);
bfaInfos.put(ip, info);
return true;
}
} else {
BruteForceAttackInfo newTry = new
BruteForceAttackInfo(now, 1, null);
bfaInfos.put(ip, newTry);
return true;
}
}
return true;
}
合规说明:
在拦截器中增添了对登录提 url(/j_security_check) 的登录错误次数限制。
网硕互联帮助中心







评论前必须登录!
注册