From e91bc26da685c280f46f1b9136eeab26d3edc8cc Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 23 Jan 2019 07:09:20 -0800 Subject: [PATCH] Don't rate limit users clicking "Wait Patiently" at an MFA gate even if they typed some text earlier Summary: Depends on D20017. Ref T13222. Currently, if you: - type some text at a TOTP gate; - wait ~60 seconds for the challenge to expire; - submit the form into a "Wait patiently" message; and - mash that wait button over and over again very patiently ...you still rack up rate limiting points, because the hidden text from your original request is preserved and triggers the "is the user responding to a challenge" test. Only perform this test if we haven't already decided that we're going to make them wait. Test Plan: - Did the above; before patch: rate limited; after patch: not rate limited. - Intentionally typed a bunch of bad answers which were actually evaluated: rate limited properly. Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13222 Differential Revision: https://secure.phabricator.com/D20018 --- .../auth/engine/PhabricatorAuthSessionEngine.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/applications/auth/engine/PhabricatorAuthSessionEngine.php b/src/applications/auth/engine/PhabricatorAuthSessionEngine.php index cef2323209..1fa2dadfd6 100644 --- a/src/applications/auth/engine/PhabricatorAuthSessionEngine.php +++ b/src/applications/auth/engine/PhabricatorAuthSessionEngine.php @@ -557,9 +557,18 @@ final class PhabricatorAuthSessionEngine extends Phobject { // Limit factor verification rates to prevent brute force attacks. $any_attempt = false; foreach ($factors as $factor) { + $factor_phid = $factor->getPHID(); + $provider = $factor->getFactorProvider(); $impl = $provider->getFactor(); + // If we already have a result (normally "wait..."), we won't try + // to validate whatever the user submitted, so this doesn't count as + // an attempt for rate limiting purposes. + if (isset($validation_results[$factor_phid])) { + continue; + } + if ($impl->getRequestHasChallengeResponse($factor, $request)) { $any_attempt = true; break;