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

相关推荐
咩咩啃树皮13 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
鱟鲥鳚14 小时前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
天天进步201514 小时前
UI-TARS 源码解析 #10:parse_action 源码解析:如何用 AST 安全解析模型生成的函数调用?
安全·ui
大模型码小白15 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
腾渊信息科技公司16 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
大耳朵-小飞象16 小时前
电力安全运维的智能密码:BACS如何破解设备全生命周期管理难题,让电网安全“看得见、管得住”?
运维·安全·智慧城市·能耗系统·楼宇智控·未来生活
爱笑的源码基地17 小时前
高并发 Redis 缓存门诊HIS系统源码,含财务统计药房进销存
java·程序·门诊系统·诊所系统·云诊所源码
wuqingshun31415917 小时前
TCP超时重传机制是为了解决什么问题?
java
HLC++17 小时前
Linux的进程间通信
android·linux·服务器
wuhanzhanhui18 小时前
视觉革命与主动安全:2026武汉汽车电子展会定档,看芯片如何定义驾驶
安全·汽车