From 1eb2df7586db97e0bd0eef52a40af846b4cee8e3 Mon Sep 17 00:00:00 2001 From: secureness Date: Fri, 13 Sep 2024 14:37:38 +0200 Subject: [PATCH 1/3] init airbyte plugin, tests not finilized yet --- ...WeakCredentialDetectorBootstrapModule.java | 2 + .../airbyte/AirbyteCredentialTester.java | 144 +++++++++++++ .../service_default_credentials.textproto | 10 + .../airbyte/AirbyteCredentialTesterTest.java | 198 ++++++++++++++++++ .../web/WebServiceFingerprinter.java | 34 +++ 5 files changed, 388 insertions(+) create mode 100644 google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTester.java create mode 100644 google/detectors/credentials/generic_weak_credential_detector/src/test/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTesterTest.java diff --git a/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/GenericWeakCredentialDetectorBootstrapModule.java b/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/GenericWeakCredentialDetectorBootstrapModule.java index db865a24a..772a794d4 100644 --- a/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/GenericWeakCredentialDetectorBootstrapModule.java +++ b/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/GenericWeakCredentialDetectorBootstrapModule.java @@ -36,6 +36,7 @@ import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.provider.DefaultCredentials; import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.provider.Top100Passwords; import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.tester.CredentialTester; +import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.testers.airbyte.AirbyteCredentialTester; import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.testers.grafana.GrafanaCredentialTester; import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.testers.hydra.HydraCredentialTester; import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.testers.jenkins.JenkinsCredentialTester; @@ -67,6 +68,7 @@ protected void configurePlugin() { Multibinder credentialTesterBinder = Multibinder.newSetBinder(binder(), CredentialTester.class); + credentialTesterBinder.addBinding().to(AirbyteCredentialTester.class); credentialTesterBinder.addBinding().to(JenkinsCredentialTester.class); credentialTesterBinder.addBinding().to(MlFlowCredentialTester.class); credentialTesterBinder.addBinding().to(MysqlCredentialTester.class); diff --git a/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTester.java b/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTester.java new file mode 100644 index 000000000..f943bf64b --- /dev/null +++ b/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTester.java @@ -0,0 +1,144 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.testers.airbyte; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.tsunami.common.net.http.HttpRequest.get; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableList; +import com.google.common.flogger.GoogleLogger; +import com.google.tsunami.common.data.NetworkEndpointUtils; +import com.google.tsunami.common.data.NetworkServiceUtils; +import com.google.tsunami.common.net.http.HttpClient; +import com.google.tsunami.common.net.http.HttpHeaders; +import com.google.tsunami.common.net.http.HttpResponse; +import com.google.tsunami.common.net.http.HttpStatus; +import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.provider.TestCredential; +import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.tester.CredentialTester; +import com.google.tsunami.proto.NetworkService; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.select.Elements; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.Base64; +import java.util.List; +import javax.inject.Inject; + +/** Credential tester specifically for airbyte. */ +public final class AirbyteCredentialTester extends CredentialTester { + private static final GoogleLogger logger = GoogleLogger.forEnclosingClass(); + private static final String AIRBYTE_SERVICE = "airbyte"; + private static final Logger log = LoggerFactory.getLogger(AirbyteCredentialTester.class); + + private final HttpClient httpClient; + + @Inject + AirbyteCredentialTester(HttpClient httpClient) { + this.httpClient = checkNotNull(httpClient); + } + + @Override + public String name() { + return "AirbyteCredentialTester"; + } + + @Override + public String description() { + return "Airbyte credential tester."; + } + + @Override + public boolean canAccept(NetworkService networkService) { + return NetworkServiceUtils.getWebServiceName(networkService).equals(AIRBYTE_SERVICE); + } + + @Override + public boolean batched() { + return true; + } + + @Override + public ImmutableList testValidCredentials( + NetworkService networkService, List credentials) { + // Always return 1st weak credential to gracefully handle no auth configured case, where we + // return empty credential instead of all the weak credentials + return credentials.stream() + .filter(cred -> isAirbyteAccessible(networkService, cred)) + .findFirst() + .map(ImmutableList::of) + .orElseGet(ImmutableList::of); + } + + private boolean isAirbyteAccessible(NetworkService networkService, TestCredential credential) { + var rootUrl = + "http://" + NetworkEndpointUtils.toUriAuthority(networkService.getNetworkEndpoint()) + "/"; + logger.atWarning().log("============NetworkServiceUtils2;==============="); + try { + HttpResponse rootResponse = + httpClient.send( + get(rootUrl) + .setHeaders( + HttpHeaders.builder() + .addHeader( + "Authorization", + "basic " + + Base64.getEncoder() + .encodeToString( + (credential.username() + + ":" + + credential.password().orElse("")) + .getBytes(UTF_8))) + .build()) + .build()); + + if (!(rootResponse.status() == HttpStatus.OK)) { + return false; + } + + if (rootResponse.status() == HttpStatus.OK + && rootResponse.bodyString().isPresent() + && bodyContainsSuccessLogin(rootResponse.bodyString().get())) { + return true; + } + + } catch (IOException e) { + logger.atWarning().withCause(e).log("Unable to query '%s'.", rootUrl); + return false; + } + return false; + } + + private static boolean bodyContainsSuccessLogin(String responseBody) { + Document doc = Jsoup.parse(responseBody); + String title = doc.title(); + if (title.contains("Airbyte")) { + Elements elements = + doc.head() + .tagName("meta") + .getElementsByAttributeValue( + "content", + "Airbyte is the turnkey open-source data integration " + + "platform that syncs data from applications, APIs and databases to warehouses."); + return !elements.isEmpty(); + } + return false; + } +} diff --git a/google/detectors/credentials/generic_weak_credential_detector/src/main/resources/detectors/credentials/genericweakcredentialdetector/data/service_default_credentials.textproto b/google/detectors/credentials/generic_weak_credential_detector/src/main/resources/detectors/credentials/genericweakcredentialdetector/data/service_default_credentials.textproto index 653b4e5ae..0bf586ff5 100644 --- a/google/detectors/credentials/generic_weak_credential_detector/src/main/resources/detectors/credentials/genericweakcredentialdetector/data/service_default_credentials.textproto +++ b/google/detectors/credentials/generic_weak_credential_detector/src/main/resources/detectors/credentials/genericweakcredentialdetector/data/service_default_credentials.textproto @@ -83,3 +83,13 @@ service_default_credentials { default_usernames: "default" default_passwords: "" } + +service_default_credentials { + service_name: "airbyte" + default_usernames: "airbyte" + default_passwords: "password" + default_usernames: "user@company.example" + default_passwords: "new_password" + default_usernames: "your_new_username_here" + default_passwords: "your_new_password_here" +} diff --git a/google/detectors/credentials/generic_weak_credential_detector/src/test/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTesterTest.java b/google/detectors/credentials/generic_weak_credential_detector/src/test/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTesterTest.java new file mode 100644 index 000000000..81b592efa --- /dev/null +++ b/google/detectors/credentials/generic_weak_credential_detector/src/test/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTesterTest.java @@ -0,0 +1,198 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.testers.airbyte; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.tsunami.common.data.NetworkEndpointUtils.forHostnameAndPort; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +import com.google.common.collect.ImmutableList; +import com.google.inject.Guice; +import com.google.tsunami.common.net.db.ConnectionProviderInterface; +import com.google.tsunami.common.net.http.HttpClientModule; +import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.provider.TestCredential; +import com.google.tsunami.proto.NetworkService; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.sql.Connection; +import java.util.Objects; +import java.util.Optional; +import javax.inject.Inject; +import okhttp3.mockwebserver.Dispatcher; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +/** Tests for {@link AirbyteCredentialTester}. */ +@RunWith(JUnit4.class) +public class AirbyteCredentialTesterTest { + @Rule public MockitoRule rule = MockitoJUnit.rule(); + @Mock private ConnectionProviderInterface mockConnectionProvider; + @Mock private Connection mockConnection; + @Inject private AirbyteCredentialTester tester; + private MockWebServer mockWebServer; + private static final TestCredential WEAK_CRED_1 = + TestCredential.create("default", Optional.of("airbyte")); + private static final TestCredential WRONG_CRED_1 = + TestCredential.create("wrong", Optional.of("password")); + + // the default username and password value for an insecure airbyte instance + private static final String DEFAULT_USERNAME = "default"; + private static final String DEFAULT_PASSWORD = ""; + + @Before + public void setup() { + mockWebServer = new MockWebServer(); + Guice.createInjector(new HttpClientModule.Builder().build()).injectMembers(this); + } + + // + // @Test + // public void detect_weakCredentialsExists_returnsWeakCredentials() throws Exception { + // startMockWebServer(); + // NetworkService targetNetworkService = + // NetworkService.newBuilder() + // .setNetworkEndpoint( + // forHostnameAndPort(mockWebServer.getHostName(), mockWebServer.getPort())) + // .setServiceName("airbyte") + // .build(); + // + // assertThat(tester.testValidCredentials(targetNetworkService, ImmutableList.of(WEAK_CRED_1))) + // .containsExactly(WEAK_CRED_1); + // mockWebServer.shutdown(); + // } + // + // @Test + // public void detect_weakCredentialsExist_returnsFirstWeakCredentials() throws Exception { + // startMockWebServer(); + // NetworkService targetNetworkService = + // NetworkService.newBuilder() + // .setNetworkEndpoint( + // forHostnameAndPort(mockWebServer.getHostName(), mockWebServer.getPort())) + // .setServiceName("airbyte") + // .build(); + // + // assertThat(tester.testValidCredentials(targetNetworkService, ImmutableList.of(WEAK_CRED_1))) + // .containsExactly(WEAK_CRED_1); + // } + + @Test + public void detect_airbyteService_canAccept() throws Exception { + startMockWebServer(); + NetworkService targetNetworkService = + NetworkService.newBuilder() + .setNetworkEndpoint( + forHostnameAndPort(mockWebServer.getHostName(), mockWebServer.getPort())) + .setServiceName("airbyte") + .build(); + + assertThat(tester.canAccept(targetNetworkService)).isTrue(); + } + + // @Test + // public void + // detect_weakCredentialsExistAndAirbyteInForeignLanguage_returnsFirstWeakCredentials() + // throws Exception { + // startMockWebServer(); + // NetworkService targetNetworkService = + // NetworkService.newBuilder() + // .setNetworkEndpoint( + // forHostnameAndPort(mockWebServer.getHostName(), mockWebServer.getPort())) + // .setServiceName("airbyte") + // .build(); + // + // assertThat(tester.testValidCredentials(targetNetworkService, ImmutableList.of(WEAK_CRED_1))) + // .containsExactly(WEAK_CRED_1); + // } + + @Test + public void detect_noWeakCredentials_returnsNoCredentials() throws Exception { + startMockWebServer(); + NetworkService targetNetworkService = + NetworkService.newBuilder() + .setNetworkEndpoint( + forHostnameAndPort(mockWebServer.getHostName(), mockWebServer.getPort())) + .setServiceName("airbyte") + .build(); + assertThat(tester.testValidCredentials(targetNetworkService, ImmutableList.of(WRONG_CRED_1))) + .isEmpty(); + } + + @Test + public void detect_nonAirbyteService_skips() throws Exception { + when(mockConnectionProvider.getConnection(any(), any(), any())).thenReturn(mockConnection); + NetworkService targetNetworkService = + NetworkService.newBuilder() + .setNetworkEndpoint(forHostnameAndPort("example.com", 8080)) + .setServiceName("http") + .build(); + + assertThat(tester.testValidCredentials(targetNetworkService, ImmutableList.of(WEAK_CRED_1))) + .isEmpty(); + verifyNoInteractions(mockConnectionProvider); + } + + private void startMockWebServer() throws IOException { + final Dispatcher dispatcher = + new Dispatcher() { + final MockResponse unauthorizedResponse = + new MockResponse() + .setResponseCode(401) + .setBody( + "{\"detail\":[\"AuthorizationException\"," + + "\"Authentication error: invalid username or password\"]}"); + + @Override + public MockResponse dispatch(RecordedRequest request) { + if (request.getPath().matches("/login") && Objects.equals(request.getMethod(), "GET")) { + return new MockResponse() + .setResponseCode(200) + .setBody(" Airbyte Dashboard "); + } + if (request.getPath().matches("/api/v1/login") + && Objects.equals(request.getMethod(), "POST") + && request + .getBody() + .readString(StandardCharsets.UTF_8) + .contains( + String.format( + "username=%s&password=%s", DEFAULT_USERNAME, DEFAULT_PASSWORD))) { + return new MockResponse() + .setResponseCode(200) + .setBody( + "{\"access_token\":\"An AccessToken\",\"token_type\":\"bearer\"," + + "\"expires_in\":null,\"refresh_token\":null,\"scope\":null}"); + } else { + return unauthorizedResponse; + } + } + }; + mockWebServer.setDispatcher(dispatcher); + mockWebServer.start(); + mockWebServer.url("/"); + } +} diff --git a/google/fingerprinters/web/src/main/java/com/google/tsunami/plugins/fingerprinters/web/WebServiceFingerprinter.java b/google/fingerprinters/web/src/main/java/com/google/tsunami/plugins/fingerprinters/web/WebServiceFingerprinter.java index b713d30d3..db776fc96 100644 --- a/google/fingerprinters/web/src/main/java/com/google/tsunami/plugins/fingerprinters/web/WebServiceFingerprinter.java +++ b/google/fingerprinters/web/src/main/java/com/google/tsunami/plugins/fingerprinters/web/WebServiceFingerprinter.java @@ -280,6 +280,7 @@ private ImmutableSet detectSoftwareByCustomHeuristics( checkForMlflow(detectedSoftware, networkService, startingUrl); checkForZenMl(detectedSoftware, networkService, startingUrl); + checkForAirbyte(detectedSoftware, networkService, startingUrl); return ImmutableSet.copyOf(detectedSoftware); } @@ -372,4 +373,37 @@ private void checkForZenMl( logger.atWarning().withCause(e).log("Unable to query '%s'.", loginUrl); } } + + private void checkForAirbyte( + Set software, NetworkService networkService, String startingUrl) { + logger.atInfo().log("probing Airbyte root page - custom fingerprint phase"); + + var rootUrl = NetworkServiceUtils.buildWebApplicationRootUrl(networkService); + try { + HttpResponse rootResponse = httpClient.send(get(rootUrl).withEmptyHeaders().build()); + // if the airbyte has basic authentication first condition will be pass + // if the airbyte doesn't have any authentication second condition will be pass + if (!(rootResponse.status() == HttpStatus.UNAUTHORIZED + && rootResponse.bodyString().isPresent() + && rootResponse.bodyString().get().contains("Airbyte - Access Denied")) + || (rootResponse.status() == HttpStatus.OK + && rootResponse.bodyString().isPresent() + && rootResponse + .bodyString() + .get() + .contains( + "content=\"Airbyte is the turnkey open-source data integration platform that " + + "syncs data from applications, APIs and databases to warehouses.\""))) { + return; + } + software.add( + DetectedSoftware.builder() + .setSoftwareIdentity(SoftwareIdentity.newBuilder().setSoftware("airbyte").build()) + .setRootPath(startingUrl) + .setContentHashes(ImmutableMap.of()) + .build()); + } catch (IOException e) { + logger.atWarning().withCause(e).log("Unable to query '%s'.", rootUrl); + } + } } From 4ba4edf75ad0e8ed11dc5c5b50eedb7d40201654 Mon Sep 17 00:00:00 2001 From: secureness Date: Fri, 13 Sep 2024 19:17:53 +0200 Subject: [PATCH 2/3] complete tests, remove logs --- .../airbyte/AirbyteCredentialTester.java | 1 - .../airbyte/AirbyteCredentialTesterTest.java | 145 +++++++++--------- 2 files changed, 74 insertions(+), 72 deletions(-) diff --git a/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTester.java b/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTester.java index f943bf64b..637e536d8 100644 --- a/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTester.java +++ b/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTester.java @@ -90,7 +90,6 @@ public ImmutableList testValidCredentials( private boolean isAirbyteAccessible(NetworkService networkService, TestCredential credential) { var rootUrl = "http://" + NetworkEndpointUtils.toUriAuthority(networkService.getNetworkEndpoint()) + "/"; - logger.atWarning().log("============NetworkServiceUtils2;==============="); try { HttpResponse rootResponse = httpClient.send( diff --git a/google/detectors/credentials/generic_weak_credential_detector/src/test/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTesterTest.java b/google/detectors/credentials/generic_weak_credential_detector/src/test/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTesterTest.java index 81b592efa..9d381828e 100644 --- a/google/detectors/credentials/generic_weak_credential_detector/src/test/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTesterTest.java +++ b/google/detectors/credentials/generic_weak_credential_detector/src/test/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTesterTest.java @@ -29,7 +29,6 @@ import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.provider.TestCredential; import com.google.tsunami.proto.NetworkService; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.sql.Connection; import java.util.Objects; import java.util.Optional; @@ -56,13 +55,13 @@ public class AirbyteCredentialTesterTest { @Inject private AirbyteCredentialTester tester; private MockWebServer mockWebServer; private static final TestCredential WEAK_CRED_1 = - TestCredential.create("default", Optional.of("airbyte")); + TestCredential.create("airbyte", Optional.of("password")); private static final TestCredential WRONG_CRED_1 = - TestCredential.create("wrong", Optional.of("password")); + TestCredential.create("wrong", Optional.of("wrong")); - // the default username and password value for an insecure airbyte instance - private static final String DEFAULT_USERNAME = "default"; - private static final String DEFAULT_PASSWORD = ""; + // The base64 encoding of default authentication username:password pairs which the tester will + // send these this to our mock webserver + private static final String WEAK_CRED_AUTH_1 = "basic YWlyYnl0ZTpwYXNzd29yZA=="; @Before public void setup() { @@ -70,35 +69,34 @@ public void setup() { Guice.createInjector(new HttpClientModule.Builder().build()).injectMembers(this); } - // - // @Test - // public void detect_weakCredentialsExists_returnsWeakCredentials() throws Exception { - // startMockWebServer(); - // NetworkService targetNetworkService = - // NetworkService.newBuilder() - // .setNetworkEndpoint( - // forHostnameAndPort(mockWebServer.getHostName(), mockWebServer.getPort())) - // .setServiceName("airbyte") - // .build(); - // - // assertThat(tester.testValidCredentials(targetNetworkService, ImmutableList.of(WEAK_CRED_1))) - // .containsExactly(WEAK_CRED_1); - // mockWebServer.shutdown(); - // } - // - // @Test - // public void detect_weakCredentialsExist_returnsFirstWeakCredentials() throws Exception { - // startMockWebServer(); - // NetworkService targetNetworkService = - // NetworkService.newBuilder() - // .setNetworkEndpoint( - // forHostnameAndPort(mockWebServer.getHostName(), mockWebServer.getPort())) - // .setServiceName("airbyte") - // .build(); - // - // assertThat(tester.testValidCredentials(targetNetworkService, ImmutableList.of(WEAK_CRED_1))) - // .containsExactly(WEAK_CRED_1); - // } + @Test + public void detect_weakCredentialsExists_returnsWeakCredentials() throws Exception { + startMockWebServer(); + NetworkService targetNetworkService = + NetworkService.newBuilder() + .setNetworkEndpoint( + forHostnameAndPort(mockWebServer.getHostName(), mockWebServer.getPort())) + .setServiceName("airbyte") + .build(); + + assertThat(tester.testValidCredentials(targetNetworkService, ImmutableList.of(WEAK_CRED_1))) + .containsExactly(WEAK_CRED_1); + mockWebServer.shutdown(); + } + + @Test + public void detect_weakCredentialsExist_returnsFirstWeakCredentials() throws Exception { + startMockWebServer(); + NetworkService targetNetworkService = + NetworkService.newBuilder() + .setNetworkEndpoint( + forHostnameAndPort(mockWebServer.getHostName(), mockWebServer.getPort())) + .setServiceName("airbyte") + .build(); + + assertThat(tester.testValidCredentials(targetNetworkService, ImmutableList.of(WEAK_CRED_1))) + .containsExactly(WEAK_CRED_1); + } @Test public void detect_airbyteService_canAccept() throws Exception { @@ -113,21 +111,20 @@ public void detect_airbyteService_canAccept() throws Exception { assertThat(tester.canAccept(targetNetworkService)).isTrue(); } - // @Test - // public void - // detect_weakCredentialsExistAndAirbyteInForeignLanguage_returnsFirstWeakCredentials() - // throws Exception { - // startMockWebServer(); - // NetworkService targetNetworkService = - // NetworkService.newBuilder() - // .setNetworkEndpoint( - // forHostnameAndPort(mockWebServer.getHostName(), mockWebServer.getPort())) - // .setServiceName("airbyte") - // .build(); - // - // assertThat(tester.testValidCredentials(targetNetworkService, ImmutableList.of(WEAK_CRED_1))) - // .containsExactly(WEAK_CRED_1); - // } + @Test + public void detect_weakCredentialsExistAndAirbyteInForeignLanguage_returnsFirstWeakCredentials() + throws Exception { + startMockWebServer(); + NetworkService targetNetworkService = + NetworkService.newBuilder() + .setNetworkEndpoint( + forHostnameAndPort(mockWebServer.getHostName(), mockWebServer.getPort())) + .setServiceName("airbyte") + .build(); + + assertThat(tester.testValidCredentials(targetNetworkService, ImmutableList.of(WEAK_CRED_1))) + .containsExactly(WEAK_CRED_1); + } @Test public void detect_noWeakCredentials_returnsNoCredentials() throws Exception { @@ -163,32 +160,38 @@ private void startMockWebServer() throws IOException { new MockResponse() .setResponseCode(401) .setBody( - "{\"detail\":[\"AuthorizationException\"," - + "\"Authentication error: invalid username or password\"]}"); + "content=\"Airbyte is the turnkey open-source data integration platform that " + + "syncs data from applications, APIs and databases to warehouses.\""); @Override public MockResponse dispatch(RecordedRequest request) { - if (request.getPath().matches("/login") && Objects.equals(request.getMethod(), "GET")) { - return new MockResponse() - .setResponseCode(200) - .setBody(" Airbyte Dashboard "); - } - if (request.getPath().matches("/api/v1/login") - && Objects.equals(request.getMethod(), "POST") - && request - .getBody() - .readString(StandardCharsets.UTF_8) - .contains( - String.format( - "username=%s&password=%s", DEFAULT_USERNAME, DEFAULT_PASSWORD))) { - return new MockResponse() - .setResponseCode(200) - .setBody( - "{\"access_token\":\"An AccessToken\",\"token_type\":\"bearer\"," - + "\"expires_in\":null,\"refresh_token\":null,\"scope\":null}"); - } else { + String authorizationHeader = request.getHeaders().get("Authorization"); + if (authorizationHeader == null) { return unauthorizedResponse; } + if (request.getPath().equals("/") && Objects.equals(request.getMethod(), "GET")) { + boolean isDefaultCredentials = authorizationHeader.equals(WEAK_CRED_AUTH_1); + if (isDefaultCredentials) { + return new MockResponse() + .setResponseCode(200) + .setBody( + "\n" + + " \n" + + " \n" + + " Airbyte\n" + + " \n" + + " \n" + + " \n" + + ""); + } else { + return unauthorizedResponse; + } + } + return new MockResponse().setResponseCode(404); } }; mockWebServer.setDispatcher(dispatcher); From 17d5deee2d8eb12218899521bfe72ec2e712037c Mon Sep 17 00:00:00 2001 From: secureness Date: Tue, 11 Mar 2025 03:12:11 +0400 Subject: [PATCH 3/3] missing google-java-format --- .../GenericWeakCredentialDetector.java | 4 +--- ...enericWeakCredentialDetectorBootstrapModule.java | 3 +-- .../testers/airbyte/AirbyteCredentialTester.java | 13 ++++++------- .../airbyte/AirbyteCredentialTesterTest.java | 5 +++-- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/GenericWeakCredentialDetector.java b/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/GenericWeakCredentialDetector.java index f0bf02a01..9bdb741f5 100644 --- a/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/GenericWeakCredentialDetector.java +++ b/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/GenericWeakCredentialDetector.java @@ -79,8 +79,7 @@ public final class GenericWeakCredentialDetector implements VulnDetector { private static final GoogleLogger logger = GoogleLogger.forEnclosingClass(); private static final Severity DEFAULT_SEVERITY = Severity.CRITICAL; - @VisibleForTesting - final ImmutableSet providers; + @VisibleForTesting final ImmutableSet providers; private final ImmutableSet testers; private final Clock utcClock; @@ -250,5 +249,4 @@ private static AdditionalDetail buildCredentialDetail( .setCredentials(Credentials.newBuilder().addAllCredential(credentials)) .build(); } - } diff --git a/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/GenericWeakCredentialDetectorBootstrapModule.java b/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/GenericWeakCredentialDetectorBootstrapModule.java index 772a794d4..42beab539 100644 --- a/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/GenericWeakCredentialDetectorBootstrapModule.java +++ b/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/GenericWeakCredentialDetectorBootstrapModule.java @@ -45,10 +45,9 @@ import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.testers.ncrack.NcrackCredentialTester; import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.testers.postgres.PostgresCredentialTester; import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.testers.rabbitmq.RabbitMQCredentialTester; -import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.testers.wordpress.WordpressCredentialTester; import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.testers.rstudio.RStudioCredentialTester; +import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.testers.wordpress.WordpressCredentialTester; import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.testers.zenml.ZenMlCredentialTester; - import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.Files; diff --git a/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTester.java b/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTester.java index 637e536d8..c9d52e057 100644 --- a/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTester.java +++ b/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTester.java @@ -31,17 +31,16 @@ import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.provider.TestCredential; import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.tester.CredentialTester; import com.google.tsunami.proto.NetworkService; +import java.io.IOException; +import java.util.Base64; +import java.util.List; +import javax.inject.Inject; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.select.Elements; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.util.Base64; -import java.util.List; -import javax.inject.Inject; - /** Credential tester specifically for airbyte. */ public final class AirbyteCredentialTester extends CredentialTester { private static final GoogleLogger logger = GoogleLogger.forEnclosingClass(); @@ -134,8 +133,8 @@ private static boolean bodyContainsSuccessLogin(String responseBody) { .tagName("meta") .getElementsByAttributeValue( "content", - "Airbyte is the turnkey open-source data integration " - + "platform that syncs data from applications, APIs and databases to warehouses."); + "Airbyte is the turnkey open-source data integration platform that syncs data" + + " from applications, APIs and databases to warehouses."); return !elements.isEmpty(); } return false; diff --git a/google/detectors/credentials/generic_weak_credential_detector/src/test/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTesterTest.java b/google/detectors/credentials/generic_weak_credential_detector/src/test/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTesterTest.java index 9d381828e..ee4706b9b 100644 --- a/google/detectors/credentials/generic_weak_credential_detector/src/test/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTesterTest.java +++ b/google/detectors/credentials/generic_weak_credential_detector/src/test/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/testers/airbyte/AirbyteCredentialTesterTest.java @@ -179,8 +179,9 @@ public MockResponse dispatch(RecordedRequest request) { + " \n" + " \n" + " Airbyte\n" + " \n"