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

相关推荐
xiaohe0719 分钟前
Maven Spring框架依赖包
java·spring·maven
hssfscv37 分钟前
软件设计师下午题二 E-R图
java·笔记·学习
十七号程序猿1 小时前
Java图书管理系统 | 无需配置任何环境,双击一键启动,开箱即用
java·spring boot·vue·毕业设计·毕设·源代码管理
优选资源分享1 小时前
椒盐音乐 v11.1.0 丨安卓无广本地音乐播放器
android
宝耶1 小时前
Java面试2:final、finally、finalize 的区别?
java·开发语言·面试
umeelove351 小时前
Spring boot整合quartz方法
java·前端·spring boot
yige451 小时前
SpringBoot 集成 Activiti 7 工作流引擎
java·spring boot·后端
dreamxian1 小时前
苍穹外卖day10
java·开发语言·spring boot
workflower1 小时前
智能体安全呈现三大核心趋势
人工智能·安全·机器人·智能家居·ai编程
李白的粉1 小时前
基于ssm的校园宽带业务管理系统
java·毕业设计·ssm·课程设计·源代码·校园宽带业务管理系统