Skip to content

Commit acdf807

Browse files
committed
Initial commit
1 parent 1ad2ced commit acdf807

File tree

10 files changed

+947
-0
lines changed

10 files changed

+947
-0
lines changed

.gitignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# https://github.com/github/gitignore/blob/main/Maven.gitignore
2+
target/
3+
pom.xml.tag
4+
pom.xml.releaseBackup
5+
pom.xml.versionsBackup
6+
pom.xml.next
7+
release.properties
8+
dependency-reduced-pom.xml
9+
buildNumber.properties
10+
.mvn/timing.properties
11+
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
12+
.mvn/wrapper/maven-wrapper.jar
13+
14+
# Eclipse m2e generated files
15+
# Eclipse Core
16+
.project
17+
# JDT-specific (Eclipse Java Development Tools)
18+
.classpath

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Dockerfile.openjdk

Dockerfile.openjdk

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Author: Sean Pesce
2+
3+
ARG JAVA_VERSION=17
4+
FROM openjdk:${JAVA_VERSION}-jdk-alpine
5+
6+
# Install Maven
7+
RUN apk add --no-cache maven # Alpine
8+
# RUN apt-get update && apt-get install -y maven # Debian
9+
# RUN yum install maven # Fedora
10+
# RUN dnf install -y maven # Oracle Linux
11+
12+
WORKDIR /
13+
14+
# Copy project files to the container
15+
COPY . .
16+
17+
# Build web app with Maven
18+
RUN mvn clean package
19+
20+
# Environment variable to indicate whether the server is running on Oracle Java or OpenJDK
21+
ENV JAVA_TYPE=OpenJDK
22+
23+
# TCP port that the vulnerable web app will listen on
24+
ENV PORT=9999
25+
26+
CMD java -jar target/spring-cve-2024-22243-0.1.0.jar ${PORT}

Dockerfile.oracle

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Edited by Sean Pesce from original source:
2+
# https://github.com/oracle/docker-images/blob/4c60fd894234f6252f44b65ed6556b63523224d7/OracleJava/17/Dockerfile
3+
4+
# Copyright (c) 2020, 2022 Oracle and/or its affiliates.
5+
#
6+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
7+
#
8+
# ORACLE DOCKERFILES PROJECT
9+
# --------------------------
10+
# This is the Dockerfile for Oracle JDK 17 on Oracle Linux 8
11+
#
12+
# REQUIRED FILES TO BUILD THIS IMAGE
13+
# ----------------------------------
14+
# This dockerfile will download a copy of JDK 17 from
15+
# https://download.oracle.com/java/17/latest/jdk-17_linux-<ARCH>_bin.tar.gz
16+
#
17+
# It will use either x64 or aarch64 depending on the target platform
18+
#
19+
# HOW TO BUILD THIS IMAGE
20+
# -----------------------
21+
# Run:
22+
# $ docker build -t oracle/jdk:17 .
23+
#
24+
# This command is already scripted in build.sh so you can alternatively run
25+
# $ bash build.sh
26+
#
27+
# The builder image will be used to uncompress the tar.gz file with the Java Runtime.
28+
29+
FROM oraclelinux:8 as builder
30+
31+
LABEL maintainer="Aurelio Garcia-Ribeyro <[email protected]>"
32+
33+
# Since the files are compressed as tar.gz first dnf install tar. gzip is already in oraclelinux:8
34+
RUN dnf install -y tar
35+
36+
# Default to UTF-8 file.encoding
37+
ENV LANG en_US.UTF-8
38+
39+
# Environment variables for the builder image.
40+
# Required to validate that you are using the correct file
41+
ENV JAVA_URL=https://download.oracle.com/java/17/latest \
42+
JAVA_HOME=/usr/java/jdk-17
43+
# (Host name parsing mismatch between Spring and java.net.URI for Oracle Java versions 11-20)
44+
45+
##
46+
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
47+
RUN set -eux; \
48+
ARCH="$(uname -m)" && \
49+
# Java uses just x64 in the name of the tarball
50+
if [ "$ARCH" = "x86_64" ]; \
51+
then ARCH="x64"; \
52+
fi && \
53+
JAVA_PKG="$JAVA_URL"/jdk-17_linux-"${ARCH}"_bin.tar.gz ; \
54+
JAVA_SHA256="$(curl "$JAVA_PKG".sha256)" ; \
55+
curl --output /tmp/jdk.tgz "$JAVA_PKG" && \
56+
echo "$JAVA_SHA256" */tmp/jdk.tgz | sha256sum -c; \
57+
mkdir -p "$JAVA_HOME"; \
58+
tar --extract --file /tmp/jdk.tgz --directory "$JAVA_HOME" --strip-components 1
59+
60+
## Get a fresh version of OL8 for the final image
61+
FROM oraclelinux:8
62+
63+
# Default to UTF-8 file.encoding
64+
ENV LANG en_US.UTF-8
65+
ENV JAVA_HOME=/usr/java/jdk-17
66+
ENV PATH $JAVA_HOME/bin:$PATH
67+
68+
# Environment variable to indicate whether the server is running on Oracle Java or OpenJDK
69+
ENV JAVA_TYPE=Oracle
70+
71+
# If you need the Java Version you can read it from the release file with
72+
# JAVA_VERSION=$(sed -n '/^JAVA_VERSION="/{s///;s/"//;p;}' "$JAVA_HOME"/release);
73+
74+
# Copy the uncompressed Java Runtime from the builder image
75+
COPY --from=builder $JAVA_HOME $JAVA_HOME
76+
77+
WORKDIR /
78+
79+
# Copy project files to the container
80+
COPY . .
81+
82+
RUN set -eux; \
83+
# Ensure we get the latest OL 8 updates available at build time
84+
dnf -y update; \
85+
# JDK assumes freetype is available
86+
dnf install -y \
87+
freetype fontconfig \
88+
; \
89+
rm -rf /var/cache/dnf; \
90+
ln -sfT "$JAVA_HOME" /usr/java/default; \
91+
ln -sfT "$JAVA_HOME" /usr/java/latest; \
92+
for bin in "$JAVA_HOME/bin/"*; do \
93+
base="$(basename "$bin")"; \
94+
[ ! -e "/usr/bin/$base" ]; \
95+
alternatives --install "/usr/bin/$base" "$base" "$bin" 20000; \
96+
done;
97+
98+
99+
RUN set -eux; dnf install -y maven
100+
101+
# Build web app with Maven
102+
RUN mvn clean package
103+
104+
# TCP port that the vulnerable web app will listen on
105+
ENV PORT=9999
106+
107+
CMD java -jar target/spring-cve-2024-22243-0.1.0.jar ${PORT}

README.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# CVE-2024-22243
2+
3+
**Author: Sean Pesce**
4+
5+
This project contains an example web application that demonstrates exploitable scenarios for
6+
[CVE-2024-22243](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-22243),
7+
a URL-parsing vulnerability in the Java [Spring Framework](https://spring.io/)
8+
(official disclosure [here](https://spring.io/security/cve-2024-22243)).
9+
10+
11+
# Vulnerability
12+
13+
Affected versions of Spring parse the
14+
["userinfo" segment](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax) of URLs in a
15+
unique way, potentially resulting in the extraction of a host name segment that differs from many
16+
other common libraries.
17+
18+
The abnormal behavior is due to the following regular expression ("regex") in the
19+
[`UriComponentsBuilder`](https://github.com/spring-projects/spring-framework/blob/2e07f9ab33d882876f46912fcea08030b2593d49/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java#L79)
20+
class (introduced by
21+
[this commit](https://github.com/spring-projects/spring-framework/commit/a4484bb767805ec9397302f1738d33123fb35dfb)
22+
in 2014):
23+
24+
```java
25+
private static final String USERINFO_PATTERN = "([^@\\[/?#]*)";
26+
```
27+
28+
This regex does not permit the "left bracket" character (`[`) in the user info segment. However,
29+
Spring appears to be an outlier with this behavior, so calling `getHost()` on a
30+
[`UriComponents`](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/util/UriComponents.html)
31+
object constructed using [`UriComponentsBuilder.fromUriString`](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/util/UriComponentsBuilder.html#fromUriString%28java.lang.String%29)
32+
or
33+
[`UriComponentsBuilder.fromHttpUrl`](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/util/UriComponentsBuilder.html#fromHttpUrl%28java.lang.String%29)
34+
can result in unexpected behavior. The
35+
[`RestTemplate`](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html)
36+
and [`WebClient`](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/reactive/function/client/WebClient.html)
37+
classes are also affected due to their internal use of `UriComponentsBuilder`; therefore,
38+
implementations can be rendered vulnerable even without direct use of `UriComponentsBuilder`.
39+
40+
For specially-crafted inputs, Spring will return a host name value that differs from all of the
41+
following:
42+
43+
* Modern web browsers, including:
44+
* Chrome (and other Chromium-based browsers)
45+
* Firefox
46+
* Safari
47+
* [`java.net.URI`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/net/URI.html) (reportedly only for specific Java versions; other versions raise a `URISyntaxException`)
48+
* [`java.net.URL`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/net/URL.html)
49+
* `curl`
50+
* [`android.net.Uri`](https://developer.android.com/reference/android/net/Uri)
51+
* [`okhttp3.HttpUrl`](https://square.github.io/okhttp/3.x/okhttp/okhttp3/HttpUrl.html)
52+
* (Python 3) [`urllib.parse.urlparse`](https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlparse)
53+
54+
(Note that this list is non-exhaustive.)
55+
56+
This behavior potentially renders Spring-based web applications vulnerable to
57+
[open redirect](https://cwe.mitre.org/data/definitions/601.html) and
58+
[server-side request forgery (SSRF)](https://cwe.mitre.org/data/definitions/918.html) if the
59+
dependent implementation uses trusted host names for authorization or other security-relevant
60+
mechanisms.
61+
62+
## Examples
63+
64+
The example web application contains two vulnerable endpoints.
65+
66+
The first endpoint, `/redirect`, shows how Spring's abnormal URL parsing can result in an open
67+
redirect. It can be exploited using a URL such as the following:
68+
69+
```
70+
https://127.0.0.1[@evil.com
71+
```
72+
73+
The second endpoint, `/health-check`, demonstrates how a mismatch in URL parsing between Spring and
74+
the Java standard library `URL` class can result in server-side request forgery (SSRF). It can be
75+
exploited using a URL such as the following:
76+
77+
```
78+
https://evil.com[@127.0.0.1
79+
```
80+
81+
82+
## Usage
83+
84+
To build this project with Maven, simply run the following command (tested with OpenJDK 17):
85+
86+
```
87+
mvn clean package
88+
```
89+
90+
Then, start the web app with a command such as the following:
91+
92+
```
93+
java -jar seanpesce-cve-2024-22243.jar 9999
94+
```
95+
96+
The web app will be accessible at `http://127.0.0.1:9999/`.
97+
98+
99+
## Docker
100+
101+
To build the docker image, run the following command:
102+
103+
```
104+
docker build -t seanpesce-cve-2024-22243:latest .
105+
```
106+
107+
Then, start the web app with a command such as the following:
108+
109+
```
110+
docker run -i -e PORT=9999 -p 9999:9999 seanpesce-cve-2024-22243:latest
111+
```
112+
113+
The web app will be accessible at `http://127.0.0.1:9999/` on the Docker host.
114+
115+
116+
## Semgrep
117+
118+
This repository also contains [semgrep](https://semgrep.dev/) rules to assist in scanning for
119+
potentially-vulnerable code paths. [`spring-cve-2024-22243_loose.yaml`](semgrep/spring-cve-2024-22243_loose.yaml)
120+
performs naive scans for any use of the vulnerable APIs; as such, it will often return a large
121+
number of false positives. [`spring-cve-2024-22243_strict.yaml`](semgrep/spring-cve-2024-22243_strict.yaml)
122+
attempts to use stricter logic and taint analysis; however, this has not been
123+
thoroughly tested and has high potential to miss some vulnerable implementations (especially when not using
124+
Semgrep Pro, which does not support cross-file analysis).
125+
126+

pom.xml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!-- Author: Sean Pesce -->
3+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>com.seanpesce</groupId>
8+
<artifactId>spring-cve-2024-22243</artifactId>
9+
<packaging>jar</packaging>
10+
<version>0.1.0</version>
11+
12+
<properties>
13+
<maven.compiler.source>17</maven.compiler.source>
14+
<maven.compiler.target>17</maven.compiler.target>
15+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
16+
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
17+
</properties>
18+
19+
<build>
20+
<plugins>
21+
<plugin>
22+
<groupId>org.apache.maven.plugins</groupId>
23+
<artifactId>maven-shade-plugin</artifactId>
24+
<version>3.2.4</version>
25+
<executions>
26+
<execution>
27+
<phase>package</phase>
28+
<goals>
29+
<goal>shade</goal>
30+
</goals>
31+
<configuration>
32+
<transformers>
33+
<transformer
34+
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
35+
<mainClass>com.seanpesce.spring.VulnerableWebApp</mainClass>
36+
</transformer>
37+
</transformers>
38+
</configuration>
39+
</execution>
40+
</executions>
41+
</plugin>
42+
</plugins>
43+
</build>
44+
<dependencies>
45+
<dependency>
46+
<groupId>org.springframework.boot</groupId>
47+
<artifactId>spring-boot-starter-web</artifactId>
48+
<version>3.2.1</version>
49+
</dependency>
50+
<dependency>
51+
<groupId>org.springframework.boot</groupId>
52+
<artifactId>spring-boot-starter-thymeleaf</artifactId>
53+
<version>3.2.2</version>
54+
</dependency>
55+
<!-- WebClient class dependency -->
56+
<dependency>
57+
<groupId>org.springframework.boot</groupId>
58+
<artifactId>spring-boot-starter-webflux</artifactId>
59+
<version>3.2.2</version>
60+
</dependency>
61+
</dependencies>
62+
</project>

0 commit comments

Comments
 (0)