@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add a rate limit for enroll attempts when adding new MFA configurations

Summary:
Depends on D20018. Ref T13222. When you add a new MFA configuration, you can technically (?) guess your way through it with brute force. It's not clear why this would ever really be useful (if an attacker can get here and wants to add TOTP, they can just add TOTP!) but it's probably bad, so don't let users do it.

This limit is fairly generous because I don't think this actually part of any real attack, at least today with factors we're considering.

Test Plan:
- Added TOTP, guessed wrong a ton of times, got rate limited.
- Added TOTP, guessed right, got a TOTP factor configuration added to my account.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13222

Differential Revision: https://secure.phabricator.com/D20019

+47
+2
src/__phutil_library_map__.php
··· 2296 2296 'PhabricatorAuthNeedsApprovalController' => 'applications/auth/controller/PhabricatorAuthNeedsApprovalController.php', 2297 2297 'PhabricatorAuthNeedsMultiFactorController' => 'applications/auth/controller/PhabricatorAuthNeedsMultiFactorController.php', 2298 2298 'PhabricatorAuthNewController' => 'applications/auth/controller/config/PhabricatorAuthNewController.php', 2299 + 'PhabricatorAuthNewFactorAction' => 'applications/auth/action/PhabricatorAuthNewFactorAction.php', 2299 2300 'PhabricatorAuthOldOAuthRedirectController' => 'applications/auth/controller/PhabricatorAuthOldOAuthRedirectController.php', 2300 2301 'PhabricatorAuthOneTimeLoginController' => 'applications/auth/controller/PhabricatorAuthOneTimeLoginController.php', 2301 2302 'PhabricatorAuthOneTimeLoginTemporaryTokenType' => 'applications/auth/tokentype/PhabricatorAuthOneTimeLoginTemporaryTokenType.php', ··· 8021 8022 'PhabricatorAuthNeedsApprovalController' => 'PhabricatorAuthController', 8022 8023 'PhabricatorAuthNeedsMultiFactorController' => 'PhabricatorAuthController', 8023 8024 'PhabricatorAuthNewController' => 'PhabricatorAuthProviderConfigController', 8025 + 'PhabricatorAuthNewFactorAction' => 'PhabricatorSystemAction', 8024 8026 'PhabricatorAuthOldOAuthRedirectController' => 'PhabricatorAuthController', 8025 8027 'PhabricatorAuthOneTimeLoginController' => 'PhabricatorAuthController', 8026 8028 'PhabricatorAuthOneTimeLoginTemporaryTokenType' => 'PhabricatorAuthTemporaryTokenType',
+21
src/applications/auth/action/PhabricatorAuthNewFactorAction.php
··· 1 + <?php 2 + 3 + final class PhabricatorAuthNewFactorAction extends PhabricatorSystemAction { 4 + 5 + const TYPECONST = 'auth.factor.new'; 6 + 7 + public function getActionConstant() { 8 + return self::TYPECONST; 9 + } 10 + 11 + public function getScoreThreshold() { 12 + return 60 / phutil_units('1 hour in seconds'); 13 + } 14 + 15 + public function getLimitExplanation() { 16 + return pht( 17 + 'You have failed too many attempts to synchronize new multi-factor '. 18 + 'authentication methods in a short period of time.'); 19 + } 20 + 21 + }
+24
src/applications/settings/panel/PhabricatorMultiFactorSettingsPanel.php
··· 234 234 $form = id(new AphrontFormView()) 235 235 ->setViewer($viewer); 236 236 237 + if ($request->isFormPost()) { 238 + // Subject users to rate limiting so that it's difficult to add factors 239 + // by pure brute force. This is normally not much of an attack, but push 240 + // factor types may have side effects. 241 + PhabricatorSystemActionEngine::willTakeAction( 242 + array($viewer->getPHID()), 243 + new PhabricatorAuthNewFactorAction(), 244 + 1); 245 + } else { 246 + // Test the limit before showing the user a form, so we don't give them 247 + // a form which can never possibly work because it will always hit rate 248 + // limiting. 249 + PhabricatorSystemActionEngine::willTakeAction( 250 + array($viewer->getPHID()), 251 + new PhabricatorAuthNewFactorAction(), 252 + 0); 253 + } 254 + 237 255 $config = $selected_provider->processAddFactorForm( 238 256 $form, 239 257 $request, 240 258 $user); 241 259 242 260 if ($config) { 261 + // If the user added a factor, give them a rate limiting point back. 262 + PhabricatorSystemActionEngine::willTakeAction( 263 + array($viewer->getPHID()), 264 + new PhabricatorAuthNewFactorAction(), 265 + -1); 266 + 243 267 $config->save(); 244 268 245 269 $log = PhabricatorUserLog::initializeNewLog(