Skip to content

LG-260 Separate otp request tracking and throttling for verified phones#2388

Merged
stevegsa merged 5 commits intomasterfrom
stevegsa-lock-any-account-with-victims-phone
May 15, 2020
Merged

LG-260 Separate otp request tracking and throttling for verified phones#2388
stevegsa merged 5 commits intomasterfrom
stevegsa-lock-any-account-with-victims-phone

Conversation

@stevegsa
Copy link
Contributor

@stevegsa stevegsa commented Jul 28, 2018

Why: So throttling a user with an unverified phone does not throttle a user with a verified phone and we can track these otp requests separately.

How: Add a new phone_confirmed true/false column to the otp_requests_trackers. Add a new unique index for phone_fingerprint + phone_confirmed. Then drop the unique index for phone_fingerprint. Force any interaction with the table to use the new composite key.

Hi! Before submitting your PR for review, and/or before merging it, please
go through the checklists below. These represent the more critical elements
of our code quality guidelines. The rest of the list can be found in
CONTRIBUTING.md

Controllers

  • When adding a new controller that requires the user to be fully
    authenticated, make sure to add before_action :confirm_two_factor_authenticated
    as the first callback.

Database

  • Unsafe migrations are implemented over several PRs and over several
    deploys to avoid production errors. The strong_migrations gem
    will warn you about unsafe migrations and has great step-by-step instructions
    for various scenarios.

  • Indexes were added if necessary. This article provides a good overview
    of indexes in Rails.

  • Verified that the changes don't affect other apps (such as the dashboard)

  • When relevant, a rake task is created to populate the necessary DB columns
    in the various environments right before deploying, taking into account the users
    who might not have interacted with this column yet (such as users who have not
    set a password yet)

  • Migrations against existing tables have been tested against a copy of the
    production database. See LG-228 Make migrations safer and more resilient #2127 for an example when a migration caused deployment
    issues. In that case, all the migration did was add a new column and an index to
    the Users table, which might seem innocuous.

Encryption

  • The changes are compatible with data that was encrypted with the old code.

Routes

  • GET requests are not vulnerable to CSRF attacks (i.e. they don't change
    state or result in destructive behavior).

Session

  • When adding user data to the session, use the user_session helper
    instead of the session helper so the data does not persist beyond the user's
    session.

Testing

  • Tests added for this feature/bug
  • Prefer feature/integration specs over controller specs
  • When adding code that reads data, write tests for nil values, empty strings,
    and invalid inputs.

@stevegsa
Copy link
Contributor Author

Table update:

screen shot 2018-07-27 at 7 22 05 pm

@stevegsa stevegsa force-pushed the stevegsa-lock-any-account-with-victims-phone branch 2 times, most recently from 2b9c5ab to b15b5ca Compare July 28, 2018 03:18
jgsmith-usds
jgsmith-usds previously approved these changes Jul 30, 2018

def up
add_column :otp_requests_trackers, :phone_confirmed, :boolean
change_column_default :otp_requests_trackers, :phone_confirmed, false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works, but why not just put this on the previous line with default: false?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strong migrations prevented it.

@stevegsa stevegsa force-pushed the stevegsa-lock-any-account-with-victims-phone branch from b15b5ca to f74efd0 Compare July 31, 2018 00:34
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit of a nit, but thoughts on changing this up to take additional args as options, e.g.

def self.find_or_create_with_phone(phone, phone_confirmed:)
  # ...
end

@stevegsa stevegsa force-pushed the stevegsa-lock-any-account-with-victims-phone branch from f74efd0 to 75c956f Compare August 7, 2018 16:55
@monfresh
Copy link
Contributor

For visibility and transparency, Steve and I discussed this last week on Slack, and I proposed a different solution that would simplify things and allow us to eliminate the OtpRequestsTracker table. This issue was placed in the backlog a while back (because we were still trying to find the best solution), and as far as I know, hasn't been officially prioritized again by any end user product manager.

This PR addresses one particular scenario, where user B who knows user A's phone number could attempt to sign up with user A's number, and keep requesting OTPs until they get locked out, which would also prevent user A from signing in because they would be locked out as well. However, it doesn't address the scenario where user B knows that user A wants to change their phone number to number X, and user B could request OTPs to phone number X until they get locked out, at which point user A would not be able to change their number to phone number X, or use this phone to verify their identity.

The fundamental problem with the original rate limiting solution we came up with is that we are locking out users, thereby adversely affecting legitimate users. I propose that we stop locking out users. Instead, what does the team think about implementing a general rate limit of X number of OTP requests over Y period of time per user, not per phone number? Twilio recommends 1 request per minute, which is essentially what our current Figaro settings average out to. Instead of locking out users, we display an error message similar to the one GitHub shows:

