Password reset gated only by security question (knowledge factor)
The forgot-password flow resets a user's password using only (email, security-question answer, new password) with no emailed token or proof-of-control of the verified channel.
The ForgotPasswordComponent implements a classic Juice-Shop-style insecure password reset flow:
findSecurityQuestion()(lines 53-79) takes an email typed into the form and callssecurityQuestionService.findBy(this.emailControl.value). This returns the security question text for any email the attacker enters — security-question metadata is exposed to anonymous callers, enabling an attacker to shop accounts for easy-to-research questions (pet's name, school, mother's maiden name, etc.).
resetPassword()(lines 81-106) submits:
this.userService.resetPassword({
email: this.emailControl.value,
answer: this.securityQuestionControl.value,
new: this.passwordControl.value,
repeat: this.repeatPasswordControl.value
})
The entire reset is gated on a knowledge factor (the answer) supplied alongside the target email and new password. There is no out-of-band token round-trip — no link mailed to the verified email, no single-use time-limited token, no re-authentication.
This directly matches the true-positive criterion: "Reset completes based on a knowledge factor (security question, DOB, address, mother's maiden name) without an out-of-band token." It also matches "Reset accepts the target email/username from the request body and sets a new password, without requiring proof-of-control of that email."
Additionally, no client-side rate limiting or lockout exists, and the security question is leaked to anonymous callers via securityQuestionService.findBy(email) (lines 57-71), letting an attacker enumerate easy targets.
- Navigate to /forgot-password.
- Enter a victim's email address — the UI fetches and displays their security question via
SecurityQuestionService.findBy(email), exposing it to an unauthenticated attacker. - Research the answer on the victim's social media (pet's name, hometown, school, etc.) or brute-force it (no rate limit visible).
- Submit email + guessed answer + new password to
userService.resetPassword(...). - Server replies success and the victim's password is now whatever the attacker chose — no email confirmation was ever sent to the verified address.
Any unauthenticated remote attacker who can guess or research a target user's security-question answer (often public information for questions like 'pet name', 'first school', 'mother's maiden name') can take over the account without any access to the victim's email inbox. The security question is even disclosed to the attacker prior to guessing, lowering the barrier further. Full account takeover including admin accounts if their security answers leak.
The resetPassword() method (lines 81–106) submits {email, answer, new, repeat} directly to userService.resetPassword(...) with no out-of-band token, email verification round-trip, or proof-of-control of the email channel. The findSecurityQuestion() method additionally leaks the victim's security question to any anonymous caller via securityQuestionService.findBy(this.emailControl.value), lowering the barrier to a research/guess attack. Per scope rules, we treat Juice Shop as a real production app, and this is the classic knowledge-factor-only reset anti-pattern — attacker need only know/guess the answer to take over any account.
The /forgot-password flow is reachable over the network by an unauthenticated attacker (AV:N, PR:N, UI:N). findSecurityQuestion() leaks the target's question to anonymous callers via securityQuestionService.findBy(email), then resetPassword() (lines 81-90) completes the reset using only (email, answer, new password) with no out-of-band token — a single straightforward request takes over the account (AC:L). Full account takeover yields total compromise of the victim's data and actions within the application (including admin accounts if their answers are guessable), so C/I/A are all H; the impact stays within the same web application's authority (S:U).
- CWE-640: Weak Password Recovery Mechanism for Forgotten Password
- CWE-287: Improper Authentication
- OWASP ASVS V2.5 Credential Recovery
- OWASP Forgot Password Cheat Sheet