Skip to content

Commit

Permalink
Expand spring-security fuzzing (#8354)
Browse files Browse the repository at this point in the history
* Expand spring-security fuzzing

* remove comment from debugging that is now misleading the reader (#20)
  • Loading branch information
CheeseHunter117 committed Aug 25, 2022
1 parent 655774f commit 8ad0622
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 5 deletions.
28 changes: 28 additions & 0 deletions projects/spring-security/EncodingUtilsConcatenateFuzzer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import com.code_intelligence.jazzer.api.FuzzedDataProvider;

import org.springframework.security.crypto.util.EncodingUtils;

public class EncodingUtilsConcatenateFuzzer {
public static void fuzzerTestOneInput(FuzzedDataProvider data) {
final byte[][] arrayOfByteArrays = getArrayOfByteArrays(data);

EncodingUtils.concatenate(arrayOfByteArrays);
}

// Constants to reduce cases of fuzzer running out of memory
private final static int MIN_OUTER_LENGTH = 500;
private final static int MAX_OUTER_LENGTH = 1000;
private final static int MIN_INNER_LENGTH = 320;
private final static int MAX_INNER_LENGTH = 700;

private static byte[][] getArrayOfByteArrays(FuzzedDataProvider data) {
final int numberOfArrays = data.consumeInt(MIN_OUTER_LENGTH, MAX_OUTER_LENGTH);
byte[][] arrayOfArrays = new byte[numberOfArrays][];

for (int i=0; i<numberOfArrays; i++) {
arrayOfArrays[i] = data.consumeBytes(data.consumeInt(MIN_INNER_LENGTH, MAX_INNER_LENGTH));
}

return arrayOfArrays;
}
}
22 changes: 22 additions & 0 deletions projects/spring-security/HexFuzzer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow;

import java.lang.CharSequence;

import org.springframework.security.crypto.codec.Hex;

public class HexFuzzer {
public static void fuzzerTestOneInput(byte[] data) {
final byte[] initialByteArray = data;
final char[] encodedChars;

try {
encodedChars = Hex.encode(initialByteArray);

if (! initialByteArray.toString().equals(Hex.decode(encodedChars.toString()))) {
throw new FuzzerSecurityIssueLow("Hex value has changed during encoding and decoding");
}
} catch (IllegalArgumentException err) {
// ignore expected exceptions
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow;
import com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh;

import java.util.List;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

public class InMemoryUserDetailsManagerChangePasswordFuzzer {
private final static String USERNAME = "admin";
private final static String PASSWORD = "secret";
private final static String USER_ROLE = "ADMIN";
private static final List<GrantedAuthority> AUTHORITIES = AuthorityUtils.createAuthorityList(USER_ROLE);

private final static int LENGTH_PASSWORD = 500;

public static void fuzzerTestOneInput(FuzzedDataProvider data) {
// generating needed objects
final String generatedPassword01 = data.consumeString(LENGTH_PASSWORD);
final String generatedPassword02 = data.consumeRemainingAsString();

// check if the fuzzer generated useful data
if (generatedPassword01.equals(PASSWORD) || generatedPassword02.equals(PASSWORD)) {
return;
}

// create all the objects needed for fuzzing the InMemoryUserDetailsManager
final User user = new User(USERNAME, PASSWORD, AUTHORITIES);
final InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager(user);

// set the SecurityContext
// this makes it so that InMemoryUserDetailsManager.changePassword(old, new) never actually checks the old password
SecurityContextHolder.getContext().setAuthentication(
UsernamePasswordAuthenticationToken.authenticated(USERNAME, PASSWORD, AUTHORITIES));

try {
userDetailsManager.changePassword(generatedPassword01, generatedPassword02);

// check if the password was successfully changed
final String finalPassword = userDetailsManager.loadUserByUsername(USERNAME).getPassword();
if (PASSWORD.equals(finalPassword)) {
throw new FuzzerSecurityIssueHigh("Password was not changed to '" + finalPassword + "'");
}
} catch (UsernameNotFoundException err) {
throw new FuzzerSecurityIssueLow("The user disappeared from the InMemoryUserDetailsManager");
} catch (AccessDeniedException problem) {
// should not be thrown anymore
problem.printStackTrace();
throw problem;
}
}

public static void fuzzerTearDown() {
SecurityContextHolder.clearContext();
}
}
23 changes: 23 additions & 0 deletions projects/spring-security/Utf8Fuzzer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow;

import java.lang.CharSequence;

import org.springframework.security.crypto.codec.Utf8;

public class Utf8Fuzzer {
public static void fuzzerTestOneInput(FuzzedDataProvider data) {
final String initialString = data.consumeString(Integer.MAX_VALUE);
final byte[] encodedBytes;

try {
encodedBytes = Utf8.encode(initialString);

if (! initialString.equals(Utf8.decode(encodedBytes))) {
throw new FuzzerSecurityIssueLow("Utf8 value has changed during encoding and decoding");
}
} catch (IllegalArgumentException err) {
// ignore expected exceptions
}
}
}
8 changes: 4 additions & 4 deletions projects/spring-security/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ index c4f6c08..413b992 100644
+
apply plugin: 'io.spring.convention.spring-module'
+apply plugin: 'com.github.johnrengelman.shadow'
dependencies {
management platform(project(":spring-security-dependencies"))
@@ -10,7 +15,7 @@ dependencies {
optional 'com.fasterxml.jackson.core:jackson-databind'
optional 'ldapsdk:ldapsdk'
- optional "com.unboundid:unboundid-ldapsdk"
Expand All @@ -60,7 +60,7 @@ cp "config/build/libs/spring-security-config-$CURRENT_VERSION-test.jar" "$OUT/sp

ALL_JARS="spring-security-ldap.jar spring-security-core.jar spring-security.jar spring-security-config.jar spring-security-config-test.jar"

# The classpath at build-time includes the project jars in $OUT as well as the
# The class path at build-time includes the project jars in $OUT as well as the
# Jazzer API.
BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH

Expand All @@ -85,4 +85,4 @@ LD_LIBRARY_PATH=\"\$this_dir/open-jdk-17/lib/server\":\$this_dir \
--jvm_args=\"-Xmx2048m\" \
\$@" > $OUT/$fuzzer_basename
chmod u+x $OUT/$fuzzer_basename
done
done
3 changes: 2 additions & 1 deletion projects/spring-security/project.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ vendor_ccs:
- "yakdan@code-intelligence.com"
- "glendowne@code-intelligence.com"
- "patrice.salathe@code-intelligence.com"
- "hlin@code-intelligence.com"
- "hlin@code-intelligence.com"
- "yoshi.weber@gmail.com"

0 comments on commit 8ad0622

Please sign in to comment.