ezBookkeeping 0.7.0 - 2FA backup code bruteforce

Basic Information

Software Type Web App
Software Name ezBookkeeping
Affected Version 0.7.0
Software Vendor Mayswind
Software Link https://github.com/mayswind/ezbookkeeping
Severity High
CVSS Score 9.1
CVE Link https://www.cve.org/CVERecord?id=CVE-2024-57604
Affected Assets 100+
Date of Discovery Dec 27, 2024

Description

The application allows users to setup Two-Factor Authentication through the following page:
http://10.0.0.94/desktop#/user/settings?tab=twoFactorSetting

Additionally, in case users can also use backup codes as an alternative to login when they don't have access to their Authenticator app.

Backup codes are submitted to /api/2fa/recovery.json endpoint, this endpoint requires a token that an attacker can get with valid credentials. This token has a short lifespan so an attacker can only attempt 10-20 backup codes and then they would need another token which can be achieved by logging in again.

Reproduce

Open the login page:
http://10.0.0.94/desktop#/login

Use a correct username and password to login, when you enter correct credentials, the login page will prompt you to enter 2FA code or a backup code. Choose backup code option.
When submitting backup codes, the request is sent to the following path:
POST /api/2fa/recovery.json HTTP/1.1 
Host: 10.0.0.94 
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:129.0) Gecko/20100101 Firefox/129.0
Accept: application/json, text/plain, */* 
Accept-Language: en Accept-Encoding: gzip, deflate, br Content-Type: application/json Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyVG9rZW5JZCI6IjMzMzU2NDYwODM3MTM1OTAxIiwianRpIjoiMzcyNjQ2NDgwODk5MjYzNjkyOCIsInVzZXJuYW1lIjoiemFjayIsInR5cGUiOjIsImlhdCI6MTczNTI3MzEzNiwiZXhwIjoxNzM1MjczNDM2fQ.mbYzpTIk5mtWrH23juT9y2x5KgtF_5bvWqRG75TO7m8 
X-Timezone-Offset: -300 
Content-Length: 30 
Origin: http://10.0.0.94/ 
Connection: keep-alive 
Referer: http://10.0.0.94/desktop 
Cookie: csrf_cookie=b1cbb3c53390c7e938c9ade7339a382d; ea_session=fb7d100eb8d129653a58ed78333d30d4bb0643c6 Priority: u=0

{"recoveryCode":"8cv9j-i136a"}

I have discovered is that you can't keep brute-forcing this endpoint repeatedly with a list of recovery codes, the token has a short lifespan & will expire, for this reason I have crafted an exploit that performs all of the following:
  1. Login to account with correct username & password
  2. Once logged in, the application responds with a token
  3. The token is then used to perform 10 brute force attempts on the backup code
  4. After 10 attempts, a new login attempt is made to get a new token
  5. The token is used with the next 10 or fewer backup codes
  6. This is repeated until the correct backup code is found
  7. Once a correct backup code is found, the application responds with another token that can be used for full account access
  8. You can use this token to change the email address of the user or even disable 2FA altogether
  9. This chain leads to full account takeover

Proof of Concept (PoC) Video

PoC Exploit

https://gist.github.com/0xHamy/908011130bc8ec05db3ac9bc54c7593a

Mitigation

  1. Backup Code Security
    • Rate Limiting: Limit the number of backup code verification attempts per account to prevent brute-forcing.
    • One-Time Use Codes: Ensure backup codes are invalidated after one successful use.
    • Strong Backup Codes: Use longer, randomly generated alphanumeric codes to increase brute force resistance (e.g., 12–16 characters).
    • Monitoring and Alerts: Notify users of backup code usage and log all attempts for potential abuse detection.
  2. Token Management
    • Short-Lived Tokens: Issue time-limited tokens that expire quickly after usage.
    • Scope Validation: Restrict tokens to specific actions (e.g., login vs. profile updates).
    • Immediate Revocation: Revoke all active tokens when critical account information (e.g., email or password) is changed.

Patch

A patch will be issued as part of a new enhancement: https://github.com/mayswind/ezbookkeeping/labels/enhancement



Posted on: January 01, 2025 10:36 AM