aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.42k stars 2.12k forks source link

major security hole in cognito sign up #1959

Closed bionicles closed 5 years ago

bionicles commented 5 years ago

Describe the bug We have waited 42 days to get a simple change, we need to simultaneously verify user email and phone, because a hacker could get a new sim card from an ISP, or spoof a number, or use an IMSI catcher, or steal someone's device, or any number of other things, and verify an account using the fake number even without owning the email in question.

That is a huge security problem and it needs to be solved now because it prevents our launch. That is unacceptable.

How long do you plan to wait around to fix this? Do you think I should contact management about this?

To Reproduce Sign up a user with a phone and email. Cognito only verifies the phone. Cognito wrongly accepts users without validating they own the email!

Expected behavior Auth.confirmSignUp(username, emailCode, phoneCode) needs to just work

Additional context We emailed Jeff Bezos about this critical security flaw 42 days ago. Around 32 days ago we got in contact with Raja Jadeja. The critical security issue remains!

mlabieniec commented 5 years ago

Hello, the service team has outlined a solution per your last comment. The solution is outlined in the Cognito docs under the important section: https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-email-phone-verification.html

If you can let us know what the issue is with this solution I’d be happy to relay the feedback for you on why this doesn’t work for your use case.

bionicles commented 5 years ago

Phone numbers are not secure, and it's possible to gain access to the SMS messages in numerous ways, so it's more secure against adversaries (and makes philosophic sense) to expect simultaneous verification of email and phone. It simplifies the user interface and reduces the code. It's much harder to create a fake user or do identity theft if you need a legit phone and email. I guess that still wouldn't stop it, but If we use this current system, someone can successfully create a user in our user pool without having access to the email. And We Have To Use A Whole Extra Screen And The "Docs" Are Prose Not Code. (https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-email-phone-verification.html)

How do you justify this in the context of potentially sensitive data?

Do you think we can modify Auth.ts like this?

