diff --git a/CVE-2022-42252.patch b/CVE-2022-42252.patch new file mode 100644 index 0000000000000000000000000000000000000000..e50e97fb444f8049765882268b62222e8dbba145 --- /dev/null +++ b/CVE-2022-42252.patch @@ -0,0 +1,127 @@ +diff -upr tomcat-9.0.10_back/java/org/apache/coyote/http11/Http11InputBuffer.java tomcat-9.0.10/java/org/apache/coyote/http11/Http11InputBuffer.java +--- tomcat-9.0.10_back/java/org/apache/coyote/http11/Http11InputBuffer.java 2022-12-14 10:39:12.917000000 +0800 ++++ tomcat-9.0.10/java/org/apache/coyote/http11/Http11InputBuffer.java 2022-12-14 10:48:31.180863424 +0800 +@@ -821,7 +821,7 @@ public class Http11InputBuffer implement + headerData.lastSignificantChar = pos; + byteBuffer.position(byteBuffer.position() - 1); + // skipLine() will handle the error +- return skipLine(); ++ return skipLine(false); + } + + // chr is next byte of header name. Convert to lowercase. +@@ -832,7 +832,7 @@ public class Http11InputBuffer implement + + // Skip the line and ignore the header + if (headerParsePos == HeaderParsePosition.HEADER_SKIPLINE) { +- return skipLine(); ++ return skipLine(false); + } + + // +@@ -883,15 +883,11 @@ public class Http11InputBuffer implement + } else if (prevChr == Constants.CR && chr == Constants.LF) { + eol = true; + } else if (prevChr == Constants.CR) { +- // Invalid value +- // Delete the header (it will be the most recent one) +- headers.removeHeader(headers.size() - 1); +- return skipLine(); ++ // Invalid value - also need to delete header ++ return skipLine(true); + } else if (chr != Constants.HT && HttpParser.isControl(chr)) { +- // Invalid value +- // Delete the header (it will be the most recent one) +- headers.removeHeader(headers.size() - 1); +- return skipLine(); ++ // Invalid value - also need to delete header ++ return skipLine(true); + } else if (chr == Constants.SP || chr == Constants.HT) { + byteBuffer.put(headerData.realPos, chr); + headerData.realPos++; +@@ -939,7 +935,27 @@ public class Http11InputBuffer implement + } + + +- private HeaderParseStatus skipLine() throws IOException { ++ private HeaderParseStatus skipLine(boolean deleteHeader) throws IOException { ++ boolean rejectThisHeader = rejectIllegalHeader; ++ // Check if rejectIllegalHeader is disabled and needs to be overridden ++ // for this header. The header name is required to determine if this ++ // override is required. The header name is only available once the ++ // header has been created. If the header has been created then ++ // deleteHeader will be true. ++ if (!rejectThisHeader && deleteHeader) { ++ if (headers.getName(headers.size() - 1).equalsIgnoreCase("content-length")) { ++ // Malformed content-length headers must always be rejected ++ // RFC 9112, section 6.3, bullet 5. ++ rejectThisHeader = true; ++ } else { ++ // Only need to delete the header if the request isn't going to ++ // be rejected (it will be the most recent one) ++ headers.removeHeader(headers.size() - 1); ++ } ++ } ++ ++ // Parse the rest of the invalid header so we can construct a useful ++ // exception and/or debug message. + headerParsePos = HeaderParsePosition.HEADER_SKIPLINE; + boolean eol = false; + +@@ -967,12 +983,12 @@ public class Http11InputBuffer implement + headerData.lastSignificantChar = pos; + } + } +- if (rejectIllegalHeader || log.isDebugEnabled()) { ++ if (rejectThisHeader || log.isDebugEnabled()) { + String message = sm.getString("iib.invalidheader", + new String(byteBuffer.array(), headerData.start, + headerData.lastSignificantChar - headerData.start + 1, + StandardCharsets.ISO_8859_1)); +- if (rejectIllegalHeader) { ++ if (rejectThisHeader) { + throw new IllegalArgumentException(message); + } + log.debug(message); +diff -upr tomcat-9.0.10_back/test/org/apache/coyote/http11/TestHttp11InputBuffer.java tomcat-9.0.10/test/org/apache/coyote/http11/TestHttp11InputBuffer.java +--- tomcat-9.0.10_back/test/org/apache/coyote/http11/TestHttp11InputBuffer.java 2022-12-14 10:39:12.971000000 +0800 ++++ tomcat-9.0.10/test/org/apache/coyote/http11/TestHttp11InputBuffer.java 2022-12-14 10:51:16.845501479 +0800 +@@ -643,6 +643,38 @@ public class TestHttp11InputBuffer exten + Assert.assertTrue(client.isResponseBodyOK()); + } + ++ @Test ++ public void testInvalidContentLength01() { ++ doTestInvalidContentLength(false); ++ } ++ ++ ++ @Test ++ public void testInvalidContentLength02() { ++ doTestInvalidContentLength(true); ++ } ++ ++ ++ private void doTestInvalidContentLength(boolean rejectIllegalHeader) { ++ getTomcatInstance().getConnector().setProperty("rejectIllegalHeader", Boolean.toString(rejectIllegalHeader)); ++ ++ String[] request = new String[1]; ++ request[0] = ++ "POST /test HTTP/1.1" + CRLF + ++ "Host: localhost:8080" + CRLF + ++ "Content-Length: 12\u000734" + CRLF + ++ "Connection: close" + CRLF + ++ CRLF; ++ ++ InvalidClient client = new InvalidClient(request); ++ ++ client.doRequest(); ++ Assert.assertTrue(client.getResponseLine(), client.isResponse400()); ++ Assert.assertTrue(client.isResponseBodyOK()); ++ } ++ ++ ++ + + /** + * Bug 48839 test client. diff --git a/tomcat.spec b/tomcat.spec index 84cfd56ed6b5125bb9218cbfb66758580312445d..c3e07901efc8754af2c079a4e4aa435bdb0fd710 100644 --- a/tomcat.spec +++ b/tomcat.spec @@ -13,7 +13,7 @@ Name: tomcat Epoch: 1 Version: %{major_version}.%{minor_version}.%{micro_version} -Release: 28 +Release: 29 Summary: Implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies License: ASL 2.0 URL: http://tomcat.apache.org/ @@ -101,6 +101,7 @@ Patch6056: CVE-2021-30640-8.patch Patch6057: CVE-2021-41079.patch Patch6058: CVE-2021-42340.patch Patch6069: CVE-2022-23181.patch +Patch6070: CVE-2022-42252.patch BuildRequires: ecj >= 1:4.6.1 findutils apache-commons-collections apache-commons-daemon BuildRequires: apache-commons-dbcp apache-commons-pool tomcat-taglibs-standard ant @@ -502,6 +503,9 @@ fi %{_javadocdir}/%{name} %changelog +* Wed Dec 21 2022 xulei - 1:9.0.10-29 +- Fix CVE-2022-42252 + * Fri Aug 12 2022 liyanan - 1:9.0.10-28 - Update build-classpath calls to ECJ to specify the JAR we want to use