├── Authentication ├── oauth-scope │ ├── images │ │ ├── 1.png │ │ ├── 2.png │ │ ├── 3.png │ │ └── 4.png │ └── README.md └── shared-secret-key │ ├── images │ ├── 1.png │ ├── 2.png │ ├── 3.png │ └── 4.png │ └── README.md └── README.md /Authentication/oauth-scope/images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoorivexTeam/BugBountyTips/HEAD/Authentication/oauth-scope/images/1.png -------------------------------------------------------------------------------- /Authentication/oauth-scope/images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoorivexTeam/BugBountyTips/HEAD/Authentication/oauth-scope/images/2.png -------------------------------------------------------------------------------- /Authentication/oauth-scope/images/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoorivexTeam/BugBountyTips/HEAD/Authentication/oauth-scope/images/3.png -------------------------------------------------------------------------------- /Authentication/oauth-scope/images/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoorivexTeam/BugBountyTips/HEAD/Authentication/oauth-scope/images/4.png -------------------------------------------------------------------------------- /Authentication/shared-secret-key/images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoorivexTeam/BugBountyTips/HEAD/Authentication/shared-secret-key/images/1.png -------------------------------------------------------------------------------- /Authentication/shared-secret-key/images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoorivexTeam/BugBountyTips/HEAD/Authentication/shared-secret-key/images/2.png -------------------------------------------------------------------------------- /Authentication/shared-secret-key/images/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoorivexTeam/BugBountyTips/HEAD/Authentication/shared-secret-key/images/3.png -------------------------------------------------------------------------------- /Authentication/shared-secret-key/images/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoorivexTeam/BugBountyTips/HEAD/Authentication/shared-secret-key/images/4.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # **Bug Bounty Tips** 2 | 3 | ## Authentication Class 4 | - **Account Takeover via Same Key in Different Regions** [[original tweet](https://x.com/_jensec/status/1292846852010721280), [our analysis](./Authentication/shared-secret-key/README.md)]. 5 | - Sign up for an account in the EU region with `victim@gmail.com` 6 | - Log in, grab the JWT token or session 7 | - Use this token/session in the **US region** to see if it works 8 | - **Email Verification Bypass via Token Binds to User not the Email** [[original tweet](https://x.com/Jayesh25_/status/1725429962931335599), [our analysis](https://github.com/VoorivexTeam/white-box-challenges/tree/main/email-verification-bypass)] 9 | - Log in to your attacker account and change your email address to an attacker-controlled email (e.g., `attacker@gmail.com`). 10 | - You’ll receive a confirmation email but **don’t verify** it yet 11 | - Change your email to the unregistered email or domain you wish to HIJACK (e.g., `victim@gmail.com`) 12 | - Click the confirmation link sent earlier to `attacker@gmail.com`. If the system hasn’t revoked it, this link could verify `victim@gmail.com` 13 | - **Account Takeover via OAuth Scope Manipulation** [[original tweet](https://x.com/intigriti/status/1158383750490800128), [our analysis](./Authentication/oauth-scope/README.md)]. 14 | - Go to the OAuth provider's authorization page. 15 | - Remove `email` from the scope in the URL. 16 | - See what happens! 17 | -------------------------------------------------------------------------------- /Authentication/shared-secret-key/README.md: -------------------------------------------------------------------------------- 1 | Have you seen this bug bounty tip from [@_jensec](https://x.com/_jensec)? 2 | 3 | > [#bugbountytips](https://twitter.com/hashtag/bugbountytips?src=hash&ref_src=twsrc%5Etfw) [#bugbounty](https://twitter.com/hashtag/bugbounty?src=hash&ref_src=twsrc%5Etfw) 4 | > How I was able to find multiple critical vulnerabilities to get Full Account Takeover with the help of PlayStore and AppStore region settings. 5 | > 6 | > ![Image](https://pbs.twimg.com/media/EfEdXCZU8AEypT0?format=jpg&name=large) 7 | > 8 | > — Jenish Sojitra (@_jensec) [August 10, 2020](https://twitter.com/_jensec/status/1292846852010721280?ref_src=twsrc%5Etfw) 9 | 10 | Have you considered how this issue occurs in an app? When implementing authentication mechanisms, methods such as tokens and sessions are commonly used. Let's say we have an app that uses JWT. This app relies on a secret key to sign the JWT tokens. 11 | 12 | ![Code snippet to sign JWT Tokens](./images/2.png) 13 | 14 | What if we run this app in different instances (such as in different regions)? It works fine as long as the secret keys are the same. Now, imagine a user has an account in the EA region. If an attacker registers with the same email in the EU region, a new account will be created. 15 | 16 | ![Attack flow](./images/3.png) 17 | 18 | But if the attacker obtains a token from the EU region and uses it in the EA region, they can access the victim's account because the secret keys are identical. This issue can also arise when companies set up dev environments, as highlighted in the [@intigriti](https://x.com/intigriti) challenge. 19 | 20 | > Can you spot the vulnerability? 🔎 21 | > 22 | > This is a docker-compose file for the infrastructure of an application. 23 | > The application allows users to sign up and log in. 24 | > Show us how you'd take over a victim's account in the comments 👇 25 | > 26 | > The best explanation gets a 25€ SWAG voucher!🎫 27 | > 28 | > ![Image](https://pbs.twimg.com/media/FkBmiP8X0AAu4R-?format=jpg&name=large) 29 | > 30 | > — Intigriti (@intigriti) [December 15, 2022](https://twitter.com/intigriti/status/1603394374272000002?ref_src=twsrc%5Etfw) 31 | 32 | As mentioned, we need to register with the victim's email and use that token in the other app. But what if the app requires email verification for registration? If we can't obtain a token, the attack will fail. However, some apps allow users to log in and retrieve tokens before verification. 33 | 34 | Also, behavior may vary between different app instances. For example, I found a dev environment that sends OTPs to your phone and displays them in the response, unlike the production environment. This allowed me to log in with any phone number. Since the dev and production environments shared the same secret key, I was able to access production accounts using staging tokens. 35 | 36 | ![Sample vulnerable app](./images/4.png) 37 | 38 | I always test this method in both development and production environments, but trying it across different regions is a game changer. Huge thanks to [@_jensec](https://x.com/_jensec) for sharing this tip. -------------------------------------------------------------------------------- /Authentication/oauth-scope/README.md: -------------------------------------------------------------------------------- 1 | # Account Takeover via OAuth Scope Manipulation 2 | > According to [@itscachemoney](https://twitter.com/itscachemoney), this sometimes leads to account takeover vulnerabilities. 🤯 3 | > [#BugBountyTip](https://twitter.com/hashtag/BugBountyTip?src=hash&ref_src=twsrc%5Etfw) [#HackWithIntigriti](https://twitter.com/hashtag/HackWithIntigriti?src=hash&ref_src=twsrc%5Etfw) 4 | > ![Image](https://pbs.twimg.com/media/EBNn4ZJWkAUNBqb?format=png&name=large) 5 | > — Intigriti (@intigriti) [August 5, 2019](https://x.com/intigriti/status/1158383750490800128?ref_src=twsrc%5Etfw) 6 | 7 | Great tip! But how exactly does removing the email from the scope lead to an account takeover? To understand this, we need to take a closer look at how OAuth works. 8 | 9 | When a web app uses OAuth, it sends you to a provider (like Google or Facebook). After you confirm your identity and agree to share your data, you return to the app with a token. The app then asks the provider to verify the token and sends back basic information, like your email, which the app uses to identify you. 10 | 11 | ![](./images/1.png) 12 | 13 | When you allow a third-party application to access certain parts of your data, this is controlled by something called "scope", which is often found in the URL query parameters. Scope defines which specific information, like your email, you choose to share with the app. But what happens if you don’t allow the app to access your email, especially if the app uses OAuth and relies on your email for authentication? 14 | 15 | In this case, the app tries to request the email, but the OAuth provider won’t return it because the app doesn’t have permission to access it. If error handling is well implemented in that application, the app will receive "undefined" or an empty string instead of the email. 16 | 17 | ![](./images/2.png) 18 | 19 | So, how does this help us take over any account? After the web app gets the email from the OAuth provider, it searches the database for your account and then creates a session or token to log you in. But what if, instead of finding your email, the app searches the database for "undefined" or an empty string? 20 | 21 | To understand this fully, let’s examine how the app interacts with the database. Modern web applications often use ORMs (Object-Relational Mappers). If the app queries for "undefined" using an ORM, some may return an error or find nothing. However, in some ORMs like Prisma and TypeORM, the query might match the first user in the database. This could allow the attacker to log you into that user's account. 22 | 23 | ![](./images/4.png) 24 | 25 | You might wonder, if it just matches one user, how can we take over other users' accounts? Features like deleting or deactivating accounts could help you switch between users and explore their accounts. 26 | 27 | As mentioned, the app may get "undefined" or an empty string instead of the email. We've already explained how "undefined" can lead to account takeover, but what if it's an empty string? This could allow access to any account with a blank email field. This happens when the app lets users sign up with both an email and something else, like a phone number. If they sign up this way, the email field stays empty. So, if the app gets an empty string instead of an email, we could log into an account with no email. 28 | 29 | You don’t need to delete accounts or anything like that to switch between users. Just set the email for a user, and the next time the OAuth response has an empty email, you'll log into a different account. 30 | 31 | In summary, I made a diagram to show this. Basically, all you need to do is remove the email from the scope, then return to the app to see what happens. And this doesn’t only work with Facebook; it can work with any OAuth provider. 32 | 33 | ![](./images/3.png) 34 | --------------------------------------------------------------------------------