screen shot 2018-08-07 at 10 45 34 am

Also, we want to make sure to track as much information as possible about these events, such as the context. Right now, we can't easily tell if they're happening mainly during authentication or confirmation.

@stevegsa
Copy link
Contributor Author

stevegsa commented Aug 13, 2018

@monfresh The solution you mention opens us up to an unlimited number of sms requests by any number of users to arbitrary phone numbers and worse a coordinated unthrottled multi-user attack to a single number (ie 1000 simultaneous sms requests to phone number X). The solution as presented prioritizes users that already have a registered phone which is the case a majority of the time in the lifecycle of the user. That is also the exact attack vector that was submitted to h1 (preventing login of a registered user/phone). Moreover I was assigned to all the issues in h1 in May by the director and fixed all of them except this one because it was assigned to another developer by the PM. When that developer removed himself from the issue in August I resolved it since we had 30 days to resolve any h1 issue.

@monfresh
Copy link
Contributor

That's a good point (about the multiple accounts sending an OTP at the same time to the same number). It's worth noting that Twilio's Verify service has rate limiting built in, which I believe will prevent this. I couldn't find much documentation, but I've seen some users in our logs hitting this rate limit when they've tried to request a bunch of OTPs over a short period of time. Twilio blocked this before our own rate limiting code kicked in.

I think it's worth spending time brainstorming some more solutions that can balance usability and security. For example, this small UI tweak can slow down how many requests a user can make: remove the "Get another code" link from the OTP verification screen. This is most likely how the user I saw in the logs was able to make so many requests within the same second: they just clicked the link a bunch of times really fast, which I can easily reproduce.

@stevegsa
Copy link
Contributor Author

stevegsa commented Aug 13, 2018

Yep. I won't merge unless we're all onboard.

@konklone
Copy link
Contributor

FWIW, the 30 day response time for H1 is not a binding thing, but was our goal as an office to measure our own response time, and to encourage a positive and responsive relationship with the security community. And our contract with H1 is over anyhow. So if the team thinks this merits further discussion, by all means.

@monfresh
Copy link
Contributor

Should we close this for now, until we discuss this further? See the JIRA issue for a link to the updated Google Doc where I wrote my thoughts.

@stevegsa
Copy link
Contributor Author

No. Let's plan on a group meeting on this one first.

@stevegsa
Copy link
Contributor Author

I'll look at your doc and add comments.

@jmhooper
Copy link
Contributor

@stevegsa: This one has been sitting here for a while. Any objections to closing it?

@brodygov
Copy link
Contributor

brodygov commented Mar 4, 2019

I added some discussion to the Jira ticket, but it would be good to at least make a decision on what to do with the outstanding HackerOne report.

Are there still current objections to merging / adopting the current proposal as-is? I do see that there are now merge conflicts.

IMO it's good to continue rate limiting on phone number, and we shouldn't feel obligated to solve all rate limiting problems in this space upfront. The sign-in lockout issue is particularly bad, even though we've never seen evidence of exploitation. So I like this current proposal of separating rate limits based on whether the phone number has been confirmed.

@lauraGgit lauraGgit closed this Mar 13, 2019
@stevegsa stevegsa reopened this May 6, 2020
…es and unverified phones.

**Why**: So throttling a user with an unverified phone does not throttle a user with a verified phone and we can track these otp requests separately.

**How**: Add a new phone_confirmed true/false column to the otp_requests_trackers.  Add a new unique index for phone_fingerprint + phone_confirmed.  Then drop the unique index for phone_fingerprint.  Force any interaction with the table to use the new composite key.
@stevegsa stevegsa force-pushed the stevegsa-lock-any-account-with-victims-phone branch from 75c956f to 1f1132b Compare May 14, 2020 18:02
@stevegsa stevegsa merged commit 4f9191b into master May 15, 2020
@stevegsa stevegsa deleted the stevegsa-lock-any-account-with-victims-phone branch May 15, 2020 23:30
achapm added a commit that referenced this pull request May 20, 2020
* Update saml_idp revision

