Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple bruteforce vulnerabilities in ezbookkeeping 0.7.0 #33

Open
0xHamy opened this issue Dec 27, 2024 · 12 comments
Open

Multiple bruteforce vulnerabilities in ezbookkeeping 0.7.0 #33

0xHamy opened this issue Dec 27, 2024 · 12 comments
Labels
enhancement New feature or request

Comments

@0xHamy
Copy link

0xHamy commented Dec 27, 2024

Multiple bruteforce vulnerabilities affecting login and backup codes

I have discovered two critical vulnerabilities Ezbookkeeping that I wanted to share with the community. I must emphasize that this is being done after I had a conversation with [email protected] and they advised to publish my findings here.

These vulnerabilities are as follows:

  1. Brute Force on Login Panel: Allows attackers to systematically guess user credentials.
  2. Brute Force on Backup Codes: Enables bypassing two-factor authentication (2FA) protections.

To demonstrate the impact of these vulnerabilities, I have developed two proof-of-concept (PoC) exploits:

  1. The first exploit automates brute-forcing passwords on the login panel.
  2. The second exploit brute-forces backup codes and programmatically changes the target account's email address

While changing the email address itself may not be a vulnerability, I included this step to illustrate the full impact of the attack and the risk of account takeover.

I conducted my testing by running your software locally using Docker. For your convenience, I have provided a detailed guide below to help you reproduce these issues.

Reproduce login bruteforce

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

Enter a username and password, intercept the request with a proxy such as BurpSuite and you will see the following HTTP request being sent:

POST /api/authorize.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
X-Timezone-Offset: -300
Content-Length: 44
Origin: http://10.0.0.94/
Connection: keep-alive
Referer: http://10.0.0.94/desktop
Priority: u=0

{"loginName":"man1","password":"1234567890"}

If you send a request with a wrong password, you get the following response:
{"errorCode":201002,"errorMessage":"login name or password is wrong","path":"/api/authorize.json","success":false}

There is no rate limiting or account lockout mechanism so you we can exploit the vulnerability by trying a list of passwords to find the correct one.

The exploit code can be found here:
https://gist.github.com/0xHamy/edbf260d4ab6bb9628148bb376619292

Reproduce backup code bruteforce

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:
image

Once enabled, you can enter these backup codes through the login page by clicking on question mark icon:
image (1)

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"}

The interesting thing 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 bruteforce 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 less 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

Here is the exploit code:
https://gist.github.com/0xHamy/908011130bc8ec05db3ac9bc54c7593a

Summary

Severity of the Vulnerability Chain

Overview of the Exploit Chain

  1. Account Brute Force:
    Exploitable due to a lack of rate limiting or account lockout mechanisms on the login endpoint.
    An attacker can brute force valid account credentials by trying different username-password combinations programmatically.
  2. Backup Code Brute Force:
    The application allows brute-forcing backup codes, which are meant to secure accounts as part of two-factor authentication (2FA).
    Lack of rate limiting or monitoring on the backup code endpoint enables systematic guessing, bypassing 2FA entirely.
  3. Programmatic Email Change:
    Once a valid backup code is brute-forced, the attacker gains full access to the account. This allows them to:
    Change the email address associated with the account.
    Lock out the legitimate user by taking ownership of the account.

Impact

  • Confidentiality Breach: Full access to sensitive user data, including account details, personal information, and potentially financial or private data.
  • Integrity Violation: Unauthorized changes to user account information, such as altering the registered email, potentially locking the original user out.
  • Scalability: The attack is scalable to other accounts, affecting multiple users and risking widespread account takeover.
  • Critical Severity: The lack of protections across multiple endpoints creates a systemic vulnerability chain, making this a Critical (CVSS 9.8) issue.

Mitigation Steps

To address this exploit chain, the following measures should be implemented:

  1. Login Brute Force Protection
    Rate Limiting: Limit the number of login attempts allowed per user/IP to a reasonable threshold (e.g., 5 attempts per minute).
    Account Lockout: Temporarily lock accounts after a defined number of failed login attempts (e.g., 3–5 attempts). Notify users of lockout events via email.
    Captcha: Add CAPTCHA challenges after multiple failed attempts to deter automated attacks.
    Password Policy: Enforce strong password requirements and recommend users enable 2FA.

  2. 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.

  3. 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.

  4. Profile Update Endpoint
    Re-Authentication: Require users to re-enter their password or a valid 2FA code before allowing changes to sensitive fields like email addresses.
    Email Verification: Require verification of the new email address before making it the account’s primary email.

Why These Steps Are Necessary

The combination of vulnerabilities creates a critical risk where attackers can systematically bypass authentication and take over user accounts.
Addressing the root causes—lack of rate limiting, inadequate backup code security, and token mismanagement—will mitigate this risk and protect user data and account integrity.

Contact

Get in touch with me @ [email protected]

@mayswind mayswind added the enhancement New feature or request label Dec 27, 2024
@luzpaz
Copy link

