diff --git a/projects/spring-security/Dockerfile b/projects/spring-security/Dockerfile index 9ca775939..ff5d2d595 100644 --- a/projects/spring-security/Dockerfile +++ b/projects/spring-security/Dockerfile @@ -24,7 +24,9 @@ COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ COPY oauth2-core/*Fuzzer.java $SRC/ COPY oauth2-client/*Fuzzer.java $SRC/ +COPY oauth2-jose/*Fuzzer.java $SRC/ COPY acl/*Fuzzer.java $SRC/ COPY *.patch $SRC/ +RUN cd spring-security && (for i in ${SRC}/*.patch; do tr -d '\015' < $i | git apply; done ) WORKDIR $SRC/spring-security \ No newline at end of file diff --git a/projects/spring-security/build.sh b/projects/spring-security/build.sh index fe99bb1a1..a2ad6f88e 100755 --- a/projects/spring-security/build.sh +++ b/projects/spring-security/build.sh @@ -19,8 +19,6 @@ export JAVA_HOME="$OUT/open-jdk-17" mkdir -p $JAVA_HOME rsync -aL --exclude=*.zip "/usr/lib/jvm/java-17-openjdk-amd64/" "$JAVA_HOME" -git apply $SRC/*.patch - CURRENT_VERSION=$(sed -nr "s/^version=(.*)/\1/p" gradle.properties) GRADLE_ARGS="-x test -x javadoc" @@ -35,6 +33,7 @@ GRADLE_ARGS="-x test -x javadoc" ./gradlew shadowJar $GRADLE_ARGS -b oauth2/oauth2-core/spring-security-oauth2-core.gradle ./gradlew shadowJar $GRADLE_ARGS -b acl/spring-security-acl.gradle ./gradlew shadowJar $GRADLE_ARGS -b oauth2/oauth2-client/spring-security-oauth2-client.gradle +./gradlew shadowJar $GRADLE_ARGS -b oauth2/oauth2-jose/spring-security-oauth2-jose.gradle # Copy all shadow jars to the $OUT folder find . -name "*-all.jar" -print0 | while read -d $'\0' file @@ -55,7 +54,7 @@ RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_di for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer --release 17 - cp $SRC/$fuzzer_basename.class $OUT/ + cp $SRC/[$fuzzer_basename]*.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/sh diff --git a/projects/spring-security/diff.patch b/projects/spring-security/diff.patch index 18b3200fe..dd5171114 100644 --- a/projects/spring-security/diff.patch +++ b/projects/spring-security/diff.patch @@ -6,6 +6,15 @@ index 0666a90..94c14cd 100644 +apply plugin: "com.github.johnrengelman.shadow" apply plugin: 'io.spring.convention.spring-module' + dependencies { +diff --git a/oauth2/oauth2-jose/spring-security-oauth2-jose.gradle b/oauth2/oauth2-jose/spring-security-oauth2-jose.gradle +index 8290b85..c177be4 100644 +--- a/oauth2/oauth2-jose/spring-security-oauth2-jose.gradle ++++ b/oauth2/oauth2-jose/spring-security-oauth2-jose.gradle +@@ -1,3 +1,4 @@ ++apply plugin: "com.github.johnrengelman.shadow" + apply plugin: 'io.spring.convention.spring-module' + dependencies { diff --git a/acl/spring-security-acl.gradle b/acl/spring-security-acl.gradle index 976d8d4..f01b423 100644 diff --git a/projects/spring-security/oauth2-jose/NimbusJwtEncoderFuzzer.java b/projects/spring-security/oauth2-jose/NimbusJwtEncoderFuzzer.java new file mode 100644 index 000000000..2d6736962 --- /dev/null +++ b/projects/spring-security/oauth2-jose/NimbusJwtEncoderFuzzer.java @@ -0,0 +1,120 @@ +// Copyright 2022 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. +// +//////////////////////////////////////////////////////////////////////////////// + +import com.code_intelligence.jazzer.api.FuzzedDataProvider; + +import org.springframework.security.oauth2.jwt.NimbusJwtEncoder; +import org.springframework.security.oauth2.jwt.JwsHeader; +import org.springframework.security.oauth2.jwt.JwtEncoderParameters; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.security.oauth2.jwt.JwtClaimsSet; +import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm; +import org.springframework.security.oauth2.jwt.JwtEncodingException; + +import com.nimbusds.jose.jwk.JWK; +import com.nimbusds.jose.jwk.KeyType; +import com.nimbusds.jose.jwk.JWKSet; +import com.nimbusds.jose.proc.SecurityContext; +import com.nimbusds.jose.jwk.source.JWKSource; +import com.nimbusds.jose.util.Base64URL; + +import java.time.temporal.ChronoUnit; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.Collections; +import java.util.LinkedHashMap; + +public class NimbusJwtEncoderFuzzer { + + + public static void fuzzerTestOneInput(FuzzedDataProvider data) { + + String keyId = data.consumeString(200); + String x5t256 = data.consumeString(300); + + List jwkList = new ArrayList<>(); + + // + MockJwk mockJwk = new NimbusJwtEncoderFuzzer.MockJwk(KeyType.RSA, keyId, x5t256); + jwkList.add(mockJwk); + + JWKSource jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(new JWKSet(jwkList)); + NimbusJwtEncoder jwtEncoder = new NimbusJwtEncoder(jwkSource); + + JwsHeader jwsHeader = JwsHeader + .with(SignatureAlgorithm.RS256) + .build(); + JwtClaimsSet jwtClaimsSet = jwtClaimsSet().build(); + + try { + Jwt encodedJws = jwtEncoder.encode(JwtEncoderParameters.from(jwsHeader, jwtClaimsSet)); + } + catch(JwtEncodingException jee) { + + } + } + + public static JwtClaimsSet.Builder jwtClaimsSet() { + String issuer = "https://provider.com"; + Instant issuedAt = Instant.now(); + Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS); + + // @formatter:off + return JwtClaimsSet.builder() + .issuer(issuer) + .subject("subject") + .audience(Collections.singletonList("client-1")) + .issuedAt(issuedAt) + .notBefore(issuedAt) + .expiresAt(expiresAt) + .id("jti") + .claim("custom-claim-name", "custom-claim-value"); + } + + private static final class MockJwk extends JWK{ + + protected MockJwk(KeyType kty, String kid, String x5t256) { + super(kty, null, null, null, kid, null, null, new Base64URL(x5t256), null, null); + //TODO Auto-generated constructor stub + } + + @Override + public LinkedHashMap getRequiredParams() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isPrivate() { + // TODO Auto-generated method stub + return false; + } + + @Override + public JWK toPublicJWK() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int size() { + // TODO Auto-generated method stub + return 0; + } + } + +} \ No newline at end of file