专栏链接

一、数据的校验

  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 重定向

二、认证与授权:密码修改(无需原密码)

漏洞描述:

正常的修改密码都是需要在最后一步验证原密码是否正确, 如果正确才去修改密码。尤其是 Ajax 技术的出现,如今很多程序在修改密码的时候,都喜欢在用户输入原密码之后,先用 ajax 异步的方式去数据库中查询一下是否正确,如果正确才允许用户继续提交密码修改的请求。可往往程序员在最后一步的时候忘了再次校验原密码的操作。

检测方法:

检查对密码的验证是否采用 Ajax 方式单独去校验。检查修改密码的最后步骤是否再次验证原密码。

不合规的代码示例:

/**

* 检测原密码是否正确

*@return

*@throws Exception

*/
public String checkOldPwd() throws Exception{
	//从页面得到原密码
	String pwd = request.getParameter(""oldPwd"");
	//实例密码处理类 
	MD5 md5 = new MD5();
	//登录者的工号
	String userNo =((SessionVO)session.get(ConstVar.SESSIONVO)).getLoginNo ();
	//得到登录者信息
	OpLoginmsgDict loginInfo =rightManageService.getLoginInfo(userNo);
	String oldPwd = md5.getMD5ofStr(pwd);
	//生成上下文
	HttpServletResponse response =ServletActionContext.getResponse();
	response.setContentType(""text/html; charset=GB2312"");
	response.setHeader(""Cache-Control"", ""no-cache"");
	PrintWriter out=response.getWriter();
	//密码比较处理
	if(oldPwd.equals(loginInfo.getLoginPassword())){ 
		out.print(""{success:true,message:'原密码正确!'}"");
	}else{ 
		out.print(""{success:false,message:'原密码不正确!'}"");
	}
	out.close();
	return null;
}
/***
*修改密码
*@return
*@throws Exception
*/
public String changePwd() throws Exception { 
	HttpServletResponse response = ServletActionContext.getResponse();
	// 登录者的工号
	String userNo = ((SessionVO) session.get(ConstVar.SESSIONVO)).getLoginNo();
	String pwdDay = ""90"";
	response.setContentType(""text/html; charset=GB2312"");
	response.setHeader(""Cache-Control"", ""no-cache"");
	PrintWriter out = null; String newPwd =
	request.getParameter(""longinPwd"");
	if (!CommonUtils.isEmpty(newPwd)) { 
		boolean isValid = CommonUtils.isPasswordValid(newPwd);
		if (isValid == false) {
			out = response.getWriter();
			out.print(""{success:false,message:'密码长度至少 8 位或以上,密码由数字及字母混合组成,其中必须同时包含大小写字母;'}"");
			out.close();
			return null;
		}
	}
	boolean flag = rightManageService.checkPwdRepeatUse(userNo, newPwd);
	if (flag == false) {
		out = response.getWriter();
		out.print(""{success:false,message:'不得使用最近5 次以内重复的密码'}"");
		out.close();
		return null;
	}
	rightManageService.changePwd(newPwd, userNo,...

不合规说明:

此处密码修改过程中,前端首先采用 Ajax 方式调用了checkOldPwd 方法,如果返回的 json 数据中 success 的值为 true 则表示原密码输入正确,然后进入下一步(修改密码),但由于修改密码的方法中未再次判断原密码是否正确。恶意用户不需要原密码即可修改密码。

合规的代码示例:

/***
*修改密码
*@return
*@throws Exception
*/
public String changePwd() throws Exception { HttpServletResponse response =
	ServletActionContext.getResponse();
	 
	// 登录者的工号
	String userNo = ((SessionVO) session.get(ConstVar.SESSIONVO)).getLoginNo();
	String pwdDay = ""90"";
	response.setContentType(""text/html; charset=GB2312"");
	response.setHeader(""Cache-Control"", ""no-cache"");
	String newPwd = request.getParameter(""longinPwd"");
	//从页面得到原密码
	String oldPwd = request.getParameter(""oldPwd"");
	//实例密码处理类 
	MD5 md5 = new MD5();
	//得到登录者信息
	OpLoginmsgDict loginInfo =
	rightManageService.getLoginInfo(userNo);
	oldPwd = md5.getMD5ofStr(oldPwd);
	PrintWriter out=response.getWriter();
	//密码比较处理
	if(oldPwd.equals(loginInfo.getLoginPassword())){
		if (!CommonUtils.isEmpty(newPwd)) {
			boolean isValid = CommonUtils.isPasswordValid(newPwd);
			if (isValid == false) {
				out.print(""{success:false,message:'密码长度至少 8 位或以上,密码由数字及字母混合组成,其中必须同时包含大小写字母;'}"");
				out.close(); return null;
			}
		}
	boolean flag = rightManageService.checkPwdRepeatUse(userNo, newPwd);
	if (flag == false) {
		out = response.getWriter();
		out.print(""{success:false,message:'不得使用最近5 次以内重复的密码'}"");
		out.close();
		return null;
	}
	rightManageService.changePwd(newPwd, userNo,...

合规说明:

在修改密码操作的 changePwd 方法中增加对原密码的判断。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