专栏链接
一、数据的校验
二、认证与授权
三、Cookie与会话管理
四、错误处理
五、日志安全
六、未验证的重定向
Cookie与会话管理:Cookie 中明文存储用户名、密码
漏洞描述:
Cookie 的一个典型的应用是当登录一个网站时,网站往往会请求用户输入用户名和密码,并且用户可以勾选"下次自动登录"。如果勾选了,那么下次访问同一网站时,用户会发现没输入用户名和密码就已经登录了。这正是因为前一次登录时,服务器发送了包含登录凭据(用户名和密码)的 Cookie 到用户的硬盘上。从安全的角度来讲,用户名、密码需要经过某种加密形式加密后再存储。
不合规的代码示例:
java
private ModelAndView userLogin(HttpServletRequest request, MuserLogin user, Model model, HttpServletResponse response, String companyId) throws Exception {
if (!imageCodeCheck(request, IMAGE_CODE, OAConstants.IMAGE_CODE)) {
return new ModelAndView("redirect:../?error_code=" +OAConstants.IMAGE_CODE_ERROR);
}
MuserLogin user1 = userLoginService.checkLogin(user.getUserCode(), MD5Tools.getStringMD5(user.getUserPass()), companyId);
Map<String, Object> map = new HashMap<String, Object>();
if (user1 == null) {
user1 = userLoginService.get(user.getUserCode());
if (null != user1) {
Company comp =this.companyService.get(user1.getCompanyId()); // 用户名 存在取所属企业的删除标志
if (ZERO.equals(comp.getDelFlag())) { // 为1 表示企业删除、用户名输入正确,密码输入错误的情况
if (userLoginErrorCount(user1.getUserCode(), companyId)) {
return new ModelAndView("redirect:../?error_code=9999");
} else {
// 更新用户登录失败次数
MLoginError mle = new MLoginError();
GetGuid guid = new GetGuid();
mle.setLoginErrorCode(guid.getGuid());
mle.setLoginErrorDate(new Date());
mle.setUserCode(user1.getUserCode());
mle.setLoginErrorIp(InetAddress.getLocalHost().toString());
mle.setCompanyId(companyId);
errorService.save(mle);
}
} else {
return new ModelAndView("redirect:../?error_code=8888");
}
}
return new ModelAndView("redirect:../?error_code=0001");
} else {
/***** 这段解决保存用户名,密码的 ****/
String userCode = user.getUserCode();
String userpd = user.getUserPass();
String flag = StringTools.sqlInj(request.getParameter("ck"));
String name = null;
int ss = 0; // 判断是不是重复保存
// set cookie
GetGuid gid = new GetGuid();
String guid = gid.getGuid();
if (flag != null && flag.equals("1")){
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i < cookies.length; i++) {
if (cookies[i].getName().contains(COOKIE_USER)) {
name = cookies[i].getValue().split(HORIZONTAL)[0];
if (name.equals(userCode)){
Cookie cook = new
Cookie(cookies[i].getName(), null);
cook.setMaxAge(0);
cook.setPath(RIGHT_DIAGONAL);
response.addCookie(cook);
Cookie cookie = new
Cookie(COOKIE_USER + guid, userCode + HORIZONTAL + userpd);
cookie.setMaxAge(SIXTY * SIXTY * TWELVE);
// cookie 保存半天
cookie.setPath(RIGHT_DIAGONAL);
response.addCookie(cookie);
}
}
}
ss = 1;
break;
if (ss == 0) {
Cookie cookie = new Cookie(COOKIE_USER + guid, userCode + HORIZONTAL + userpd);
cookie.setMaxAge(SIXTY * SIXTY * TWELVE); // cookie 保存半天
cookie.setPath(RIGHT_DIAGONAL);
response.addCookie(cookie);
}
} else {
Cookie[] cookie = request.getCookies(); // 获取 cookie
for (int i = 0; cookie != null && i < cookie.length; i++) {
if (cookie[i].getName().contains(COOKIE_USER)) {
Cookie cook = new
Cookie(cookie[i].getName(), null);
cook.setMaxAge(0);
cook.setPath(RIGHT_DIAGONAL);
response.addCookie(cook);
}
}
}
/*******************************/
// 取所属企业的删除标志
Company comp = this.companyService.get(companyId);
if(!ZERO.equals(comp.getDelFlag())){
return newModelAndView("redirect:../?error_code=8888");
}
if (userLoginErrorCount(user1.getUserCode(), companyId)) {
return new ModelAndView("redirect:../?error_code=9999");
}
request.getSession(true).setAttribute(USER2, user1);
model.addAttribute(OAConstants.USER_INFO_SESSION, user1);
// 名为 Constants.USER_INFO_SESSION 的属性放到Session 属性列表中
String viewName = DEFAULT;
// 菜 单 树
List<MFunctree> lstTree = mfunctreeService.getTreeListBySupFuncid(ZERO,
user1.getUserCode(), companyId);
map.put(TREE, lstTree);
ModelAndView mav = new ModelAndView();
mav.setViewName("redirect:" + viewName);
mav.addObject(TREELIST, lstTree);
//ip 地址 // 更新登录次数,最后登录时间,最后登录
user1.setLastlogintime(new Date());
int logincount = 0;
try {
logincount = user1.getLogincount();
}catch(Exception ex){
ex.printStackTrace() ;
}
user1.setLogincount(logincount + 1);
user1.setLoginip(request.getLocalAddr());
user1.setCompanyId(companyId);
userLoginService.update(user1);
// 记录操作日志
String funcname = "登录";
String operContent = "登录进入系统";
String logKind = "I";
String ouserCode = user1.getUserCode();String loginip =
request.getRemoteHost();
String cId = user1.getCompanyId();
dLogService.saveDetail(funcname,
operContent, logKind, ouserCode, loginip, cId);
// 登 录 信 息Session 保 存
LoginedUserInfo userinfo = new LoginedUserInfo();
userinfo.setMuser(user1);
MDepartment department = user1.getMDepartment();
if (department != null) {
userinfo.setDeptName(department.getDeptName());
}
MHeadShip headship = user1.getMHeadship();
if (headship != null) {
userinfo.setHeadshipName(headship.getRoleDesc());
}
Company company = this.companyService.get(userinfo.getMuser().getCompanyId());
// 登录排名
int order = userLoginService.getUserlogincountOrder(user1.getUserCode(), cId);
userinfo.setLogin_number(order);
request.getSession(true).setAttribute(OAConstants.SESSION_USERINFO, userinfo);
request.getSession(true).setAttribute(COMPANY_ID,
userinfo.getMuser().getCompanyId());
request.getSession(true).setAttribute("password_",
user.getUserPass());
mav.addObject(COMPANY2, company);
return mav;
}
}
不合规说明:
登录成功之后将用户名和密码明文存储在 Cookie 中。
合规的代码示例:
java
private ModelAndView userLogin(HttpServletRequest request, MuserLogin user, Model model, HttpServletResponse response, String companyId) throws Exception {
if (!imageCodeCheck(request, IMAGE_CODE, OAConstants.IMAGE_CODE)) {
return new ModelAndView("redirect:../?error_code=" + OAConstants.IMAGE_CODE_ERROR);
}
// 将 用 户 名 和 密 码 进 行 解 密
EncryptionDecryption des = new EncryptionDecryption("8e5d4a9e5c");
try {
user.setUserCode(des.decrypt(user.getUserCode()));
user.setUserPass(des.encrypt(user.getUserPass()));
} catch (Exception e) {
e.printStackTrace();
}
MuserLogin user1 = userLoginService.checkLogin(user.getUserCode(),
user.getUserPass(), companyId);
Map<String, Object> map = new HashMap<String, Object>();
if (user1 == null){
user1 = userLoginService.get(user.getUserCode());
if (null != user1) {
Company comp = this.companyService.get(user1.getCompanyId()); // 用户名 存在取所属企业的删除标志
if (ZERO.equals(comp.getDelFlag())) {
// 为1 表示企业删除、用户名输入正确,密码输入错误的情况
if (userLoginErrorCount(user1.getUserCode(), companyId)) {
return new ModelAndView("redirect:../?error_code=9999");
} else {
MLoginError();
// 更新用户登录失败次数
MLoginError mle = new
GetGuid guid = new GetGuid();
mle.setLoginErrorCode(guid.getGuid());
mle.setLoginErrorDate(new Date());
mle.setUserCode(user1.getUserCode());
mle.setLoginErrorIp(InetAddress.getLocalHost().toString());
mle.setCompanyId(companyId);
errorService.save(mle);
}
} else {
return new ModelAndView("redirect:../?error_code=8888");
}
}
return new ModelAndView("redirect:../?error_code=0001");
} else {
/***** 这段解决保存用户名,密码的 ****/
String userCode = user.getUserCode();
String userpd = user.getUserPass();
String flag = StringTools.sqlInj(request.getParameter("ck"));
String name = null;
int ss = 0; // 判断是不是重复保存
// set cookie
GetGuid gid = new GetGuid();
String guid = gid.getGuid();
if (flag != null && flag.equals("1")){
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i < cookies.length; i++) {
if (cookies[i].getName().contains(COOKIE_USER)) {
name =cookies[i].getValue().split(HORIZONTAL)[0];
if (name.equals(userCode)){
Cookie cook = new Cookie(cookies[i].getName(), null);
cook.setMaxAge(0);
cook.setPath(RIGHT_DIAGONAL);
response.addCookie(cook);
Cookie cookie = new Cookie(COOKIE_USER + guid, des.encrypt(userCode) + HORIZONTAL + des.encrypt(userpd));//将用户名和密码进行加密
cookie.setMaxAge(SIXTY * SIXTY * TWELVE); // cookie 保存半天
cookie.setPath(RIGHT_DIAGONAL);
response.addCookie(cookie);
ss = 1;
break;
}
}
}
if (ss == 0) {
Cookie cookie = new Cookie(COOKIE_USER + guid,
des.encrypt(userCode) + HORIZONTAL + des.encrypt(userpd));//将用户名和密码进行加密
cookie.setMaxAge(SIXTY * SIXTY * TWELVE); // cookie 保存半天
cookie.setPath(RIGHT_DIAGONAL);
response.addCookie(cookie);
}
} else {
Cookie[] cookie = request.getCookies(); // 获取 cookie
for (int i = 0; cookie != null && i < cookie.length; i++) {
if (cookie[i].getName().contains(COOKIE_USER)) {
Cookie cook = newCookie(cookie[i].getName(), null);
cook.setMaxAge(0);
cook.setPath(RIGHT_DIAGONAL);
response.addCookie(cook);
}
}
}
/*******************************/
// 取所属企业的删除标志
Company comp = this.companyService.get(companyId);
if (!ZERO.equals(comp.getDelFlag())){
return new ModelAndView("redirect:../?error_code=8888");
}
if (userLoginErrorCount(user1.getUserCode(), companyId)) {
return new ModelAndView("redirect:../?error_code=9999");
}
model.addAttribute(OAConstants.USER_INFO_SESSION, user1);
// 名为 Constants.USER_INFO_SESSION 的属性放到Session 属性列表中
String viewName = DEFAULT;
// 菜 单 树
List<MFunctree> lstTree = mfunctreeService.getTreeListBySupFuncid(ZERO, user1.getUserCode(), companyId);
map.put(TREE, lstTree);
ModelAndView mav = new ModelAndView();
mav.setViewName("redirect:" + viewName);
mav.addObject(TREELIST, lstTree);
// 更新登录次数,最后登录时间,最后登录 ip 地址
user1.setLastlogintime(new Date());
int logincount = 0;
request.getSession(true).setAttribute(USER2, user1);
}
catch (Exception ex){
ex.printStackTrace();
}
user1.setLogincount(logincount + 1);
user1.setLoginip(request.getLocalAddr());
user1.setCompanyId(companyId);
userLoginService.update(user1);
// 记录操作日志
String funcname = "登录";
String operContent = "登录进入系统";
String logKind = "I";
String ouserCode = user1.getUserCode();
String loginip = request.getRemoteHost();
String cId = user1.getCompanyId();
dLogService.saveDetail(funcname, operContent, logKind, ouserCode, loginip, cId);
try {
logincount = user1.getLogincount();userinfo.setMuser(user1);
MDepartment department = user1.getMDepartment();
if (department != null) {
userinfo.setDeptName(department.getDeptName());
}
MHeadShip headship = user1.getMHeadship();
if (headship != null) {
userinfo.setHeadshipName(headship.getRoleDesc());
}
Company company = this.companyService.get(userinfo.getMuser().getCompanyId());
// 登录排名
int order = userLoginService.getUserlogincountOrder(user1.getUserCode(), cId);
LoginedUserInfo userinfo = new
LoginedUserInfo();userinfo.setLogin_number(order);
request.getSession(true).setAttribute(OAConstants.SESSION_USERINFO, userinfo);
request.getSession(true).setAttribute(COMPANY_ID, userinfo.getMuser().getCompanyId());
request.getSession(true).setAttribute("password_", user.getUserPass());
mav.addObject(COMPANY2, company);
return mav;
}
}
合规说明:
登录成功之后将用户名和密码进行加密后存储在 Cookie中。