From 327eb0219d18e2d3e8579fe6ab63f1ec0a976b9e Mon Sep 17 00:00:00 2001 From: Ravi Khadiwala Date: Thu, 9 Jun 2022 13:35:14 -0400 Subject: [PATCH] Bypass account registration captcha on test devices --- .../controllers/AccountController.java | 5 ++- .../controllers/AccountControllerTest.java | 41 ++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/AccountController.java b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/AccountController.java index 2ae19bbe9..1d4f01194 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/AccountController.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/AccountController.java @@ -728,8 +728,11 @@ public class AccountController { Optional pushChallenge, String userAgent) { - final String countryCode = Util.getCountryCode(number); + if (testDevices.containsKey(number)) { + return new CaptchaRequirement(false, false); + } + final String countryCode = Util.getCountryCode(number); if (captchaToken.isPresent()) { boolean validToken = recaptchaClient.verify(captchaToken.get(), sourceHost); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/AccountControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/AccountControllerTest.java index 2f93b6c31..71c21cceb 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/AccountControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/AccountControllerTest.java @@ -19,6 +19,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @@ -127,6 +128,9 @@ class AccountControllerTest { private static final String VALID_CAPTCHA_TOKEN = "valid_token"; private static final String INVALID_CAPTCHA_TOKEN = "invalid_token"; + private static final String TEST_NUMBER = "+14151111113"; + private static final Integer TEST_VERIFICATION_CODE = 123456; + private static StoredVerificationCodeManager pendingAccountsManager = mock(StoredVerificationCodeManager.class); private static AccountsManager accountsManager = mock(AccountsManager.class); private static AbusiveHostRules abusiveHostRules = mock(AbusiveHostRules.class); @@ -174,7 +178,7 @@ class AccountControllerTest { smsSender, dynamicConfigurationManager, turnTokenGenerator, - new HashMap<>(), + Map.of(TEST_NUMBER, TEST_VERIFICATION_CODE), recaptchaClient, gcmSender, apnSender, @@ -499,6 +503,7 @@ class AccountControllerTest { verify(abusiveHostRules).isBlocked(eq(NICE_HOST)); } + @Test void testSendCodeImpossibleNumber() { final Response response = @@ -1031,6 +1036,22 @@ class AccountControllerTest { verifyNoMoreInteractions(smsSender); } + @Test + void testSendCodeTestDeviceNumber() throws Exception { + // no push code and a blocked host, but should evade captchas and skip smsSender + Response response = + resources.getJerseyTest() + .target(String.format("/v1/accounts/sms/code/%s", TEST_NUMBER)) + .request() + .header("X-Forwarded-For", ABUSIVE_HOST) + .get(); + ArgumentCaptor captor = ArgumentCaptor.forClass(StoredVerificationCode.class); + verify(pendingAccountsManager).store(eq(TEST_NUMBER), captor.capture()); + assertThat(captor.getValue().getCode()).isEqualTo(Integer.toString(TEST_VERIFICATION_CODE)); + assertThat(response.getStatus()).isEqualTo(200); + verifyNoInteractions(smsSender); + } + @ParameterizedTest @ValueSource(booleans = {false, true}) void testVerifyCode(final boolean enrolledInVerifyExperiment) throws Exception { @@ -1235,6 +1256,24 @@ class AccountControllerTest { assertThat(response.getStatus()).isEqualTo(200); } + @Test + void testVerifyTestDeviceNumber() throws Exception { + + when(pendingAccountsManager.getCodeForNumber(TEST_NUMBER)).thenReturn(Optional.of( + new StoredVerificationCode(Integer.toString(TEST_VERIFICATION_CODE), System.currentTimeMillis(), "push", null))); + + + final Response response = resources.getJerseyTest() + .target(String.format("/v1/accounts/code/%s", TEST_VERIFICATION_CODE)) + .request() + .header("Authorization", AuthHelper.getProvisioningAuthHeader(TEST_NUMBER, "bar")) + .put(Entity.entity(new AccountAttributes(), MediaType.APPLICATION_JSON_TYPE)); + + verify(accountsManager).create(eq(TEST_NUMBER), eq("bar"), any(), any(), anyList()); + assertThat(response.getStatus()).isEqualTo(200); + + } + @Test void testChangePhoneNumber() throws Exception { final String number = "+18005559876";