• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 Code Intelligence GmbH
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 
17 package com.code_intelligence.jazzer.api;
18 
19 import java.util.concurrent.atomic.AtomicReference;
20 import java.util.function.BiPredicate;
21 
22 /**
23  * Provides static functions that configure the behavior of bug detectors provided by Jazzer.
24  */
25 public final class BugDetectors {
26   private static final AtomicReference<BiPredicate<String, Integer>> currentPolicy =
27       getConnectionPermittedReference();
28 
29   /**
30    * Allows all network connections.
31    *
32    * <p>See {@link #allowNetworkConnections(BiPredicate)} for an alternative that provides
33    * fine-grained control over which network connections are expected.
34    *
35    * <p>By default, all attempted network connections are considered unexpected and result in a
36    * finding being reported.
37    *
38    * <p>By wrapping the call into a try-with-resources statement, network connection permissions
39    * can be configured to apply to individual parts of the fuzz test only:
40    *
41    * <pre>{@code
42    *   Image image = parseImage(bytes);
43    *   Response response;
44    *   try (SilentCloseable unused = BugDetectors.allowNetworkConnections()) {
45    *     response = uploadImage(image);
46    *   }
47    *   handleResponse(response);
48    * }</pre>
49    *
50    * @return a {@link SilentCloseable} that restores the previously set permissions when closed
51    */
allowNetworkConnections()52   public static SilentCloseable allowNetworkConnections() {
53     return allowNetworkConnections((host, port) -> true);
54   }
55 
56   /**
57    * Allows all network connections for which the provided predicate returns {@code true}.
58    *
59    * <p>By default, all attempted network connections are considered unexpected and result in a
60    * finding being reported.
61    *
62    * <p>By wrapping the call into a try-with-resources statement, network connection permissions
63    * can be configured to apply to individual parts of the fuzz test only:
64    *
65    * <pre>{@code
66    *   Image image = parseImage(bytes);
67    *   Response response;
68    *   try (SilentCloseable unused = BugDetectors.allowNetworkConnections(
69    *       (host, port) -> host.equals("example.org"))) {
70    *     response = uploadImage(image, "example.org");
71    *   }
72    *   handleResponse(response);
73    * }</pre>
74    *
75    * @param connectionPermitted a predicate that evaluate to {@code true} if network connections to
76    *                            the provided combination of host and port are permitted
77    * @return a {@link SilentCloseable} that restores the previously set predicate when closed
78    */
allowNetworkConnections( BiPredicate<String, Integer> connectionPermitted)79   public static SilentCloseable allowNetworkConnections(
80       BiPredicate<String, Integer> connectionPermitted) {
81     if (connectionPermitted == null) {
82       throw new IllegalArgumentException("connectionPermitted must not be null");
83     }
84     if (currentPolicy == null) {
85       throw new IllegalStateException("Failed to set network connection policy");
86     }
87     BiPredicate<String, Integer> previousPolicy = currentPolicy.getAndSet(connectionPermitted);
88     return () -> {
89       if (!currentPolicy.compareAndSet(connectionPermitted, previousPolicy)) {
90         throw new IllegalStateException(
91             "Failed to reset network connection policy - using try-with-resources is highly recommended");
92       }
93     };
94   }
95 
96   private static AtomicReference<BiPredicate<String, Integer>> getConnectionPermittedReference() {
97     try {
98       Class<?> ssrfSanitizer =
99           Class.forName("com.code_intelligence.jazzer.sanitizers.ServerSideRequestForgery");
100       return (AtomicReference<BiPredicate<String, Integer>>) ssrfSanitizer
101           .getField("connectionPermitted")
102           .get(null);
103     } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
104       System.err.println("WARNING: ");
105       e.printStackTrace();
106       return null;
107     }
108   }
109 
110   private BugDetectors() {}
111 }
112