JAVA开发常见安全问题:Cookie 中明文存储用户名、密码

专栏链接

一、数据的校验

  1. SQL注入
  2. 命令注入
  3. 跨站脚本
  4. 任意文件上传
  5. 任意文件下载
  6. 任意文件删除
  7. 任意文件读取与写入
  8. Iframe 框架钓鱼
  9. 负值支付漏洞

二、认证与授权

  1. 密码修改(无需原密码)
  2. 密码策略不足
  3. 用户名密码(敏感信息)明文传输
  4. 验证码可重复利用
  5. 缺少验证码功能
  6. 用户名枚举(用户名和密码单独验证)
  7. 登录尝试次数限制功能失效
  8. 登录后门
  9. 横向越权
  10. 纵向越权

三、Cookie与会话管理

  1. 直接关闭浏览器"退出"系统
  2. 会话标识未更新
  3. Cookie 中明文存储用户名、密码

四、错误处理

  1. 数据库交互中的异常处理

五、日志安全

  1. 日志记录敏感信息

六、未验证的重定向

  1. URL 重定向

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中。

相关推荐
lingggggaaaa8 小时前
安全工具篇&动态绕过&DumpLsass凭据&Certutil下载&变异替换&打乱源头特征
学习·安全·web安全·免杀对抗
忆~遂愿8 小时前
GE 引擎进阶:依赖图的原子性管理与异构算子协作调度
java·开发语言·人工智能
凯子坚持 c8 小时前
CANN-LLM:基于昇腾 CANN 的高性能、全功能 LLM 推理引擎
人工智能·安全
MZ_ZXD0018 小时前
springboot旅游信息管理系统-计算机毕业设计源码21675
java·c++·vue.js·spring boot·python·django·php
PP东8 小时前
Flowable学习(二)——Flowable概念学习
java·后端·学习·flowable
ManThink Technology8 小时前
如何使用EBHelper 简化EdgeBus的代码编写?
java·前端·网络
invicinble8 小时前
springboot的核心实现机制原理
java·spring boot·后端
人道领域8 小时前
SSM框架从入门到入土(AOP面向切面编程)
java·开发语言
大模型玩家七七8 小时前
梯度累积真的省显存吗?它换走的是什么成本
java·javascript·数据库·人工智能·深度学习