🤬
  • ■ ■ ■ ■ ■ ■
    common/src/main/java/com/google/tsunami/common/net/FuzzingUtils.java
     1 +/*
     2 + * Copyright 2022 Google LLC
     3 + *
     4 + * Licensed under the Apache License, Version 2.0 (the "License");
     5 + * you may not use this file except in compliance with the License.
     6 + * You may obtain a copy of the License at
     7 + *
     8 + * http://www.apache.org/licenses/LICENSE-2.0
     9 + *
     10 + * Unless required by applicable law or agreed to in writing, software
     11 + * distributed under the License is distributed on an "AS IS" BASIS,
     12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 + * See the License for the specific language governing permissions and
     14 + * limitations under the License.
     15 + */
     16 +package com.google.tsunami.common.net;
     17 + 
     18 +import static com.google.common.base.Strings.isNullOrEmpty;
     19 +import static com.google.common.collect.ImmutableList.toImmutableList;
     20 +import static java.util.stream.Collectors.joining;
     21 + 
     22 +import com.google.auto.value.AutoValue;
     23 +import com.google.common.base.Splitter;
     24 +import com.google.common.collect.ImmutableList;
     25 +import com.google.common.collect.ImmutableSet;
     26 +import com.google.tsunami.common.net.http.HttpRequest;
     27 +import java.net.URI;
     28 +import java.util.ArrayList;
     29 +import java.util.List;
     30 +import java.util.Optional;
     31 + 
     32 +/** Fuzzing utilities for HTTP request properties. */
     33 +public final class FuzzingUtils {
     34 + /* TODO(b/251480660): Refactor to generic fuzzing library. */
     35 + 
     36 + /**
     37 + * Fuzz GET parameters by replacing values with the provided payload. If no GET parameter is
     38 + * found, add a new parameter called {@code defaultParameter}.
     39 + */
     40 + public static ImmutableList<HttpRequest> fuzzGetParametersWithDefaultParameter(
     41 + HttpRequest request, String payload, String defaultParameter) {
     42 + return fuzzGetParameters(request, payload, Optional.of(defaultParameter));
     43 + }
     44 + 
     45 + /**
     46 + * Fuzz GET parameters by replacing values with the provided payload. If no GET parameter is
     47 + * found, return an empty list.
     48 + */
     49 + public static ImmutableList<HttpRequest> fuzzGetParameters(HttpRequest request, String payload) {
     50 + return fuzzGetParameters(request, payload, Optional.empty());
     51 + }
     52 + 
     53 + private static ImmutableList<HttpRequest> fuzzGetParameters(
     54 + HttpRequest request, String payload, Optional<String> defaultParameter) {
     55 + URI parsedUrl = URI.create(request.url());
     56 + ImmutableList<HttpQueryParams> queryParams = parseQuery(parsedUrl.getQuery());
     57 + if (queryParams.isEmpty() && defaultParameter.isPresent()) {
     58 + return ImmutableList.of(
     59 + request.toBuilder()
     60 + .setUrl(
     61 + assembleUrlWithQueries(
     62 + parsedUrl,
     63 + ImmutableList.of(HttpQueryParams.create(defaultParameter.get(), payload))))
     64 + .build());
     65 + }
     66 + return fuzzParams(queryParams, payload).stream()
     67 + .map(fuzzedParams -> assembleUrlWithQueries(parsedUrl, fuzzedParams))
     68 + .map(fuzzedUrl -> request.toBuilder().setUrl(fuzzedUrl).build())
     69 + .collect(toImmutableList());
     70 + }
     71 + 
     72 + private static ImmutableSet<ImmutableList<HttpQueryParams>> fuzzParams(
     73 + ImmutableList<HttpQueryParams> params, String payload) {
     74 + ImmutableSet.Builder<ImmutableList<HttpQueryParams>> fuzzedParamsbuilder =
     75 + ImmutableSet.builder();
     76 + 
     77 + for (int i = 0; i < params.size(); i++) {
     78 + List<HttpQueryParams> paramsWithPayload = new ArrayList<>(params);
     79 + paramsWithPayload.set(i, HttpQueryParams.create(params.get(i).name(), payload));
     80 + fuzzedParamsbuilder.add(ImmutableList.copyOf(paramsWithPayload));
     81 + }
     82 + 
     83 + return fuzzedParamsbuilder.build();
     84 + }
     85 + 
     86 + private static ImmutableList<HttpQueryParams> parseQuery(String query) {
     87 + if (isNullOrEmpty(query)) {
     88 + return ImmutableList.of();
     89 + }
     90 + ImmutableList.Builder<HttpQueryParams> queryParamsBuilder = ImmutableList.builder();
     91 + for (String param : Splitter.on('&').split(query)) {
     92 + int equalPosition = param.indexOf("=");
     93 + if (equalPosition > -1) {
     94 + String name = param.substring(0, equalPosition);
     95 + String value = param.substring(equalPosition + 1);
     96 + queryParamsBuilder.add(HttpQueryParams.create(name, value));
     97 + } else {
     98 + queryParamsBuilder.add(HttpQueryParams.create(param, ""));
     99 + }
     100 + }
     101 + return queryParamsBuilder.build();
     102 + }
     103 + 
     104 + private static String assembleUrlWithQueries(
     105 + URI parsedUrl, ImmutableList<HttpQueryParams> params) {
     106 + String query = assembleQueryParams(params);
     107 + StringBuilder urlBuilder = new StringBuilder();
     108 + urlBuilder.append(parsedUrl.getScheme()).append("://").append(parsedUrl.getRawAuthority());
     109 + if (!isNullOrEmpty(parsedUrl.getRawPath())) {
     110 + urlBuilder.append(parsedUrl.getRawPath());
     111 + }
     112 + if (!isNullOrEmpty(query)) {
     113 + urlBuilder.append('?').append(query);
     114 + }
     115 + if (!isNullOrEmpty(parsedUrl.getRawFragment())) {
     116 + urlBuilder.append('#').append(parsedUrl.getRawFragment());
     117 + }
     118 + return urlBuilder.toString();
     119 + }
     120 + 
     121 + private static String assembleQueryParams(ImmutableList<HttpQueryParams> params) {
     122 + return params.stream()
     123 + .map(param -> String.format("%s=%s", param.name(), param.value()))
     124 + .collect(joining("&"));
     125 + }
     126 + 
     127 + @AutoValue
     128 + abstract static class HttpQueryParams {
     129 + abstract String name();
     130 + 
     131 + abstract String value();
     132 + 
     133 + public static HttpQueryParams create(String name, String value) {
     134 + return new AutoValue_FuzzingUtils_HttpQueryParams(name, value);
     135 + }
     136 + }
     137 + 
     138 + private FuzzingUtils() {}
     139 +}
     140 + 
  • ■ ■ ■ ■ ■ ■
    common/src/test/java/com/google/tsunami/common/net/FuzzingUtilsTest.java
     1 +/*
     2 + * Copyright 2022 Google LLC
     3 + *
     4 + * Licensed under the Apache License, Version 2.0 (the "License");
     5 + * you may not use this file except in compliance with the License.
     6 + * You may obtain a copy of the License at
     7 + *
     8 + * http://www.apache.org/licenses/LICENSE-2.0
     9 + *
     10 + * Unless required by applicable law or agreed to in writing, software
     11 + * distributed under the License is distributed on an "AS IS" BASIS,
     12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 + * See the License for the specific language governing permissions and
     14 + * limitations under the License.
     15 + */
     16 +package com.google.tsunami.common.net;
     17 + 
     18 +import static com.google.common.truth.Truth.assertThat;
     19 + 
     20 +import com.google.common.collect.ImmutableList;
     21 +import com.google.tsunami.common.net.http.HttpRequest;
     22 +import org.junit.Test;
     23 +import org.junit.runner.RunWith;
     24 +import org.junit.runners.JUnit4;
     25 + 
     26 +@RunWith(JUnit4.class)
     27 +public final class FuzzingUtilsTest {
     28 + private static final HttpRequest REQUEST_WITHOUT_GET_PARAMETERS =
     29 + HttpRequest.get("https://google.com").withEmptyHeaders().build();
     30 + private static final HttpRequest REQUEST_WITH_GET_PARAMETERS =
     31 + HttpRequest.get("https://google.com?key=value&other=test").withEmptyHeaders().build();
     32 + 
     33 + @Test
     34 + public void fuzzGetParametersWithDefaultParameter_whenNoGetParameters_addsDefaultParameter() {
     35 + HttpRequest requestWithDefaultParameter =
     36 + HttpRequest.get("https://google.com?default=<payload>").withEmptyHeaders().build();
     37 + 
     38 + assertThat(
     39 + FuzzingUtils.fuzzGetParametersWithDefaultParameter(
     40 + REQUEST_WITHOUT_GET_PARAMETERS, "<payload>", "default"))
     41 + .contains(requestWithDefaultParameter);
     42 + }
     43 + 
     44 + @Test
     45 + public void fuzzGetParametersWithDefaultParameter_whenGetParameters_doesNotAddDefaultParameter() {
     46 + HttpRequest requestWithDefaultParameter =
     47 + HttpRequest.get("https://google.com?default=<payload>").withEmptyHeaders().build();
     48 + 
     49 + assertThat(
     50 + FuzzingUtils.fuzzGetParametersWithDefaultParameter(
     51 + REQUEST_WITH_GET_PARAMETERS, "<payload>", "default"))
     52 + .doesNotContain(requestWithDefaultParameter);
     53 + }
     54 + 
     55 + @Test
     56 + public void fuzzGetParametersWithDefaultParameter_whenGetParameters_fuzzesAllParameters() {
     57 + ImmutableList<HttpRequest> requestsWithFuzzedGetParameters =
     58 + ImmutableList.of(
     59 + HttpRequest.get("https://google.com?key=<payload>&other=test")
     60 + .withEmptyHeaders()
     61 + .build(),
     62 + HttpRequest.get("https://google.com?key=value&other=<payload>")
     63 + .withEmptyHeaders()
     64 + .build());
     65 + 
     66 + assertThat(
     67 + FuzzingUtils.fuzzGetParametersWithDefaultParameter(
     68 + REQUEST_WITH_GET_PARAMETERS, "<payload>", "default"))
     69 + .containsAtLeastElementsIn(requestsWithFuzzedGetParameters);
     70 + }
     71 + 
     72 + @Test
     73 + public void fuzzGetParameters_whenNoGetParameters_returnsEmptyList() {
     74 + assertThat(FuzzingUtils.fuzzGetParameters(REQUEST_WITHOUT_GET_PARAMETERS, "<payload>"))
     75 + .isEmpty();
     76 + }
     77 + 
     78 + @Test
     79 + public void fuzzGetParameters_whenGetParameters_fuzzesAllParameters() {
     80 + ImmutableList<HttpRequest> requestsWithFuzzedGetParameters =
     81 + ImmutableList.of(
     82 + HttpRequest.get("https://google.com?key=<payload>&other=test")
     83 + .withEmptyHeaders()
     84 + .build(),
     85 + HttpRequest.get("https://google.com?key=value&other=<payload>")
     86 + .withEmptyHeaders()
     87 + .build());
     88 + 
     89 + assertThat(FuzzingUtils.fuzzGetParameters(REQUEST_WITH_GET_PARAMETERS, "<payload>"))
     90 + .containsAtLeastElementsIn(requestsWithFuzzedGetParameters);
     91 + }
     92 +}
     93 + 
Please wait...
Page is in error, reload to recover