Security question lookup by email exposed to anonymous callers
The frontend service fetches a user's security question text by email with no authentication, enabling attackers to shop accounts for guessable answers used in the password reset flow.
The findBy(email) method issues an unauthenticated GET to /rest/user/security-question?email=<email> and returns response.question. This client-side wiring confirms the backend exposes the security-question text to any anonymous caller who supplies an email address. Combined with Juice Shop's known security-question-based reset flow, an attacker can:
- Enumerate or guess email addresses.
- Retrieve the security question for each.
- Pick targets whose questions are trivially researchable (e.g., "Name of your favorite pet?", "Eldest sibling's middle name?").
- Submit the guessed answer to the reset endpoint to take over the account.
findBy (email: string) {
return this.http.get(this.hostServer + '/' + 'rest/user/security-question?email=' + email).pipe(
map((response: any) => response.question),
...
)
}
This matches the brief's "Security-question metadata exposed" anti-pattern: endpoints that return the security question text to anonymous callers let attackers shop accounts to find easy questions. Security questions should never be a sole reset factor, and their text should not be disclosed pre-auth.
- Open a browser/curl with no session.
GET https://<host>/rest/user/security-question?email=victim@example.com- Response includes the security question text (e.g., "Eldest sibling's middle name?").
- Research victim's social media; submit guessed answer to the reset endpoint to set a new password.
Any unauthenticated attacker who knows or guesses a user's email can retrieve that user's security question, dramatically lowering the cost of account takeover via the reset flow. Affects every registered user whose question/answer is researchable.
The findBy(email) method in security-question.service.ts issues a plain HttpClient.get to /rest/user/security-question?email=<email> with no auth options and maps response.question from the body — this matches the known Juice Shop backend route that returns the security question text for any email without requiring a session, enabling pre-auth question enumeration that feeds the reset flow. The PoC (anonymous GET with ?email=victim@example.com returning the question text) is reachable because no auth header is set here and Juice Shop's interceptor only attaches a token if one exists. The exploit chain (enumerate emails → fetch question → guess answer → reset password) is plausible against the documented reset endpoint.
The findBy(email) method issues an unauthenticated GET to /rest/user/security-question?email=<email> with no session/token attached, so any remote anonymous caller can retrieve the question text (AV:N, AC:L, PR:N, UI:N). The disclosure is limited to the security question string for an arbitrary email — sensitive metadata that aids account takeover, but not direct credential or bulk PII exfiltration — so Confidentiality is L. This endpoint itself only reads data; the integrity-impacting reset flow lives in a separate endpoint not shown here, so I and A are N at this sink, and the scope stays within the same web application (S:U).
- CWE-640
- CWE-200
- OWASP ASVS V6.3