Moderate severity vulnerability that affects org.springframework:spring-core
Research is free — Hunters explains how the bug works, the root-cause code pattern, how the fix addresses it, and how to test whether a target is affected, in chat. Investigate & write exploit is a paid run — the engine reads the advisory and fix commits, then builds and validates a working proof-of-concept exploit with reproduction steps.
Affected versions
Details
Spring Framework, versions 5.0.x prior to 5.0.7 and 4.3.x prior to 4.3.18 and older unsupported versions, allows web applications to enable cross-domain requests via JSONP (JSON with Padding) through AbstractJsonpResponseBodyAdvice for REST controllers and MappingJackson2JsonView for browser requests. Both are not enabled by default in Spring Framework nor Spring Boot, however, when MappingJackson2JsonView is configured in an application, JSONP support is automatically ready to use through the "jsonp" and "callback" JSONP parameters, enabling cross-domain requests.
The fix
Deprecate JSONP and disable it by default in Jackson view
spring-web/src/main/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverter.java+3 −1
@@ -1,5 +1,5 @@/*-* Copyright 2002-2016 the original author or authors.+* Copyright 2002-2018 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -88,6 +88,7 @@ public void setPrefixJson(boolean prefixJson) {@Override+@SuppressWarnings("deprecation")protected void writePrefix(JsonGenerator generator, Object object) throws IOException {if (this.jsonPrefix != null) {generator.writeRaw(this.jsonPrefix);@@ -101,6 +102,7 @@ protected void writePrefix(JsonGenerator generator, Object object) throws IOExce}@Override+@SuppressWarnings("deprecation")protected void writeSuffix(JsonGenerator generator, Object object) throws IOException {String jsonpFunction =(object instanceof MappingJacksonValue ? ((MappingJacksonValue) object).getJsonpFunction() : null);
spring-web/src/main/java/org/springframework/http/converter/json/MappingJacksonValue.java+7 −1
@@ -1,5 +1,5 @@/*-* Copyright 2002-2015 the original author or authors.+* Copyright 2002-2018 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -108,14 +108,20 @@ public FilterProvider getFilters() {/*** Set the name of the JSONP function name.+* @deprecated Will be removed as of Spring Framework 5.1, use+* <a href="https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/html/cors.html">CORS</a> instead.*/+@Deprecatedpublic void setJsonpFunction(String functionName) {this.jsonpFunction = functionName;}/*** Return the configured JSONP function name.+* @deprecated Will be removed as of Spring Framework 5.1, use+* <a href="https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/html/cors.html">CORS</a> instead.*/+@Deprecatedpublic String getJsonpFunction() {return this.jsonpFunction;}
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractJsonpResponseBodyAdvice.java+4 −1
@@ -1,5 +1,5 @@/*-* Copyright 2002-2015 the original author or authors.+* Copyright 2002-2018 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -45,7 +45,10 @@** @author Rossen Stoyanchev* @since 4.1+* @deprecated Will be removed as of Spring Framework 5.1, use+* <a href="https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/html/cors.html">CORS</a> instead.*/+@Deprecatedpublic abstract class AbstractJsonpResponseBodyAdvice extends AbstractMappingJacksonResponseBodyAdvice {/**
spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/MappingJackson2JsonView.java+12 −3
@@ -1,5 +1,5 @@/*-* Copyright 2002-2015 the original author or authors.+* Copyright 2002-2018 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -17,7 +17,6 @@package org.springframework.web.servlet.view.json;import java.io.IOException;-import java.util.Arrays;import java.util.Collections;import java.util.HashMap;import java.util.LinkedHashSet;@@ -58,6 +57,7 @@* @author Sebastien Deleuze* @since 3.1.2*/+@SuppressWarnings("deprecation")public class MappingJackson2JsonView extends AbstractJackson2View {/**@@ -68,7 +68,10 @@ public class MappingJackson2JsonView extends AbstractJackson2View {/*** Default content type for JSONP: "application/javascript".+* @deprecated Will be removed as of Spring Framework 5.1, use+* <a href="https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/html/cors.html">CORS</a> instead.*/+@Deprecatedpublic static final String DEFAULT_JSONP_CONTENT_TYPE = "application/javascript";/**@@ -83,7 +86,7 @@ public class MappingJackson2JsonView extends AbstractJackson2View {private boolean extractValueFromSingleKeyModel = false;-private Set<String> jsonpParameterNames = new LinkedHashSet<String>(Arrays.asList("jsonp", "callback"));+private Set<String> jsonpParameterNames = new LinkedHashSet<String>();/**@@ -168,7 +171,10 @@ public void setExtractValueFromSingleKeyModel(boolean extractValueFromSingleKeyM* <p>The parameter names configured by default are "jsonp" and "callback".* @since 4.1* @see <a href="http://en.wikipedia.org/wiki/JSONP">JSONP Wikipedia article</a>+* @deprecated Will be removed as of Spring Framework 5.1, use+* <a href="https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/html/cors.html">CORS</a> instead.*/+@Deprecatedpublic void setJsonpParameterNames(Set<String> jsonpParameterNames) {this.jsonpParameterNames = jsonpParameterNames;}@@ -198,7 +204,10 @@ private String getJsonpParameterValue(HttpServletRequest request) {* Invalid parameter values are ignored.* @param value the query param value, never {@code null}* @since 4.1.8+* @deprecated Will be removed as of Spring Framework 5.1, use+* <a href="https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/html/cors.html">CORS</a> instead.*/+@Deprecatedprotected boolean isValidJsonpQueryParam(String value) {return CALLBACK_PARAM_PATTERN.matcher(value).matches();}
spring-webmvc/src/test/java/org/springframework/web/servlet/view/json/MappingJackson2JsonViewTests.java+12 −2
@@ -1,5 +1,5 @@/*-* Copyright 2002-2015 the original author or authors.+* Copyright 2002-2018 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -17,9 +17,11 @@package org.springframework.web.servlet.view.json;import java.io.IOException;+import java.util.Arrays;import java.util.Date;import java.util.HashMap;import java.util.HashSet;+import java.util.LinkedHashSet;import java.util.Map;import java.util.Set;@@ -324,11 +326,19 @@ public void renderSimpleBeanWithFilters() throws Exception {@Testpublic void renderWithJsonp() throws Exception {+testJsonp("jsonp", "callback", false);+testJsonp("jsonp", "_callback", false);+testJsonp("jsonp", "_Call.bAcK", false);+testJsonp("jsonp", "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_.", false);+testJsonp("jsonp", "<script>", false);+testJsonp("jsonp", "!foo!bar", false);++this.view.setJsonpParameterNames(new LinkedHashSet<String>(Arrays.asList("jsonp")));+testJsonp("jsonp", "callback", true);testJsonp("jsonp", "_callback", true);testJsonp("jsonp", "_Call.bAcK", true);testJsonp("jsonp", "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_.", true);-testJsonp("jsonp", "<script>", false);testJsonp("jsonp", "!foo!bar", false);}
spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/TransportType.java+5 −1
@@ -1,5 +1,5 @@/*-* Copyright 2002-2015 the original author or authors.+* Copyright 2002-2018 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -27,6 +27,8 @@/*** SockJS transport types.*+* <p>JSONP support will be removed as of Spring Framework 5.1, use others transports instead.+** @author Rossen Stoyanchev* @author Sebastien Deleuze* @since 4.0@@ -39,8 +41,10 @@ public enum TransportType {XHR_SEND("xhr_send", HttpMethod.POST, "cors", "jsessionid", "no_cache"),+@DeprecatedJSONP("jsonp", HttpMethod.GET, "jsessionid", "no_cache"),+@DeprecatedJSONP_SEND("jsonp_send", HttpMethod.POST, "jsessionid", "no_cache"),XHR_STREAMING("xhr_streaming", HttpMethod.POST, "cors", "jsessionid", "no_cache"),
spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/handler/DefaultSockJsService.java+2 −1
@@ -1,5 +1,5 @@/*-* Copyright 2002-2014 the original author or authors.+* Copyright 2002-2018 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -78,6 +78,7 @@ public DefaultSockJsService(TaskScheduler scheduler, Collection<TransportHandler}+@SuppressWarnings("deprecation")private static Set<TransportHandler> getDefaultTransportHandlers(Collection<TransportHandler> overrides) {Set<TransportHandler> result = new LinkedHashSet<TransportHandler>(8);result.add(new XhrPollingTransportHandler());
spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/handler/JsonpPollingTransportHandler.java+3 −1
@@ -1,5 +1,5 @@/*-* Copyright 2002-2014 the original author or authors.+* Copyright 2002-2018 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -40,7 +40,9 @@** @author Rossen Stoyanchev* @since 4.0+* @deprecated Will be removed as of Spring Framework 5.1, use others transports instead.*/+@Deprecatedpublic class JsonpPollingTransportHandler extends AbstractHttpSendingTransportHandler {@Override
Deprecate JSONP and disable it by default in Jackson view
spring-web/src/main/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverter.java+3 −1
@@ -1,5 +1,5 @@/*-* Copyright 2002-2017 the original author or authors.+* Copyright 2002-2018 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -91,6 +91,7 @@ public void setPrefixJson(boolean prefixJson) {@Override+@SuppressWarnings("deprecation")protected void writePrefix(JsonGenerator generator, Object object) throws IOException {if (this.jsonPrefix != null) {generator.writeRaw(this.jsonPrefix);@@ -104,6 +105,7 @@ protected void writePrefix(JsonGenerator generator, Object object) throws IOExce}@Override+@SuppressWarnings("deprecation")protected void writeSuffix(JsonGenerator generator, Object object) throws IOException {String jsonpFunction =(object instanceof MappingJacksonValue ? ((MappingJacksonValue) object).getJsonpFunction() : null);
spring-web/src/main/java/org/springframework/http/converter/json/MappingJacksonValue.java+7 −1
@@ -1,5 +1,5 @@/*-* Copyright 2002-2017 the original author or authors.+* Copyright 2002-2018 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -115,14 +115,20 @@ public FilterProvider getFilters() {/*** Set the name of the JSONP function name.+* @deprecated Will be removed as of Spring Framework 5.1, use+* <a href="https://docs.spring.io/spring/docs/5.0.x/spring-framework-reference/web.html#mvc-cors">CORS</a> instead.*/+@Deprecatedpublic void setJsonpFunction(@Nullable String functionName) {this.jsonpFunction = functionName;}/*** Return the configured JSONP function name.+* @deprecated Will be removed as of Spring Framework 5.1, use+* <a href="https://docs.spring.io/spring/docs/5.0.x/spring-framework-reference/web.html#mvc-cors">CORS</a> instead.*/+@Deprecated@Nullablepublic String getJsonpFunction() {return this.jsonpFunction;
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractJsonpResponseBodyAdvice.java+4 −1
@@ -1,5 +1,5 @@/*-* Copyright 2002-2015 the original author or authors.+* Copyright 2002-2018 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -45,7 +45,10 @@** @author Rossen Stoyanchev* @since 4.1+* @deprecated Will be removed as of Spring Framework 5.1, use+* <a href="https://docs.spring.io/spring/docs/5.0.x/spring-framework-reference/web.html#mvc-cors">CORS</a> instead.*/+@Deprecatedpublic abstract class AbstractJsonpResponseBodyAdvice extends AbstractMappingJacksonResponseBodyAdvice {/**
spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/MappingJackson2JsonView.java+14 −3
@@ -1,5 +1,5 @@/*-* Copyright 2002-2017 the original author or authors.+* Copyright 2002-2018 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -59,6 +59,7 @@* @author Sebastien Deleuze* @since 3.1.2*/+@SuppressWarnings("deprecation")public class MappingJackson2JsonView extends AbstractJackson2View {/**@@ -69,7 +70,10 @@ public class MappingJackson2JsonView extends AbstractJackson2View {/*** Default content type for JSONP: "application/javascript".+* @deprecated Will be removed as of Spring Framework 5.1, use+* <a href="https://docs.spring.io/spring/docs/5.0.x/spring-framework-reference/web.html#mvc-cors">CORS</a> instead.*/+@Deprecatedpublic static final String DEFAULT_JSONP_CONTENT_TYPE = "application/javascript";/**@@ -87,7 +91,7 @@ public class MappingJackson2JsonView extends AbstractJackson2View {private boolean extractValueFromSingleKeyModel = false;@Nullable-private Set<String> jsonpParameterNames = new LinkedHashSet<>(Arrays.asList("jsonp", "callback"));+private Set<String> jsonpParameterNames = new LinkedHashSet<>();/**@@ -170,10 +174,14 @@ public void setExtractValueFromSingleKeyModel(boolean extractValueFromSingleKeyM* Set JSONP request parameter names. Each time a request has one of those* parameters, the resulting JSON will be wrapped into a function named as* specified by the JSONP request parameter value.-* <p>The parameter names configured by default are "jsonp" and "callback".+* <p>As of Spring Framework 5.0.7, there is no parameter name configured+* by default.* @since 4.1* @see <a href="http://en.wikipedia.org/wiki/JSONP">JSONP Wikipedia article</a>+* @deprecated Will be removed as of Spring Framework 5.1, use+* <a href="https://docs.spring.io/spring/docs/5.0.x/spring-framework-reference/web.html#mvc-cors">CORS</a> instead.*/+@Deprecatedpublic void setJsonpParameterNames(Set<String> jsonpParameterNames) {this.jsonpParameterNames = jsonpParameterNames;}@@ -204,7 +212,10 @@ private String getJsonpParameterValue(HttpServletRequest request) {* Invalid parameter values are ignored.* @param value the query param value, never {@code null}* @since 4.1.8+* @deprecated Will be removed as of Spring Framework 5.1, use+* <a href="https://docs.spring.io/spring/docs/5.0.x/spring-framework-reference/web.html#mvc-cors">CORS</a> instead.*/+@Deprecatedprotected boolean isValidJsonpQueryParam(String value) {return CALLBACK_PARAM_PATTERN.matcher(value).matches();}
spring-webmvc/src/test/java/org/springframework/web/servlet/view/json/MappingJackson2JsonViewTests.java+12 −2
@@ -1,5 +1,5 @@/*-* Copyright 2002-2016 the original author or authors.+* Copyright 2002-2018 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -17,9 +17,11 @@package org.springframework.web.servlet.view.json;import java.io.IOException;+import java.util.Arrays;import java.util.Date;import java.util.HashMap;import java.util.HashSet;+import java.util.LinkedHashSet;import java.util.Map;import java.util.Set;@@ -324,11 +326,19 @@ public void renderSimpleBeanWithFilters() throws Exception {@Testpublic void renderWithJsonp() throws Exception {+testJsonp("jsonp", "callback", false);+testJsonp("jsonp", "_callback", false);+testJsonp("jsonp", "_Call.bAcK", false);+testJsonp("jsonp", "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_.", false);+testJsonp("jsonp", "<script>", false);+testJsonp("jsonp", "!foo!bar", false);++this.view.setJsonpParameterNames(new LinkedHashSet<>(Arrays.asList("jsonp")));+testJsonp("jsonp", "callback", true);testJsonp("jsonp", "_callback", true);testJsonp("jsonp", "_Call.bAcK", true);testJsonp("jsonp", "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_.", true);-testJsonp("jsonp", "<script>", false);testJsonp("jsonp", "!foo!bar", false);}
spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/TransportType.java+5 −1
@@ -1,5 +1,5 @@/*-* Copyright 2002-2017 the original author or authors.+* Copyright 2002-2018 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -28,6 +28,8 @@/*** SockJS transport types.*+* <p>JSONP support will be removed as of Spring Framework 5.1, use others transports instead.+** @author Rossen Stoyanchev* @author Sebastien Deleuze* @since 4.0@@ -40,8 +42,10 @@ public enum TransportType {XHR_SEND("xhr_send", HttpMethod.POST, "cors", "jsessionid", "no_cache"),+@DeprecatedJSONP("jsonp", HttpMethod.GET, "jsessionid", "no_cache"),+@DeprecatedJSONP_SEND("jsonp_send", HttpMethod.POST, "jsessionid", "no_cache"),XHR_STREAMING("xhr_streaming", HttpMethod.POST, "cors", "jsessionid", "no_cache"),
spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/handler/DefaultSockJsService.java+2 −1
@@ -1,5 +1,5 @@/*-* Copyright 2002-2016 the original author or authors.+* Copyright 2002-2018 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -79,6 +79,7 @@ public DefaultSockJsService(TaskScheduler scheduler, Collection<TransportHandler}+@SuppressWarnings("deprecation")private static Set<TransportHandler> getDefaultTransportHandlers(@Nullable Collection<TransportHandler> overrides) {Set<TransportHandler> result = new LinkedHashSet<>(8);result.add(new XhrPollingTransportHandler());
spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/handler/JsonpPollingTransportHandler.java+3 −1
@@ -1,5 +1,5 @@/*-* Copyright 2002-2016 the original author or authors.+* Copyright 2002-2018 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -41,7 +41,9 @@** @author Rossen Stoyanchev* @since 4.0+* @deprecated Will be removed as of Spring Framework 5.1, use others transports instead.*/+@Deprecatedpublic class JsonpPollingTransportHandler extends AbstractHttpSendingTransportHandler {@Override
References
- ADVISORYhttps://nvd.nist.gov/vuln/detail/CVE-2018-11040
- WEBhttps://github.com/spring-projects/spring-framework/commit/874859493bbda59739c38c7e52eb3625f247b93a
- WEBhttps://github.com/spring-projects/spring-framework/commit/b80c13b722bb207ddf43f53a007ee3ddc1dd2e26
- ADVISORYhttps://github.com/advisories/GHSA-f26x-pr96-vw86
- PACKAGEhttps://github.com/spring-projects/spring-framework
- WEBhttps://lists.debian.org/debian-lts-announce/2021/04/msg00022.html
- WEBhttps://pivotal.io/security/cve-2018-11040
- WEBhttps://www.oracle.com/security-alerts/cpujan2020.html
- WEBhttps://www.oracle.com/security-alerts/cpujul2020.html
- WEBhttps://www.oracle.com/security-alerts/cpuoct2021.html
- WEBhttps://www.oracle.com/technetwork/security-advisory/cpuapr2019-5072813.html
- WEBhttps://www.oracle.com/technetwork/security-advisory/cpujan2019-5072801.html