/**

public confirmEmail(user: user, emailCode: string){ return new Promise((resolve, reject) => { user.confirmEmailRegistration(emailCode, forceAliasCreation, function(err, data) { if (err) { reject(err); } else { resolve(data); } }); }); };

public confirmPhone(user: user, phoneCode: string){ return new Promise((resolve, reject) => { user.confirmPhoneRegistration(phoneCode, forceAliasCreation, function(err, data) { if (err) { reject(err); } else { resolve(data); } }); }); };

but how do you think we can best add the confirm email and phone promises to CognitoUser class?

powerful23 commented 5 years ago

@bionicles Hi so if I am understanding this correctly the purpose of doing this is to ensure that the user has verified both his email and phone number before signing in right? We can't verify both during registration because of the service only asks for phone number verification even both attributes are required. I think the workaround could be check the user's attributes before getting them signed in and if they don't complete that attributes verification (email or phone_number), then they will be signed out. It's something like:

Auth.signIn(username, password)
            .then(user => {
                if (user.challengeName === 'SMS_MFA' || user.challengeName === 'SOFTWARE_TOKEN_MFA') {

                } else if (user.challengeName === 'NEW_PASSWORD_REQUIRED') {

                } else if (user.challengeName === 'MFA_SETUP') {

                }
                else {
                   // this is where the user is signed in but didn't check his attribute
                    this.checkContact(user);
                }
            });

checkContact(user) {
        // check the user attributes
        // if email or phone_number found not verified, call Auth.verifyCurrentUserAttribute() to verify it
        // if not completed, sign the user out.
}

What do you think?

bionicles commented 5 years ago

The issue involves Sign Up, not Sign In. This service has a major security hole because when you sign up with both email and phone, the user is “authentic” even if they only provide a phone number verification code and no email code.

Just imagine how easily bad actors can get fake phone numbers and sign up with other people’s emails. This is extremely easy. They could even use a device to intercept SMS and/or spoof your spoof your phone, so they create an account with your email and phone number! Then they’ve basically stolen your identity...because this fix has not happened in nearly 2 months since we reported it! This is a major security hole in Amplify and Cognito. For what reason do you guys seem to ignore and minimize it?

How do you expect us to launch web platforms on Amplify + Cognito if hackers can easily validate accounts for other people’s emails?!?

bionicles commented 5 years ago

@mlabieniec It’s safety critical for medical data.

would it be possible for you to do us a small favor and fix this one first thing tomorrow?

rachitdhall commented 5 years ago

Hello, the supported method for verifying both phone and email is to use the following process:

GetUserAttributeVerificationCode and VerifyUserAttribute APIs both need the user to provide access token in order to be authenticated, but these APIs can only be called once the user’s account has been confirmed and signed-in. So the steps are:

  1. In the client app interface, on the signup page, the end user provides an email address and a phone number, and then clicks a ‘Sign-up’ button.
  2. The client code calls the SignUp API action, which initiates the phone number verification flow, and the user pool sends a code via SMS to the user.
  3. The client interface goes to a confirmation page, where the user enters the code received in #2 and confirms the account as well as verifying the phone number using the ConfirmSignUp API action.
  4. At this point user status is confirmed, phone number is verified, but email is not verified.
  5. The client code should call InitiateAuth API to obtain the access token for the user and then the corresponding RespondToAuthChallenge.
  6. Using the access token received in #5, the client code calls GetUserAttributeVerificationCode for the email attribute. This sends a code to the registered email address.
  7. Once the user provides the code, VerifyUserAttribute API action is called with the code. Now the email address is verified.

Once #5 is done, given that the end user is authenticated, applications can also use the id token to determine whether email is verified or not by checking the value of email_verified attribute. The app logic could be that every time it gets a new token, it looks for unverified attributes and provides user an option to verify them if they want.

As communicated last week and in our previous conversations, this is the best way to achieve phone and email verification during account signup at this time.

bionicles commented 5 years ago

This issue is not fixed. how do you justify closing this just based on a "workaround?" --

hacker can still create accounts with emails they don't own. the workaround still requires an extra step and doesnt solve that key issue we care about

Sorry but this means we will not be using AWS Amplify. just going to do it ourselves because AWS Amplify Cognito drops the ball on this critical security issue. I feel extremely disappointed you guys (@mlabieniec @rachitdhall Raja Jadeja, whole amplify cognito auth team) won't fix this critical matter of data security because I thought AWS was about customers.

If there is this serious of an issue in simply signing up a user, and if it takes this long to get IGNORED for a solution, then how do you expect anyone to trust this solution? I certainly have lost trust in AWS over this.

I highly recommend no one use Amplify Cognito Auth for sensitive data!

JustFly1984 commented 5 years ago

Please reopen. @bionicles please provide example in public repo

bionicles commented 5 years ago

@JustFly1984 still working on it, thinking about Availability issues with public and private key encryption of user data in gun.js

Ideally we just want to do this: **1. Auth.signUp(userDataObject)

  1. Auth.confirmSignup(emailCode, phoneCode)**
bionicles commented 5 years ago

@mlabieniec @JustFly1984 @rachitdhall @powerful23 we just exploited this vulnerability against our own bitpharma.com cognito user pool to confirm jeff@amazon.com

posted the proof on twitter : https://twitter.com/bitpharma/status/1062368063478288384

this hole has been here for months guys. wake up

JustFly1984 commented 5 years ago

@bionicles I think you need to open new issue with link to this issue.

adrianhall commented 5 years ago

@bionicles,

As you know, we (AWS) have reviewed your GitHub issues (#1685, #1959, and #2102), replied multiple times, and spoke with you on the phone. Just to summarize:

We understand that you “expect the system to send verification to both the user's phone and email” during signup. However, as we state in our documentation, this is not yet a feature Cognito supports:

Important If a user signs up with both a phone number and an email address, and your user pool settings require verification of both attributes, a verification code is sent via SMS to the phone. The email address is not verified, so your app needs to call GetUser to see if an email address is awaiting verification. If it is, the app should call GetUserAttributeVerificationCode to initiate the email verification flow and then submit the verification code by calling VerifyUserAttribute.

While most customers' use cases have been satisfied with the ability to verify either by phone number OR email address, we understand that your particular application has the requirement to verify both phone number AND email address. We've therefore provided you instructions on how your application can verify both the user's phone and email in the Cognito Developer Guide and GitHub issue #1959. As we’ve also shared, we’re happy to help you implement this in your app.

We understand that you’d prefer the service offer the feature above more easily, but this is not a security issue in the service as it’s working as documented. Your screenshot in issue #2102 does not demonstrate a security vulnerability. In your example, the user shows confirmed. A viewer might incorrectly assume that the jeff@ email address was used to confirm the user, however if you click on the username you can view the user details page where we clearly show that jeff@ email address itself is not verified. The user was confirmed via phone, matching the Cognito documentation. We do appreciate your feedback, and agree that we could probably make the UI clearer. We will move quickly on trying to make those tweaks. We will also explore your feature request of verifying users by both email and phone number for our longer-term roadmap, however, we understand if Cognito does not yet meet your immediate needs for this project.

Thank you for sharing your feedback,

(Posted on behalf of...) Saroj Thatte GM, Amazon Cognito

Xcode09 commented 5 years ago

Hello, the supported method for verifying both phone and email is to use the following process:

GetUserAttributeVerificationCode and VerifyUserAttribute APIs both need the user to provide access token in order to be authenticated, but these APIs can only be called once the user’s account has been confirmed and signed-in. So the steps are:

  1. In the client app interface, on the signup page, the end user provides an email address and a phone number, and then clicks a ‘Sign-up’ button.
  2. The client code calls the SignUp API action, which initiates the phone number verification flow, and the user pool sends a code via SMS to the user.
  3. The client interface goes to a confirmation page, where the user enters the code received in #2 and confirms the account as well as verifying the phone number using the ConfirmSignUp API action.
  4. At this point user status is confirmed, phone number is verified, but email is not verified.
  5. The client code should call InitiateAuth API to obtain the access token for the user and then the corresponding RespondToAuthChallenge.
  6. Using the access token received in #5, the client code calls GetUserAttributeVerificationCode for the email attribute. This sends a code to the registered email address.
  7. Once the user provides the code, VerifyUserAttribute API action is called with the code. Now the email address is verified.

Once #5 is done, given that the end user is authenticated, applications can also use the id token to determine whether email is verified or not by checking the value of email_verified attribute. The app logic could be that every time it gets a new token, it looks for unverified attributes and provides user an option to verify them if they want.

As communicated last week and in our previous conversations, this is the best way to achieve phone and email verification during account signup at this time.

i am facing same problem .i called the GetUserAttributeVerificationCode function swift but i cannot received any code in email and results are nil?kindly help me Thanks

github-actions[bot] commented 3 years ago

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels or Discussions for those types of questions.