* Lg 2939 update us gov banner (#3751)

Add 'Here's how you know' section LG-2939

**Why**: So users can be confident in legitimacy/security of the site
**How**: Base layout renders single ERB banner; JS enables toggling

Co-authored-by: Nick Ng <nick.ng@gsa.gov>

* [Snyk] Fix for 1 vulnerabilities (#3746)

* fix: package.json & .snyk to reduce vulnerabilities

The following vulnerabilities are fixed with a Snyk patch:
- https://snyk.io/vuln/SNYK-JS-LODASH-567746

* Copy over .snyk too

Co-authored-by: Zach Margolis <zachary.margolis@gsa.gov>

* Add spec to make sure that re-proofing costs behave as expected (#3754)

* Fix spec to reflect the fact that we've removed SingleLogoutService

* Revert "[Snyk] Fix for 1 vulnerabilities (#3746)" (#3755)

This reverts commit 9323c2a.

* fix bundler config to work (#3759)

* Add deal and IAA information to service_providers table (LG-2865) (#3756)

* Add deal and IAA information to service_providers table (LG-2865)

**Why**: So that we can track metadata associated with SPs better

* Various accessibility Fixes (#3761)

* Fix TOTP setup nickname label (LG-2986)
**Why**: Screen readers use this to describe the field, the
old label was for a different field

* Update accordion header's role to be a button (LG-2985)
**Why**: It's intended to be clicked to show/hide information

* Make the TOTP key copy button a button (LG-2987)
**Why**: So it can be detected by screen readers as clickable

* Make cancel link a button role on account deletion page (LG-2988)
**Why**: Better screen reader support

* Make sure hidden webauthn element is skipped by screen readers (LG-2984) (#3762)

**Why**: Merely styling it as hidden, or setting aria-hidden does
not hide sufficiently from screen readers, so we use the HTML5
"hidden" attribute to do this.

* Update GSA logo alt text for screen readers (LG-2983) (#3763)

**Why**: The alt text and link text both described GSA
so now it's just the link text

* LG-2959 Add a missing `return` statement when a Acuant SDK file is not permitted (#3765)

**Why**: So the execution does not continue leading to a 500 error

* Remove load testing scripts (#3764)


**Why**: They were moved to their own repository
(https://github.com/18f/identity-loadtest/)

* Fix typo in method name (#3766)

* Update order of elements in footer to match visual order (LG-2989) (#3768)

* fix: package.json to reduce vulnerabilities (#3757)

The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-YARGSPARSER-560381

* Remove the Acuant SDK from the desktop flow (#3767)

**Why**: People using the desktop flow have to use a file picker already. Having the SDK there only means they have to wait for it to load.

* LG-2375 Don't truncate the return to SP link (#3770)

**Why**: SPs have names of varying length. Before this commit you can't read the name of SPs with long names.

* Fix positioning of remember-this-browser checkbox (#3769)

* Fix positioning of remember-this-browser checkbox

**Why**: LG-1047 - chk + label are on diff. lines on some mobile devices
**How**: Added flex container and leveraged several USWDS classes

* Cleanup

**Why**: To improve ERB template readability
**How**: Better indentation; hash keys on multiple lines

* Update yarn.lock (#3771)

- To match package.json updates in #3757

* LG-2936 Add liveness check to main doc auth flow (#3758)

* Hide/show email error messages via HTML5 hidden attribute (LG-2996) (#3773)

**Why**: We got reports from an accessibility audit that
IE 11 + JAWS was still reading these even though they're
hidden by CSS

* LG-260 Separate otp request tracking and throttling for verified phones (#2388)

**Why**: So throttling a user with an unverified phone does not throttle a user with a verified phone and we can track these otp requests separately.

**How**: Add a new phone_confirmed true/false column to the otp_requests_trackers.  Add a new unique index for phone_fingerprint + phone_confirmed.  Then drop the unique index for phone_fingerprint.  Force any interaction with the table to use the new composite key.

* Bring back i18n keys removed in #3767 (#3776)

**Why**: They're still used

* Account Delete: Require Password (LG-2964) (#3775)

* Update account delete to require a password on the page (LG-2964)
**Why**: To prevent drive-by deletions from leaving a screen
unlocked

* users/delete#show: slim to ERB conversion
* Add analytics tracking

Co-authored-by: Shade L. Jenifer <shade.jenifer@gsa.gov>
Co-authored-by: Nick Ng <nick.ng@gsa.gov>
Co-authored-by: Snyk bot <snyk-bot@snyk.io>
Co-authored-by: Zach Margolis <zachary.margolis@gsa.gov>
Co-authored-by: Zach Margolis <zachmargolis@users.noreply.github.com>
Co-authored-by: Tim Spencer <timothy.spencer@gsa.gov>
Co-authored-by: Jonathan Hooper <jonathan.hooper@gsa.gov>
Co-authored-by: Steve Urciuoli <steve.urciuoli@gsa.gov>
achapm added a commit that referenced this pull request May 20, 2020
* Update saml_idp revision

* Lg 2939 update us gov banner (#3751)

Add 'Here's how you know' section LG-2939

**Why**: So users can be confident in legitimacy/security of the site
**How**: Base layout renders single ERB banner; JS enables toggling

Co-authored-by: Nick Ng <nick.ng@gsa.gov>

* [Snyk] Fix for 1 vulnerabilities (#3746)

* fix: package.json & .snyk to reduce vulnerabilities

The following vulnerabilities are fixed with a Snyk patch:
- https://snyk.io/vuln/SNYK-JS-LODASH-567746

* Copy over .snyk too

Co-authored-by: Zach Margolis <zachary.margolis@gsa.gov>

* Add spec to make sure that re-proofing costs behave as expected (#3754)

* Fix spec to reflect the fact that we've removed SingleLogoutService

* Revert "[Snyk] Fix for 1 vulnerabilities (#3746)" (#3755)

This reverts commit 9323c2a.

* fix bundler config to work (#3759)

* Add deal and IAA information to service_providers table (LG-2865) (#3756)

* Add deal and IAA information to service_providers table (LG-2865)

**Why**: So that we can track metadata associated with SPs better

* Various accessibility Fixes (#3761)

* Fix TOTP setup nickname label (LG-2986)
**Why**: Screen readers use this to describe the field, the
old label was for a different field

* Update accordion header's role to be a button (LG-2985)
**Why**: It's intended to be clicked to show/hide information

* Make the TOTP key copy button a button (LG-2987)
**Why**: So it can be detected by screen readers as clickable

* Make cancel link a button role on account deletion page (LG-2988)
**Why**: Better screen reader support

* Make sure hidden webauthn element is skipped by screen readers (LG-2984) (#3762)

**Why**: Merely styling it as hidden, or setting aria-hidden does
not hide sufficiently from screen readers, so we use the HTML5
"hidden" attribute to do this.

* Update GSA logo alt text for screen readers (LG-2983) (#3763)

**Why**: The alt text and link text both described GSA
so now it's just the link text

* LG-2959 Add a missing `return` statement when a Acuant SDK file is not permitted (#3765)

**Why**: So the execution does not continue leading to a 500 error

* Remove load testing scripts (#3764)


**Why**: They were moved to their own repository
(https://github.com/18f/identity-loadtest/)

* Fix typo in method name (#3766)

* Update order of elements in footer to match visual order (LG-2989) (#3768)

* fix: package.json to reduce vulnerabilities (#3757)

The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-YARGSPARSER-560381

* Remove the Acuant SDK from the desktop flow (#3767)

**Why**: People using the desktop flow have to use a file picker already. Having the SDK there only means they have to wait for it to load.

* LG-2375 Don't truncate the return to SP link (#3770)

**Why**: SPs have names of varying length. Before this commit you can't read the name of SPs with long names.

* Fix positioning of remember-this-browser checkbox (#3769)

* Fix positioning of remember-this-browser checkbox

**Why**: LG-1047 - chk + label are on diff. lines on some mobile devices
**How**: Added flex container and leveraged several USWDS classes

* Cleanup

**Why**: To improve ERB template readability
**How**: Better indentation; hash keys on multiple lines

* Update yarn.lock (#3771)

- To match package.json updates in #3757

* LG-2936 Add liveness check to main doc auth flow (#3758)

* Hide/show email error messages via HTML5 hidden attribute (LG-2996) (#3773)

**Why**: We got reports from an accessibility audit that
IE 11 + JAWS was still reading these even though they're
hidden by CSS

* LG-260 Separate otp request tracking and throttling for verified phones (#2388)

**Why**: So throttling a user with an unverified phone does not throttle a user with a verified phone and we can track these otp requests separately.

**How**: Add a new phone_confirmed true/false column to the otp_requests_trackers.  Add a new unique index for phone_fingerprint + phone_confirmed.  Then drop the unique index for phone_fingerprint.  Force any interaction with the table to use the new composite key.

* Bring back i18n keys removed in #3767 (#3776)

**Why**: They're still used

* Account Delete: Require Password (LG-2964) (#3775)

* Update account delete to require a password on the page (LG-2964)
**Why**: To prevent drive-by deletions from leaving a screen
unlocked

* users/delete#show: slim to ERB conversion
* Add analytics tracking

Co-authored-by: Shade L. Jenifer <shade.jenifer@gsa.gov>
Co-authored-by: Nick Ng <nick.ng@gsa.gov>
Co-authored-by: Snyk bot <snyk-bot@snyk.io>
Co-authored-by: Zach Margolis <zachary.margolis@gsa.gov>
Co-authored-by: Zach Margolis <zachmargolis@users.noreply.github.com>
Co-authored-by: Tim Spencer <timothy.spencer@gsa.gov>
Co-authored-by: Jonathan Hooper <jonathan.hooper@gsa.gov>
Co-authored-by: Steve Urciuoli <steve.urciuoli@gsa.gov>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants