Hello, I have prepared a security update for Jackrabbit to fix CVE-2016-6801. Please find attached the debdiff. Regards, Markus
diff -Nru jackrabbit-2.3.6/debian/changelog jackrabbit-2.3.6/debian/changelog --- jackrabbit-2.3.6/debian/changelog 2015-06-29 01:49:08.000000000 +0200 +++ jackrabbit-2.3.6/debian/changelog 2016-09-26 15:20:09.000000000 +0200 @@ -1,3 +1,14 @@ +jackrabbit (2.3.6-1+deb8u2) jessie-security; urgency=medium + + * Team upload. + * Fix CVE-2016-6801: + The CSRF content-type check for POST requests did not handle missing + Content-Type header fields, nor variations in field values with respect to + upper/lower case or optional parameters. This could be exploited to create + a resource via CSRF. + + -- Markus Koschany <apo@debian.org> Mon, 26 Sep 2016 15:20:09 +0200 + jackrabbit (2.3.6-1+deb8u1) jessie-security; urgency=medium * Team upload. diff -Nru jackrabbit-2.3.6/debian/patches/CVE-2016-6801.patch jackrabbit-2.3.6/debian/patches/CVE-2016-6801.patch --- jackrabbit-2.3.6/debian/patches/CVE-2016-6801.patch 1970-01-01 01:00:00.000000000 +0100 +++ jackrabbit-2.3.6/debian/patches/CVE-2016-6801.patch 2016-09-26 15:20:09.000000000 +0200 @@ -0,0 +1,192 @@ +From: Markus Koschany <apo@debian.org> +Date: Sun, 18 Sep 2016 16:46:33 +0200 +Subject: CVE-2016-6801 + +The CSRF content-type check for POST requests did not handle missing +Content-Type header fields, nor variations in field values with respect to +upper/lower case or optional parameters. This could be exploited to create a +resource via CSRF. + +Backported to the 2.3 branch. + +Origin: https://svn.apache.org/viewvc?view=revision&revision=1758791 +--- + .../apache/jackrabbit/spi2davex/PostMethod.java | 1 + + .../org/apache/jackrabbit/webdav/DavResource.java | 2 +- + .../webdav/server/AbstractWebdavServlet.java | 3 +- + .../apache/jackrabbit/webdav/util/CSRFUtil.java | 83 ++++++++++++++++++---- + 4 files changed, 74 insertions(+), 15 deletions(-) + +diff --git a/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/PostMethod.java b/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/PostMethod.java +index 5355a72..f6e243c 100644 +--- a/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/PostMethod.java ++++ b/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/PostMethod.java +@@ -47,6 +47,7 @@ class PostMethod extends DavMethodBase { + + public PostMethod(String uri) { + super(uri); ++ super.setRequestHeader("Referer", uri); + HttpMethodParams params = getParams(); + params.setContentCharset("UTF-8"); + } +diff --git a/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResource.java b/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResource.java +index c99b5cd..6e70a42 100644 +--- a/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResource.java ++++ b/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResource.java +@@ -40,7 +40,7 @@ public interface DavResource { + /** + * String constant representing the WebDAV 1 and 2 method set. + */ +- public static final String METHODS = "OPTIONS, GET, HEAD, POST, TRACE, PROPFIND, PROPPATCH, MKCOL, COPY, PUT, DELETE, MOVE, LOCK, UNLOCK"; ++ public static final String METHODS = "OPTIONS, GET, HEAD, TRACE, PROPFIND, PROPPATCH, MKCOL, COPY, PUT, DELETE, MOVE, LOCK, UNLOCK"; + + /** + * Returns a comma separated list of all compliance classes the given +diff --git a/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java b/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java +index 128946e..a1bdbf4 100644 +--- a/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java ++++ b/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java +@@ -568,7 +568,7 @@ abstract public class AbstractWebdavServlet extends HttpServlet implements DavCo + */ + protected void doPost(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { +- doPut(request, response, resource); ++ response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED); + } + + /** +@@ -1356,7 +1356,6 @@ abstract public class AbstractWebdavServlet extends HttpServlet implements DavCo + * @param out + * @return + * @see #doPut(WebdavRequest, WebdavResponse, DavResource) +- * @see #doPost(WebdavRequest, WebdavResponse, DavResource) + * @see #doMkCol(WebdavRequest, WebdavResponse, DavResource) + */ + protected OutputContext getOutputContext(DavServletResponse response, OutputStream out) { +diff --git a/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/CSRFUtil.java b/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/CSRFUtil.java +index 4d431eb..b5fc8f4 100644 +--- a/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/CSRFUtil.java ++++ b/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/CSRFUtil.java +@@ -19,12 +19,18 @@ package org.apache.jackrabbit.webdav.util; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + +-import javax.servlet.http.HttpServletRequest; +-import java.net.MalformedURLException; +-import java.net.URL; ++import java.net.URI; ++import java.net.URISyntaxException; ++import java.util.Arrays; + import java.util.Collections; ++import java.util.Enumeration; + import java.util.HashSet; + import java.util.Set; ++import java.util.Locale; ++import javax.servlet.http.HttpServletRequest; ++ ++import org.slf4j.Logger; ++import org.slf4j.LoggerFactory; + + /** + * <code>CSRFUtil</code>... +@@ -37,6 +43,19 @@ public class CSRFUtil { + public static final String DISABLED = "disabled"; + + /** ++ * Request content types for CSRF checking, see JCR-3909, JCR-4002, and JCR-4009 ++ */ ++ public static final Set<String> CONTENT_TYPES = Collections.unmodifiableSet(new HashSet<String>( ++ Arrays.asList( ++ new String[] { ++ "application/x-www-form-urlencoded", ++ "multipart/form-data", ++ "text/plain" ++ } ++ ) ++ )); ++ ++ /** + * logger instance + */ + private static final Logger log = LoggerFactory.getLogger(CSRFUtil.class); +@@ -77,6 +96,7 @@ public class CSRFUtil { + if (config == null || config.length() == 0) { + disabled = false; + allowedReferrerHosts = Collections.emptySet(); ++ log.debug("CSRF protection disabled"); + } else { + if (DISABLED.equalsIgnoreCase(config.trim())) { + disabled = true; +@@ -89,23 +109,62 @@ public class CSRFUtil { + allowedReferrerHosts.add(entry.trim()); + } + } ++ log.debug("CSRF protection enabled, allowed referrers: " + allowedReferrerHosts); + } + } + +- public boolean isValidRequest(HttpServletRequest request) throws MalformedURLException { ++ public boolean isValidRequest(HttpServletRequest request) { ++ + if (disabled) { + return true; ++ } else if (!"POST".equals(request.getMethod())) { ++ // protection only needed for POST ++ return true; + } else { ++ Enumeration<String> cts = (Enumeration<String>) request.getHeaders("Content-Type"); ++ String ct = null; ++ if (cts != null && cts.hasMoreElements()) { ++ String t = cts.nextElement(); ++ // prune parameters ++ int semicolon = t.indexOf(';'); ++ if (semicolon >= 0) { ++ t = t.substring(0, semicolon); ++ } ++ ct = t.trim().toLowerCase(Locale.ENGLISH); ++ } ++ if (cts != null && cts.hasMoreElements()) { ++ // reject if there are more header field instances ++ log.debug("request blocked because there were multiple content-type header fields"); ++ return false; ++ } ++ if (ct != null && !CONTENT_TYPES.contains(ct)) { ++ // type present and not in blacklist ++ return true; ++ } ++ + String refHeader = request.getHeader("Referer"); ++ // empty referrer headers are not allowed for POST + relevant ++ // content types (see JCR-3909) + if (refHeader == null) { +- // empty referrer is always allowed +- return true; +- } else { +- String host = new URL(refHeader).getHost(); +- // test referrer-host equelst server or +- // if it is contained in the set of explicitly allowed host names +- return host.equals(request.getServerName()) || allowedReferrerHosts.contains(host); ++ log.debug("POST with content type" + ct + " blocked due to missing referer header field"); ++ return false; ++ } ++ ++ try { ++ String host = new URI(refHeader).getHost(); ++ // test referrer-host equals server or ++ // if it is contained in the set of explicitly allowed host ++ // names ++ boolean ok = host == null || host.equals(request.getServerName()) || allowedReferrerHosts.contains(host); ++ if (!ok) { ++ log.debug("POST with content type" + ct + " blocked due to referer header field being: " + refHeader); ++ } ++ return ok; ++ } catch (URISyntaxException ex) { ++ // referrer malformed -> block access ++ log.debug("POST with content type" + ct + " blocked due to malformed referer header field: " + refHeader); ++ return false; + } + } + } +-} +\ No newline at end of file ++} diff -Nru jackrabbit-2.3.6/debian/patches/series jackrabbit-2.3.6/debian/patches/series --- jackrabbit-2.3.6/debian/patches/series 2015-06-29 01:49:08.000000000 +0200 +++ jackrabbit-2.3.6/debian/patches/series 2016-09-26 15:20:09.000000000 +0200 @@ -1,3 +1,4 @@ modules.diff servlet_api_25.diff CVE-2015-1833.patch +CVE-2016-6801.patch
Attachment:
signature.asc
Description: OpenPGP digital signature