burst(CVE-2024-53484) Privilege Escalation in Ever® Traduora™

Hard-coded keys in codebase are like treasures to digital pirates.

circle-info

The content on this blog is published for educational and informational purposes only. I am sharing my analysis and research to help others learn about cybersecurity threats and defensive techniques.

In the modern day, the JWT (JSON Web Token) is the most used authentication method for web development. Because of its flexibility, many OSS (Open Source Software) projects choose to implement it into their projects.

What is JWT token?

So let me explain how a JWT works in the simplest terms. If you remember the security concept about Alice and Bobarrow-up-right, you know that encryption is a must to protect ourselves from someone who wants to eavesdrop on us. To do that, the sender requires a public key and the recipient must have a private key in order to decrypt the message. This very concept also applies to JWT implementation. A JWT requires a signing key which serves as an integrity check so that no one can tamper with the token. Although a JWT is not perfect, as we know there have been historical CVEs in JWT tokens, I won't explain more than this.

More information: https://www.miniorange.com/blog/what-is-jwt-json-web-token-how-does-jwt-authentication-work/arrow-up-right

circle-info

The purpose of this blog is to make you understand the JWT concept and how we can abuse a signing key to tamper with the JWT token.

Generated by ChatGPT. Sorry i'm too lazy to draw it myself. 😄

Real-world scenario

As always, where's the fun if it isn't real? In this article, I choose Ever® Traduora™arrow-up-right as a case study. The vulnerability has been resolved a year ago before this blog is published. This means version 0.21.0 and onwards aren't vulnerable to this.

So yeah, the blog will be mainly focusing on the root cause analysis like patch diffing (Actually, that is an excuse, in facts, i just too lazy to set up the lab again. haha)

So, what is Ever® Traduora™arrow-up-right?

Is the Open Translation Management Platform for teams.

Once you setup your project you can import and export your translations to various formats, work together with your team, instantly deliver translation updates over the air, and soon automatically translate your project via third-party integrations.

If you look at their repository stars, you can see that it's popular in a niche community. I mean not everyone use a translator app right? And over 500k downloads in Docker hubenvelope!?

Let's fast forward to after I set up everything and spinned up Burp Suite. Right off the bat, after login, the tool gave us something very useful!

Another way to look for JWT secret (AKA Signing key) is through codebase at api/src/config.ts . If you can't find it, Don't worry that's because they already removed it. The screenshot below is from git commit.

As you can see that the configuration use || meaning if we don't configure TR_SECRET environment variable, the application will use the secret value instead. Since I didn't config anything that means JWT signing key is secret!

So how is this a vulnerability? Well let me reference it to CWE-798arrow-up-right.

In short (I mean copy & paste their words):

The product contains hard-coded credentials, such as a password or cryptographic key.

So yeah, this is a valid vulnerability. Remember this, when you report a vulnerability to bug bounty programs, VDP programs, OSS maintainers, enterprise security teams, or any CNA. Make sure you map your finding to a proper CWE. So that it makes sense to them!

Exploitation

Here comes the fun part. Since you have a valid JWT token and JWT signing key. You are now able to craft/tamper any JWT token. Typically, when we exploit JWT signing key, we usually want to escalate our low-privileged user to high-privileged user. This is very common though. The hacking methodology looks like this in general: Recon > Exploitation > Privilege Escalation > Lateral Movement > Post Exploitation . Personally, the methodology isn't fixed, different firms use different methodologies.

But first let us check that the JWT secret is legit. You can use JWT.ioarrow-up-right to validate the secret key.

1

Place JWT token first

Copy & paste JWT token.

2

Then place JWT secret key

Copy & paste JWT secret key.

As expected, "Signature Verified" means it is valid!

I know the screenshot is blur because i captured it from my PoC video on YT.

To exploit this, I created 2 accounts one is an admin user and the another one is a normal user.

A normal user (Viewer)
An admin user (Admin)

Next, I created a new project team and added these 2 to join. There is an endpoint that listed all users in that project team which can be accessed by anyone in the team (Apparently, broken access control vulnerability here. I'm just too lazy to report it.). So yeah, UserId which is in UUIDv4 format is useless if we can find a way to identify it.

circle-info

UUIDv4 and other variants are created to make value unpredictable.

So what are we going to do with UserId values?

Well, we could use admin's UserId to tamper our JWT token then use JWT signing key to sign it. There you go, we are now able to craft an admin JWT token!

This is an admin value

Nice! we successfully crafted an admin JWT token. Now we can interact with any endpoint that required admin privileges. Normally, admin has privileges to assign anyone any role and since we learnt that the admin role value is basically "admin". We just have to find that endpoint to complete our privilege escalation attack.

Remember use your crafted JWT token to send requests

Now, try refresh the page and notice that our normal user is now an admin!

We can even make the current admin user becomes a normal user too!

Mitigation

I looked at git commit and i could see they have implemented a new defense and also used CodeRabbitarrow-up-right for secure code review.

Git commit: https://github.com/ever-co/ever-traduora/pull/432/filesarrow-up-right

To summarize the developer's mitigations,

  1. Added .env.sample file which serves as a template for you to configure your own .env file.

  1. Added .env in .gitignore . This is important and very common to protect credentials from data breaches.

  1. The dotenv library was added to load configuration and credentials from the .env file, making them available as environment variables.

  1. Deleted old configuration including default JWT signing key

  1. Implemented checkEnvVariables() , if the TR_Secret variable is not configured. Then alert the warning console log.

The application looks for the TR_Secret value, however, if it isn't set then it reverts to the default value!

My honest reaction to the patch

Conclusion

I reported this to the vendor via their security email and notified them through Git issue, the vulnerability was being "handled" quickly. Later on, I submitted CVE form and was assigned CVE-2024-53484 later.

Last updated