Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/arguments-and-configuration-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ Some parameters only have an effect when used with standalone Jazzer binary (mar
- In regression mode, controls which folders are used for coverage computation.
- `false` (default): Use only thej crash file folder.
- `true`: Use both the crash file folder and the corpus folder.
- **JAZZER_SSRF_PERMISSIVE_UNTIL_CONFIGURED** [bool, default=""] (*environment variable only*)
- When set to a truthy value, the ServerSideRequestForgery sanitizer will allow all outgoing requests until it is explicitly configured with allowed hosts in the fuzz test.
This is useful to avoid false positives in multithreaded applications that make network requests during initialization.

- **keep_going** [uint64, default="1"]
- Number of distinct findings after which the fuzzer should stop.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@ public class ServerSideRequestForgery {
public static final AtomicReference<BiPredicate<String, Integer>> connectionPermitted =
new AtomicReference<>((host, port) -> true);

// Disallow all connections right before the first fuzz target is executed.
static {
Jazzer.onFuzzTargetReady(() -> connectionPermitted.set((host, port) -> false));
// Disallow all connections right before the first fuzz target is executed, if the user has not
// specifically opted into permissive behavior.
// In multithreaded fuzzing scenarios, a network request can be made after the fuzzing has
// started but before a user had a chance to call BugDetectors.allowNetworkConnections().
if (System.getenv("JAZZER_SSRF_PERMISSIVE_UNTIL_CONFIGURED") == null) {
Jazzer.onFuzzTargetReady(() -> connectionPermitted.set((host, port) -> false));
}
}

/**
Expand Down Expand Up @@ -132,7 +137,10 @@ private static void checkSsrf(Object[] arguments) {
+ "If the fuzz test is expected to perform network connections, call"
+ " com.code_intelligence.jazzer.api.BugDetectors#allowNetworkConnections at"
+ " the beginning of your fuzz test and optionally provide a predicate"
+ " matching the expected hosts.",
+ " matching the expected hosts.\n\n"
+ "In multithreaded fuzzing scenarios consider using the environment variable"
+ " JAZZER_SSRF_PERMISSIVE_UNTIL_CONFIGURED to allow all connections until"
+ " the fuzz test has been configured to allow specific connections.",
host, port)));
}
}
Expand Down
17 changes: 17 additions & 0 deletions sanitizers/src/test/java/com/example/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,23 @@ java_fuzz_target_test(
verify_crash_reproducer = False,
)

java_fuzz_target_test(
name = "SsrfAllowUntilConfigured",
srcs = [
"SsrfAllowUntilConfigured.java",
],
env = {
"JAZZER_SSRF_PERMISSIVE_UNTIL_CONFIGURED": "1",
},
fuzzer_args = [
"-runs=1",
"-print_final_stats=1",
],
# tags = ["dangerous"],
target_class = "com.example.SsrfAllowUntilConfigured",
verify_crash_reproducer = False,
)

java_fuzz_target_test(
name = "ScriptEngineInjection",
srcs = [
Expand Down
58 changes: 58 additions & 0 deletions sanitizers/src/test/java/com/example/SsrfAllowUntilConfigured.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright 2024 Code Intelligence GmbH
*
* 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.example;

import com.code_intelligence.jazzer.api.BugDetectors;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.CountDownLatch;

public class SsrfAllowUntilConfigured {

private static final CountDownLatch fuzzTestStarted = new CountDownLatch(1);

static {
// Simulate a background thread that starts before fuzz test configuration
Thread backgroundThread =
new Thread(
() -> {
try {
// Wait for fuzz test to start but before it configures SSRF
fuzzTestStarted.await();
System.out.println("Background thread making early request...");

URL url = new URL("https://localhost:8080");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(1000);
conn.setReadTimeout(1000);
conn.getResponseCode();
conn.disconnect();
} catch (Exception ignored) {
}
});
backgroundThread.setDaemon(true);
backgroundThread.start();
}

public static void fuzzerTestOneInput(boolean ignored) throws Exception {
fuzzTestStarted.countDown();
Thread.sleep(500); // Ensure background thread has time to run

BugDetectors.allowNetworkConnections((host, port) -> host.equals("localhost"));
}
}