Skip to content

Commit

Permalink
Merge branch 'google:master' into CVE-2023-33246
Browse files Browse the repository at this point in the history
  • Loading branch information
lokiuox authored Oct 24, 2024
2 parents 1465ca4 + c663072 commit ef9073a
Show file tree
Hide file tree
Showing 6 changed files with 389 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.testers.jenkins.JenkinsCredentialTester;
import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.testers.mlflow.MlFlowCredentialTester;
import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.testers.mysql.MysqlCredentialTester;
import com.google.tsunami.plugins.detectors.credentials.genericweakcredentialdetector.testers.hive.HiveCredentialTester;
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;
Expand Down Expand Up @@ -70,6 +71,7 @@ protected void configurePlugin() {
credentialTesterBinder.addBinding().to(JenkinsCredentialTester.class);
credentialTesterBinder.addBinding().to(MlFlowCredentialTester.class);
credentialTesterBinder.addBinding().to(MysqlCredentialTester.class);
credentialTesterBinder.addBinding().to(HiveCredentialTester.class);
credentialTesterBinder.addBinding().to(HydraCredentialTester.class);
credentialTesterBinder.addBinding().to(NcrackCredentialTester.class);
credentialTesterBinder.addBinding().to(PostgresCredentialTester.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public final class Top100Passwords extends CredentialProvider {

private static final ImmutableList<String> TOP_USER_NAMES =
ImmutableList.of(
"",
"anonymous",
"root",
"admin",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* 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.hive;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.tsunami.common.net.http.HttpRequest.get;

import com.google.common.collect.ImmutableList;
import com.google.common.flogger.GoogleLogger;
import com.google.common.net.HostAndPort;
import com.google.tsunami.common.data.NetworkEndpointUtils;
import com.google.tsunami.common.data.NetworkServiceUtils;
import com.google.tsunami.common.net.db.ConnectionProviderInterface;
import com.google.tsunami.common.net.http.HttpClient;
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 java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Optional;
import javax.inject.Inject;

/** Credential tester specifically for hive. */
public final class HiveCredentialTester extends CredentialTester {
private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
private final ConnectionProviderInterface connectionProvider;
private final HttpClient httpClient;
private static final String HIVE_TITLE = "<title>HiveServer2</title>";
private static final int HIVE_TCP_PORT = 10000;

@Inject
HiveCredentialTester(ConnectionProviderInterface connectionProvider, HttpClient httpClient) {
this.connectionProvider = checkNotNull(connectionProvider);
this.httpClient = httpClient;
}

@Override
public String name() {
return "HiveCredentialTester";
}

@Override
public String description() {
return "Hive credential tester.";
}

@Override
public boolean canAccept(NetworkService networkService) {
String targetUri = NetworkServiceUtils.buildWebApplicationRootUrl(networkService);

try {
HttpResponse response =
httpClient.send(get(targetUri).withEmptyHeaders().build(), networkService);
if (response != null) {
Optional<String> body = response.bodyString();
if (response.status().code() == HttpStatus.OK.code()
&& body.isPresent()
&& body.get().contains(HIVE_TITLE)) {
return true;
}
}
} catch (IOException e) {
return false;
}
return false;
}

@Override
public boolean batched() {
return true;
}

@Override
public ImmutableList<TestCredential> testValidCredentials(
NetworkService networkService, List<TestCredential> credentials) {
if (!canAccept(networkService)) {
return ImmutableList.of();
}

return credentials.stream()
.filter(cred -> isHiveAccessible(networkService, cred))
.collect(toImmutableList());
}

private boolean isHiveAccessible(NetworkService networkService, TestCredential credential) {
HostAndPort targetPage =
NetworkEndpointUtils.toHostAndPort(networkService.getNetworkEndpoint());
try {
String url = String.format("jdbc:hive2://%s:%d/default", targetPage.getHost(), HIVE_TCP_PORT);
logger.atInfo().log(
"url: %s, username: %s, password: %s",
url, credential.username(), credential.password().orElse(""));
Connection conn =
connectionProvider.getConnection(
url, credential.username(), credential.password().orElse(""));

if (conn != null) {
logger.atInfo().log("Connected to the Hive server successfully.");
return true;
}
} catch (SQLException e) {
logger.atSevere().log(
"HiveCredentialTester sql error: %s (%d)", e.getMessage(), e.getErrorCode());
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,5 @@ enum TargetService {
OWA = 23; // Outlook Web App (Web Application)
DICOM = 24; // Digital Imaging and Communications in Medicine (Healthcare
// Protocol)
HIVE = 25; // Apache Hive (SQL Database)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/*
* 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.hive;

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.protobuf.ByteString;
import com.google.tsunami.common.net.db.ConnectionProviderInterface;
import com.google.tsunami.common.net.http.HttpClient;
import com.google.tsunami.common.net.http.HttpHeaders;
import com.google.tsunami.common.net.http.HttpRequest;
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.proto.NetworkService;
import com.google.tsunami.proto.Software;
import java.io.IOException;
import java.sql.Connection;
import java.util.Optional;
import okhttp3.mockwebserver.Dispatcher;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import org.junit.After;
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 HiveCredentialTester}. */
@RunWith(JUnit4.class)
public class HiveCredentialTesterTest {
@Rule public MockitoRule rule = MockitoJUnit.rule();
@Mock private ConnectionProviderInterface mockConnectionProvider;
@Mock private Connection mockConnection;
@Mock private HttpClient httpClient;
private HiveCredentialTester tester;
private MockWebServer mockWebServer;

private static final TestCredential WEAK_CRED_1 =
TestCredential.create("user", Optional.of("1234"));
private static final TestCredential WEAK_CRED_2 =
TestCredential.create("root", Optional.of("pass"));

@Before
public void setup() throws IOException {
mockWebServer = new MockWebServer();
startMockWebServer();
tester = new HiveCredentialTester(mockConnectionProvider, httpClient);
}

@After
public void tearDown() throws IOException {
mockWebServer.shutdown();
}

@Test
public void detect_weakCredExists_returnsWeakCred() throws Exception {
when(mockConnectionProvider.getConnection(
"jdbc:hive2://example.com:10000/default", "user", "1234"))
.thenReturn(mockConnection);
when(httpClient.send(any(HttpRequest.class), any(NetworkService.class)))
.thenReturn(
HttpResponse.builder()
.setStatus(HttpStatus.OK)
.setBodyBytes(ByteString.copyFromUtf8("<title>HiveServer2</title>"))
.setHeaders(HttpHeaders.builder().addHeader("Content-Type", "text/html").build())
.build());
NetworkService targetNetworkService =
NetworkService.newBuilder()
.setNetworkEndpoint(forHostnameAndPort("example.com", mockWebServer.getPort()))
.setServiceName("http")
.setSoftware(Software.newBuilder().setName("hive"))
.build();

assertThat(tester.testValidCredentials(targetNetworkService, ImmutableList.of(WEAK_CRED_1)))
.containsExactly(WEAK_CRED_1);
}

@Test
public void detect_weakCredsExist_returnsAllWeakCreds() throws Exception {
when(mockConnectionProvider.getConnection(
"jdbc:hive2://example.com:10000/default", "user", "1234"))
.thenReturn(mockConnection);
when(mockConnectionProvider.getConnection(
"jdbc:hive2://example.com:10000/default", "root", "pass"))
.thenReturn(mockConnection);
when(httpClient.send(any(HttpRequest.class), any(NetworkService.class)))
.thenReturn(
HttpResponse.builder()
.setStatus(HttpStatus.OK)
.setBodyBytes(ByteString.copyFromUtf8("<title>HiveServer2</title>"))
.setHeaders(HttpHeaders.builder().addHeader("Content-Type", "text/html").build())
.build());
NetworkService targetNetworkService =
NetworkService.newBuilder()
.setNetworkEndpoint(forHostnameAndPort("example.com", mockWebServer.getPort()))
.setServiceName("http")
.setSoftware(Software.newBuilder().setName("hive"))
.build();

assertThat(
tester.testValidCredentials(
targetNetworkService, ImmutableList.of(WEAK_CRED_1, WEAK_CRED_2)))
.containsExactly(WEAK_CRED_1, WEAK_CRED_2);
}

@Test
public void detect_noWeakCred_returnsNoCred() throws Exception {
when(mockConnectionProvider.getConnection(
"jdbc:hive2://example.com:10000/default", "hardtoguess", "hardtoguess"))
.thenReturn(mockConnection);
when(httpClient.send(any(HttpRequest.class), any(NetworkService.class)))
.thenReturn(
HttpResponse.builder()
.setStatus(HttpStatus.OK)
.setBodyBytes(ByteString.copyFromUtf8("<title>HiveServer2</title>"))
.setHeaders(HttpHeaders.builder().addHeader("Content-Type", "text/html").build())
.build());
NetworkService targetNetworkService =
NetworkService.newBuilder()
.setNetworkEndpoint(forHostnameAndPort("example.com", mockWebServer.getPort()))
.setServiceName("http")
.setSoftware(Software.newBuilder().setName("hive"))
.build();

assertThat(tester.testValidCredentials(targetNetworkService, ImmutableList.of(WEAK_CRED_1)))
.isEmpty();
}

@Test
public void detect_hiveService_skips() throws Exception {
when(mockConnectionProvider.getConnection(any(), any(), any())).thenReturn(mockConnection);
NetworkService targetNetworkService =
NetworkService.newBuilder()
.setNetworkEndpoint(forHostnameAndPort("example.com", mockWebServer.getPort()))
.setServiceName("http")
.setSoftware(Software.newBuilder().setName("hive"))
.build();

assertThat(tester.testValidCredentials(targetNetworkService, ImmutableList.of())).isEmpty();
verifyNoInteractions(mockConnectionProvider);
}

private void startMockWebServer() throws IOException {
final Dispatcher dispatcher =
new Dispatcher() {
@Override
public MockResponse dispatch(RecordedRequest request) {
return new MockResponse().setResponseCode(200).setBody("<title>HiveServer2</title>");
}
};
mockWebServer.setDispatcher(dispatcher);
mockWebServer.start();
mockWebServer.url("/");
}
}
Loading

0 comments on commit ef9073a

Please sign in to comment.