Skip to content

Login throttling should be per-user #3564

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 25, 2018
Merged

Conversation

redshiftzero
Copy link
Contributor

@redshiftzero redshiftzero commented Jun 25, 2018

Status

Ready for review

Description of Changes

Fixes #3563.

Changes proposed in this pull request:

Testing

  • Reproduce original bug following STR in Login throttling should be per-user #3563
  • Checkout the regression test without the fix (i.e. check out e128b04) and verify it fails
  • Apply the fix in 369b472, the regression test should now pass and logging in as the second user in the STR should now result in success

Deployment

To be deployed in securedrop-app-code deb package tomorrow

Checklist

If you made changes to the server application code:

  • Linting (make ci-lint) and tests (make -C securedrop test) pass in the development container

If you made non-trivial code changes:

  • I have written a test plan and validated it for this PR

We try to login multiple times as one user, trigger the login
throttling, and then switch to a second user and try to login
again. This second user should be able to login despite the
tricksy behavior of the first.
@redshiftzero redshiftzero added this to the 0.8 milestone Jun 25, 2018
@redshiftzero redshiftzero requested a review from a user June 25, 2018 18:00
@redshiftzero redshiftzero requested a review from emkll June 25, 2018 18:00
@redshiftzero
Copy link
Contributor Author

(once merged this should get backported into 0.8.0)

@codecov-io
Copy link

Codecov Report

Merging #3564 into develop will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff            @@
##           develop    #3564   +/-   ##
========================================
  Coverage    85.12%   85.12%           
========================================
  Files           37       37           
  Lines         2367     2367           
  Branches       260      260           
========================================
  Hits          2015     2015           
  Misses         289      289           
  Partials        63       63
Impacted Files Coverage Δ
models.py 88.35% <0%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update af5df30...369b472. Read the comment docs.

Copy link
Contributor

@emkll emkll left a comment

Choose a reason for hiding this comment

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

@redshiftzero thanks for adding a regression test and providing a test plan, changes look good.

One thing I've discovered while doing manual testing of this PR: logins for invalid usernames are not throttled. This would allow an attacker to potentially enumerate journalist usernames. Given that it requires an ATHS token, I think the risk is quite small.

@redshiftzero
Copy link
Contributor Author

Very good point, marking as wip for a bit

@redshiftzero redshiftzero changed the title Login throttling should be per-user [wip] Login throttling should be per-user Jun 25, 2018
@redshiftzero
Copy link
Contributor Author

Actually, upon investigation, this is actually the case on develop also - this is due to the fact we check if the username is valid prior to checking the number of prior login attempts.

@redshiftzero
Copy link
Contributor Author

And since in the journalist_login_attempt table we have journalist_id as a foreign key to the journalist table, we can't actually store or track login attempts for non-journalists users... so this is something that we should file as a followup and address in 0.9.0

@redshiftzero redshiftzero changed the title [wip] Login throttling should be per-user Login throttling should be per-user Jun 25, 2018
@redshiftzero redshiftzero merged commit 0a90136 into develop Jun 25, 2018
@redshiftzero redshiftzero deleted the fix-login-throttling branch June 25, 2018 19:40
@redshiftzero
Copy link
Contributor Author

(here's a regression test for that other bug for later)

diff --git a/securedrop/tests/test_journalist.py b/securedrop/tests/test_journalist.py
index 13426872..098ddb8b 100644
--- a/securedrop/tests/test_journalist.py
+++ b/securedrop/tests/test_journalist.py
@@ -231,6 +231,38 @@ def test_login_throttle_is_not_global(journalist_app, test_journo, test_admin):
         models.LOGIN_HARDENING = False
 
 
+def test_login_throttle_works_for_invalid_usernames(journalist_app,
+                                                    test_journo, test_admin):
+
+    # Overwrite the default value used during testing
+    # Note that this may break other tests if doing parallel testing
+    models.LOGIN_HARDENING = True
+    try:
+        with journalist_app.test_client() as app:
+            for _ in range(Journalist._MAX_LOGIN_ATTEMPTS_PER_PERIOD):
+                resp = app.post(
+                    url_for('main.login'),
+                    data=dict(username='invalid',
+                              password='invalid',
+                              token='invalid'))
+                assert resp.status_code == 200
+                text = resp.data.decode('utf-8')
+                assert "Login failed" in text
+
+            resp = app.post(
+                url_for('main.login'),
+                data=dict(username='invalid',
+                          password='invalid',
+                          token='invalid'))
+            assert resp.status_code == 200
+            text = resp.data.decode('utf-8')
+            assert ("Please wait at least {} seconds".format(
+                Journalist._LOGIN_ATTEMPT_PERIOD) in text)
+
+    finally:
+        models.LOGIN_HARDENING = False
+
+
 def test_login_invalid_credentials(journalist_app, test_journo):
     with journalist_app.test_client() as app:
         resp = app.post(url_for('main.login'),

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.

Login throttling should be per-user
3 participants