Business Logic: Bypass 2FA to ATO

Giongnef
8 min readJan 18, 2024

Hello my friend!

I’ve read many quality blog posts and learned a lot from the community. Therefore, I’d like to contribute something back. Here’s an interesting business logic case I encountered, along with how to chain it to bypass Two-factor authentication (2FA) and exploit the app’s features to escalate the impact to Account Takeover (ATO).

Although this is a purely technical article, I poured all my precision and emotions into every sentence because it’s my first bounty received. It helped cover my tuition fees for the final semester and fulfilled my dream of self-funding my four-year university education. This means a lot to me.

Let’s get started!

  • Note: As the server had a WAF that immediately blocked IP addresses upon scanning attempts, so I hacked this target entirely manually.

Overview:

  • I’ll temporarily refer to this website as ‘redacted.com’. It is a platform managing IoT projects, cloud solutions, devices, etc. It allows creating multiple accounts within one user and inviting different users to join projects once their email addresses are known.
  • The website allows for flexible account registration. However, each registration requires entering an OTP sent to the business email for verification before the account can be created.
Requires verification via business email
Enter the OTP code sent to the business email for verification.

1. Business Logic: Create accounts of another user

After registering a user and exploring all the app’s features, the “Create New Account” feature caught my attention.

A user is allowed to create multiple different accounts for various managed projects. On the UI, just by entering a name for the new account, we can create it instantly.

However, the interesting thing about the request is as follows:

I’ll temporarily refer to the subdomain as store.redacted.com
  • Not only does it have the Name field, but it also includes the Email field when creating a new account.
  • The response contains idUser, Email, Role and an interesting field called sso_type -> This is an important field that we will discuss later.

So what happens if I change the value of an Email belonging to another user when creating an account?

  • I have another user giongfnef26+user2@intigriti.me (victim email) with only a single normal account.
  • Using the request from giongfnef@wearehackerone.com for giongfnef26+user2@intigriti.me.

Yeah, that’s right. I’ve got the first bug, attacker can create an account that belongs to another user.

The first impact:

  • Attacker can create an unlimited number of accounts within the victim user. These accounts can even have different names, potentially allowing for identical names.
  • Not stopping here, I can chain this vulnerability to bypass 2FA.

2. Bypass 2FA

Observing the request again based on logic:

On the UI, only the name needs to be entered -> but in the request, an email is required.

This time, intuition and experience gained from numerous pentesting projects at my company have suggested to me that there might be a hidden parameter!

I’ve tried common parameters as well as those I found in the response, but none of them were effective.

At this point, I’ve considered the possibility that the naming convention might vary depending on the developer’s habits -> I tried exploring in this way, combining it with the observed patterns.

  • Something interesting has happened:

This happened because of Mass assignment vulnerabilities . I’ve encountered many cases like this in company projects, so I had a hunch when looking at that request.

  • Now so great! that I have the password, let’s proceed with logging in, shall we?
  • No, it’s not working at all! I’ve tried numerous methods, but none have worked. At that time, I’m genuinely questioning if this password actually serves any purpose? (This issue will be resolved in part 3) (*)

Now, let’s try another approach:

It took me many nights, until that night…

  • I can create any accounts within any users if I know the email associated with that user!

So what happens if I don’t know email of that user? What happens if that email has never been used to register a user?

  • I immediately tried with an email that had never been registered then I noticed something strange in the response.
Hmm maybe because I didn’t meet the password requirement correctly.
  • Adjusting the password to meet the requirements and… BOOM!
  • You know what? The value of sso_type is null !
  • I attempted to log in again using the Email and Password and unbelievably, I could directly log in without needing to verify the OTP from the email.
Login in store.redacted.com
  • Depending on each business, employees whose email like “employee1@companyA” will grant roles to view, invite and have full access rights to the resources of companyA. Combining this with another vulnerability I found which allows viewing all the registered emails in the system including internal server emails….

-> Now I can be employee of any company and freely access that company’s resources.