luzpaz commented Feb 5, 2025

This is super thorough. Thank you for doing that.

@HelloMusician
Copy link

Thank you for your sharing!
I have used it for more than two years.
For personal users, my suggestion is to deploy it to the local environment and import the bills from the phone into it daily or monthly.
Do not attempt to set external access mechanisms such as DDNS for it unless the above issues are fixed.
Anyway, it is a good enough project, thanks to the developers for your efforts!

@mayswind
Copy link
Owner

mayswind commented Feb 8, 2025

Thank you for your sharing! I have used it for more than two years. For personal users, my suggestion is to deploy it to the local environment and import the bills from the phone into it daily or monthly. Do not attempt to set external access mechanisms such as DDNS for it unless the above issues are fixed. Anyway, it is a good enough project, thanks to the developers for your efforts!

In my opinion, almost no personal user's data is worth brute-forcing. Especially after using a strong password and turing on 2fa, the security of ezBookkeeping for personal users is enough.
If users have higher requirements for security issues, they can use some tools like fail2ban.

@0xHamy
Copy link
Author

0xHamy commented Feb 8, 2025

@luzpaz

This is super thorough. Thank you for doing that.

You are welcome :)

@0xHamy
Copy link
Author

0xHamy commented Feb 8, 2025

@HelloMusician

Thank you for your sharing! I have used it for more than two years. For personal users, my suggestion is to deploy it to the local environment and import the bills from the phone into it daily or monthly. Do not attempt to set external access mechanisms such as DDNS for it unless the above issues are fixed. Anyway, it is a good enough project, thanks to the developers for your efforts!

You are welcome, stay secure :)

@0xHamy
Copy link
Author

0xHamy commented Feb 8, 2025

@mayswind

In my opinion, almost no personal user's data is worth brute-forcing. Especially after using a strong password and turing on 2fa, the security of ezBookkeeping for personal users is enough. If users have higher requirements for security issues, they can use some tools like fail2ban.

It's pretty common tactic we use in penetration testing, you can see an example here:
https://www.exploit-db.com/exploits/48942

2FA itself can be bypassed because there is an exploit for that too.

@mayswind
Copy link
Owner

mayswind commented Feb 8, 2025

@mayswind

In my opinion, almost no personal user's data is worth brute-forcing. Especially after using a strong password and turing on 2fa, the security of ezBookkeeping for personal users is enough. If users have higher requirements for security issues, they can use some tools like fail2ban.

It's pretty common tactic we use in penetration testing, you can see an example here: https://www.exploit-db.com/exploits/48942

2FA itself can be bypassed because there is an exploit for that too.

Without brute-forcing protection, 2fa can certainly be cracked. But what I said is

Image

@0xHamy
Copy link
Author

0xHamy commented Feb 8, 2025

@mayswind

Without brute-forcing protection, 2fa can certainly be cracked. But what I said is

Image

I don't think strong password rules were implemented at the time I was testing this because I was able to set passwords like "1234567890" and get away with it. The application should encourage users to set strong passwords by asking for at least 12 characters, that would include special characters, numbers, letters, etc.

@mayswind
Copy link
Owner

mayswind commented Feb 8, 2025

@mayswind

Without brute-forcing protection, 2fa can certainly be cracked. But what I said is
Image

I don't think strong password rules were implemented at the time I was testing this because I was able to set passwords like "1234567890" and get away with it. The application should encourage users to set strong passwords by asking for at least 12 characters, that would include special characters, numbers, letters, etc.

The ezBookkeeping project does not provide any services to the public, so it should not to tell users how to set up their password. In most cases, each ezBookkeeping instance has only one user, who is also the system administrator. The system administrator of each ezBookkeeping instance should take responsibility for itself security.

@marcaurele
Copy link

Protecting login brute forcing is best done with a WAF (Web Application Firewall) in front of any application. It does not make much sense to include it in the application code.

@0xHamy
Copy link
Author

0xHamy commented Feb 8, 2025

@marcaurele

Protecting login brute forcing is best done with a WAF (Web Application Firewall) in front of any application. It does not make much sense to include it in the application code.

It makes every sense to include it at the core of your application because without that core security protection, you are expecting your users would protect themselves, not everyone has the technical know-how to do it. It's not as straight-forward for most developers.

In my own website, I am using Flask-Limiter to limit number of logins, but that's not enough, I use account lockout functionality provided by Flask-Security to take it one step further and then there is Captcha.

I think that if you take a look at hacking forums like BreachForums, you will notice that brute-force is used in most major campaigns. I have seen it myself in penetration testing (both internal & external).

But to each their own, if your users are experts then you don't need security at all :)

@0xHamy
Copy link
Author

0xHamy commented Feb 13, 2025

I would like to share that this vulnerability was reported to MITRE and it was published under CVE-2024-57603:
https://www.cve.org/CVERecord?id=CVE-2024-57603

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants