|
| 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 | + |
0 commit comments