From 89b6bdbc2c2d3838863e9447e138b054765a2ea3711cdda0168bf155c43bb791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Chv=C3=A1tal?= Date: Tue, 18 Sep 2018 10:59:09 +0000 Subject: [PATCH] Accepting request 636365 from home:pmonrealgonzalez:branches:Java:packages - Security fix: [bsc#1105443, CVE-2018-1000632] * Version prior to version 2.1.1 contains a CWE-91: XML Injectionvulnerability in Class: Element. Methods: addElement, addAttribute that canresult in an attacker tampering with XML documents through. * Added dom4j-CVE-2018-1000632.patch OBS-URL: https://build.opensuse.org/request/show/636365 OBS-URL: https://build.opensuse.org/package/show/Java:packages/dom4j?expand=0&rev=25 --- dom4j-CVE-2018-1000632.patch | 259 +++++++++++++++++++++++++++++++++++ dom4j.changes | 10 ++ dom4j.spec | 5 +- 3 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 dom4j-CVE-2018-1000632.patch diff --git a/dom4j-CVE-2018-1000632.patch b/dom4j-CVE-2018-1000632.patch new file mode 100644 index 0000000..788b519 --- /dev/null +++ b/dom4j-CVE-2018-1000632.patch @@ -0,0 +1,259 @@ +Index: dom4j/src/java/org/dom4j/Namespace.java +=================================================================== +--- dom4j.orig/src/java/org/dom4j/Namespace.java ++++ dom4j/src/java/org/dom4j/Namespace.java +@@ -51,6 +51,10 @@ public class Namespace extends AbstractN + public Namespace(String prefix, String uri) { + this.prefix = (prefix != null) ? prefix : ""; + this.uri = (uri != null) ? uri : ""; ++ ++ if (!this.prefix.isEmpty()) { ++ QName.validateNCName(this.prefix); ++ } + } + + /** +Index: dom4j/src/java/org/dom4j/QName.java +=================================================================== +--- dom4j.orig/src/java/org/dom4j/QName.java ++++ dom4j/src/java/org/dom4j/QName.java +@@ -11,6 +11,7 @@ import java.io.IOException; + import java.io.ObjectInputStream; + import java.io.ObjectOutputStream; + import java.io.Serializable; ++import java.util.regex.Pattern; + + import org.dom4j.tree.QNameCache; + import org.dom4j.util.SingletonStrategy; +@@ -20,6 +21,7 @@ import org.dom4j.util.SingletonStrategy; + * QName represents a qualified name value of an XML element or + * attribute. It consists of a local name and a {@link Namespace}instance. This + * object is immutable. ++ * @author Filip Jirsak + *

+ * + * @author James Strachan +@@ -28,6 +30,81 @@ public class QName implements Serializab + /** The Singleton instance */ + private static SingletonStrategy singleton = null; + ++ /** ++ * {@code NameStartChar} without colon. ++ * ++ *
NameStartChar      ::=     ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
++ * ++ * @see XML 1.0 - 2.3 Common Syntactic Constructs ++ * @see XML 1.1 - 2.3 Common Syntactic Constructs ++ */ ++ private static final String NAME_START_CHAR = "_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD"; ++ ++ /** ++ * {@code NameChar} without colon. ++ * ++ *
NameChar   ::=     NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
++ * ++ * @see XML 1.0 - 2.3 Common Syntactic Constructs ++ * @see XML 1.1 - 2.3 Common Syntactic Constructs ++ */ ++ private static final String NAME_CHAR = NAME_START_CHAR + "-.0-9\u00B7\u0300-\u036F\u203F-\u2040"; ++ ++ /** ++ * {@code NCName} ++ * {@code NCName} ++ * ++ *
++     * NCName          ::=     NCNameStartChar NCNameChar*     (An XML Name, minus the ":")
++     * NCNameChar      ::=     NameChar -':'
++     * NCNameStartChar ::=     NameStartChar -':'
++     * 
++ * ++ * @see Namespaces in XML 1.0 - 4 Qualified Names ++ * @see Namespaces in XML 1.1 - 4 Qualified Names ++ */ ++ private static final String NCNAME = "["+NAME_START_CHAR+"]["+NAME_CHAR+"]*"; ++ ++ /** ++ * Regular expression for {@code Name} (with colon). ++ * ++ *
Name       ::=     NameStartChar (NameChar)*
++ * ++ * @see XML 1.0 - 2.3 Common Syntactic Constructs ++ * @see XML 1.1 - 2.3 Common Syntactic Constructs ++ */ ++ private static final Pattern RE_NAME = Pattern.compile("[:"+NAME_START_CHAR+"][:"+NAME_CHAR+"]*"); ++ ++ /** ++ * Regular expression for {@code NCName}. ++ * ++ *
++     * NCName          ::=     NCNameStartChar NCNameChar*     (An XML Name, minus the ":")
++     * NCNameChar      ::=     NameChar -':'
++     * NCNameStartChar ::=     NameStartChar -':'
++     * 
++ * ++ * @see Namespaces in XML 1.0 - 4 Qualified Names ++ * @see Namespaces in XML 1.1 - 4 Qualified Names ++ */ ++ private static final Pattern RE_NCNAME = Pattern.compile(NCNAME); ++ ++ /** ++ * Regular expression for {@code QName}. ++ * ++ *
++     * QName           ::=     PrefixedName | UnprefixedName
++     * PrefixedName    ::=     Prefix ':' LocalPart
++     * UnprefixedName  ::=     LocalPart
++     * Prefix          ::=     NCName
++     * LocalPart       ::=     NCName
++     * 
++ * ++ * @see Namespaces in XML 1.0 - 4 Qualified Names ++ * @see Namespaces in XML 1.1 - 4 Qualified Names ++ */ ++ private static final Pattern RE_QNAME = Pattern.compile("(?:"+NCNAME+":)?"+NCNAME); ++ + static { + try { + String defaultSingletonClass = "org.dom4j.util.SimpleSingleton"; +@@ -73,6 +150,11 @@ public class QName implements Serializab + this.name = (name == null) ? "" : name; + this.namespace = (namespace == null) ? Namespace.NO_NAMESPACE + : namespace; ++ if (this.namespace.equals(Namespace.NO_NAMESPACE)) { ++ validateName(this.name); ++ } else { ++ validateNCName(this.name); ++ } + } + + public QName(String name, Namespace namespace, String qualifiedName) { +@@ -80,6 +162,8 @@ public class QName implements Serializab + this.qualifiedName = qualifiedName; + this.namespace = (namespace == null) ? Namespace.NO_NAMESPACE + : namespace; ++ validateNCName(this.name); ++ validateQName(this.qualifiedName); + } + + public static QName get(String name) { +@@ -253,6 +337,24 @@ public class QName implements Serializab + QNameCache cache = (QNameCache) singleton.instance(); + return cache; + } ++ ++ private static void validateName(String name) { ++ if (!RE_NAME.matcher(name).matches()) { ++ throw new IllegalArgumentException(String.format("Illegal character in name: '%s'.", name)); ++ } ++ } ++ ++ protected static void validateNCName(String ncname) { ++ if (!RE_NCNAME.matcher(ncname).matches()) { ++ throw new IllegalArgumentException(String.format("Illegal character in local name: '%s'.", ncname)); ++ } ++ } ++ ++ private static void validateQName(String qname) { ++ if (!RE_QNAME.matcher(qname).matches()) { ++ throw new IllegalArgumentException(String.format("Illegal character in qualified name: '%s'.", qname)); ++ } ++ } + } + + +Index: dom4j/src/java/org/dom4j/tree/QNameCache.java +=================================================================== +--- dom4j.orig/src/java/org/dom4j/tree/QNameCache.java ++++ dom4j/src/java/org/dom4j/tree/QNameCache.java +@@ -164,6 +164,8 @@ public class QNameCache { + + if (index < 0) { + return get(qualifiedName, Namespace.get(uri)); ++ } else if (index == 0){ ++ throw new IllegalArgumentException("Qualified name cannot start with ':'."); + } else { + String name = qualifiedName.substring(index + 1); + String prefix = qualifiedName.substring(0, index); +Index: dom4j/src/test/org/dom4j/AllowedCharsTest.java +=================================================================== +--- /dev/null ++++ dom4j/src/test/org/dom4j/AllowedCharsTest.java +@@ -0,0 +1,78 @@ ++package org.dom4j;^M ++^M ++import org.testng.annotations.Test;^M ++^M ++/**^M ++ * @author Filip Jirsak^M ++ */^M ++public class AllowedCharsTest {^M ++ @Test^M ++ public void localName() {^M ++ QName.get("element");^M ++ QName.get(":element");^M ++ QName.get("elem:ent");^M ++ }^M ++^M ++ @Test(expectedExceptions = IllegalArgumentException.class)^M ++ public void localNameFail() {^M ++ QName.get("!element");^M ++ }^M ++^M ++ @Test^M ++ public void qname() {^M ++ QName.get("element", "http://example.com/namespace");^M ++ QName.get("ns:element", "http://example.com/namespace");^M ++ }^M ++^M ++ @Test(expectedExceptions = IllegalArgumentException.class)^M ++ public void qnameFail1() {^M ++ QName.get("ns:elem:ent", "http://example.com/namespace");^M ++ }^M ++^M ++ @Test(expectedExceptions = IllegalArgumentException.class)^M ++ public void qnameFail2() {^M ++ QName.get(":nselement", "http://example.com/namespace");^M ++ }^M ++^M ++ @Test(expectedExceptions = IllegalArgumentException.class)^M ++ public void createElementLT() {^M ++ DocumentHelper.createElement("elementname");^M ++ }^M ++^M ++ @Test(expectedExceptions = IllegalArgumentException.class)^M ++ public void createElementAmpersand() {^M ++ DocumentHelper.createElement("element&name");^M ++ }^M ++^M ++ @Test(expectedExceptions = IllegalArgumentException.class)^M ++ public void addElement() {^M ++ Element root = DocumentHelper.createElement("root");^M ++ root.addElement("element>name");^M ++ }^M ++^M ++ @Test(expectedExceptions = IllegalArgumentException.class)^M ++ public void addElementQualified() {^M ++ Element root = DocumentHelper.createElement("root");^M ++ root.addElement("element>name", "http://example.com/namespace");^M ++ }^M ++^M ++ @Test(expectedExceptions = IllegalArgumentException.class)^M ++ public void addElementQualifiedPrefix() {^M ++ Element root = DocumentHelper.createElement("root");^M ++ root.addElement("ns:element>name", "http://example.com/namespace");^M ++ }^M ++^M ++ @Test(expectedExceptions = IllegalArgumentException.class)^M ++ public void addElementPrefix() {^M ++ Element root = DocumentHelper.createElement("root");^M ++ root.addElement("ns>:element", "http://example.com/namespace");^M ++ }^M ++^M ++ //TODO It is illegal to create element or attribute with namespace prefix and empty namespace IRI.^M ++ //See https://www.w3.org/TR/2006/REC-xml-names11-20060816/#scoping^M ++}^M diff --git a/dom4j.changes b/dom4j.changes index 00905ce..1b96d48 100644 --- a/dom4j.changes +++ b/dom4j.changes @@ -1,3 +1,13 @@ +------------------------------------------------------------------- +Tue Sep 18 10:31:28 UTC 2018 - pmonrealgonzalez@suse.com + +- Security fix: [bsc#1105443, CVE-2018-1000632] + * Version prior to version 2.1.1 contains a CWE-91: XML + Injectionvulnerability in Class: Element. Methods: addElement, + addAttribute that canresult in an attacker tampering with XML + documents through. + * Added dom4j-CVE-2018-1000632.patch + ------------------------------------------------------------------- Tue Jul 10 12:41:17 UTC 2018 - fstrba@suse.com diff --git a/dom4j.spec b/dom4j.spec index 6aca867..f465d1d 100644 --- a/dom4j.spec +++ b/dom4j.spec @@ -37,6 +37,8 @@ Source2: http://repo1.maven.org/maven2/dom4j/dom4j/1.6.1/dom4j-1.6.1.pom Patch0: dom4j-1.6.1-bug1618750.patch Patch1: dom4j-sourcetarget.patch Patch2: dom4j-javadoc.patch +# PATCH-FIX-UPSTREAM bsc#1105443 CVE-2018-1000632 +Patch3: dom4j-CVE-2018-1000632.patch BuildRequires: ant >= 1.6.5 BuildRequires: ant-apache-resolver BuildRequires: ant-junit @@ -130,6 +132,7 @@ rm -f src/test/org/dom4j/io/StaxTest.java %patch0 -p1 -b .bug1618750 %patch1 -p1 -b .sourcetarget %patch2 -p1 -b .javadoc +%patch3 -p1 perl -pi -e 's/\r//g' LICENSE.txt docs/clover/*.css docs/style/*.css docs/xref/*.css docs/xref-test/*.css src/doc/style/*.css docs/benchmarks/xpath/*.java pushd lib @@ -187,7 +190,7 @@ mkdir -p %{buildroot}%{_datadir}/%{name}/classes/org/dom4j cp -pr xml %{buildroot}%{_datadir}/%{name} mkdir -p %{buildroot}%{_datadir}/%{name}/src cp -pr src/samples %{buildroot}%{_datadir}/%{name}/src -#cp -pr build/classes/org/dom4j/samples $RPM_BUILD_ROOT%{_datadir}/%{name}/classes/org/dom4j +#cp -pr build/classes/org/dom4j/samples $RPM_BUILD_ROOT%%{_datadir}/%%{name}/classes/org/dom4j install -m 0755 run.sh %{buildroot}%{_datadir}/%{name} %fdupes -s %{buildroot}%{_javadocdir}/%{name} %fdupes -s %{buildroot}%{_docdir}/%{name}-%{version}