The second impact:

  • Bypassing 2FA, creating users without needing OTP.
  • Accessing the resources of any registered business.
  • Of course, not stopping here I want more. I can still escalate this bug to an Account Takeover (ATO).

3. Account Takeover (ATO)

Honestly, I was certain that bypassing 2FA could lead to a higher impact but I couldn’t find a way forward. I shared this scenario with my senior colleague (a seasoned hacker), he directed me in a very interesting way:

  • Assuming the context:
  1. Somehow, Attacker could register a user first with a password like passwdAttacker for instance.
  2. Then Victim registers with the same user using the different password like passwdVictim.
  3. If Attacker can still log in to user using the old password passwdAttacker -> This means: Attacker achieved Account Takeover or more accurately that is Pre-Account Takeover.

-> Kool! Now, if I still can register the user vrongdethuongv@gmail.com -> everything is done?

  • Unsuccessful, there’s a request that checks whether this user existed before or not :(

But one strange thing I noticed now is that: when registering, I was redirected to sso.redacted.com -> very different from store.redacted.com that I usually encounter ….

-> This leads to a hypothesis that I’ll explain later.

I go around vrongdethuongv@gmail.com user obtained in part 2 and found some interesting information:

  1. Checking the user’s email API.
  • So, if an email is verified with sso_type:1 it means the user is verified by email and sso_type:null if it is not.
  • Pay attention to the type value now, which is sso and local

Another point I observed is that:

  • If sso_type:1 -> we will redirect to login in sso.redacted.com
  • If sso_type:null -> we will redirect to login in store.redacted.com

2. A function that verified users don’t have: “Migrate”

Trying out this function:

  • “Successfully migrate SSO login” ?
  • For sure, I checked this email once again -> The response is change: sso_type:1 and type:sso

Now, this email can be registered normally:

I can verify OTP via email as usual
  • I registered this user with a different password than the one I used and verified the OTP as usual.
  • However, I can still use the old password to log in to this account!

So, we have successfully conducted a Pre-ATO where two passwords coexist for the same account!?

But how? What happened?

I think my initial hypothesis was correct. I’ll explain it using the following model:

This could be a feature of the app, the initial feature
  • There are 2 different databases, let’s call them Store and SSO
  • A normal user can only register in SSO database
  • Only authorized individuals (with special role) can create accounts in the Store and the ‘Migrate’ function migrate that email to SSO for that normal user

These two databases are not synchronized and I have observed some interesting things:

  • If creating a user in the Store first, we can use the “Migrate” function to migrate data to SSO -> we can login at both store.redacted.com and SSO.redacted.com.
  • If an account is created in SSO first, the user can only log in at SSO.redacted.com and only use the password from the first register

-> (*) That’s why we can’t log in at part 2.

The Pre-ATO scenario goes as follows:

  1. Attacker exploits the vulnerability of pre-registering an account of the victim@companyA.com in the Store database.
  2. Next, attacker login victim@companyA.com and use the Migrate function to transfer it to the SSO database, waiting for the victim to register this account.
  3. The victim registers account victim@companyA.com and uses it normally.
  4. The attacker can still log in as victim@companyA.com and access all resources

The third impact:

  • Pre-Account Take Over involves gaining full-access to a business email and concurrently logging/operating in alongside the legitimate user.

Conclusion

  • A very interesting biz case, I have learned a lot from it!
  • I’ve received $$$$ from this bug.
  • A fascinating aspect when it comes to bug bounty is that people often inquire about “How much?” but few ask “How well do I sleep?”
  • I am currently a final year student and have a full-time job. After handling everything, I only have a little time left at night, including a bit of time for sleeping and continuing to work/school at 7 a.m the next morning.
  • I mention this not to complain about what I’m going through. I just want to convey a simple message:

To achieve something, you need to strive and make an effort.

The more effort you put in, the more you’ll receive.

If you’re feeling a bit down in the job you love, just try a little harder.

You’re on the right way!

Thanks for reading ❤

Feel free to reach me on Linkedin or Twitter

HAPPY NEW YEAR & HAPPY HACKING!

--

--