From 6f5429baf38ae268128dbb941b5c5bfc1c06a46c Mon Sep 17 00:00:00 2001 From: Julian Reschke Date: Fri, 26 Feb 2016 12:51:35 +0000 Subject: [PATCH] JCR-3950: fix XSS vulnerability in DirListingExportHandler (ported to 2.0) git-svn-id: https://svn.apache.org/repos/asf/jackrabbit/branches/2.0@1732470 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/jackrabbit/util/Text.java | 21 +++++++++-- .../org/apache/jackrabbit/util/TextTest.java | 7 ++++ .../server/io/DirListingExportHandler.java | 36 +++++++++---------- 3 files changed, 43 insertions(+), 21 deletions(-) diff --git a/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/Text.java b/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/Text.java index 5787cc5e403..bdce022bfa1 100644 --- a/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/Text.java +++ b/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/Text.java @@ -210,13 +210,28 @@ public static String replace(String text, String oldString, String newString) { } /** - * Replaces illegal XML characters in the given string by their corresponding - * predefined entity references. + * Replaces XML characters in the given string that might need escaping + * as XML text or attribute * * @param text text to be escaped * @return a string */ public static String encodeIllegalXMLCharacters(String text) { + return encodeMarkupCharacters(text, false); + } + + /** + * Replaces HTML characters in the given string that might need escaping + * as HTML text or attribute + * + * @param text text to be escaped + * @return a string + */ + public static String encodeIllegalHTMLCharacters(String text) { + return encodeMarkupCharacters(text, true); + } + + private static String encodeMarkupCharacters(String text, boolean isHtml) { if (text == null) { throw new IllegalArgumentException("null argument"); } @@ -251,7 +266,7 @@ public static String encodeIllegalXMLCharacters(String text) { } else if (ch == '"') { buf.append("""); } else if (ch == '\'') { - buf.append("'"); + buf.append(isHtml ? "'" : "'"); } } if (buf == null) { diff --git a/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/TextTest.java b/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/TextTest.java index 1deba9beed7..60dc4f184d4 100644 --- a/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/TextTest.java +++ b/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/TextTest.java @@ -189,4 +189,11 @@ public void testEscapeIllegalJcrChars() throws Exception { assertEquals("local'name", Text.escapeIllegalJcrChars("local'name")); assertEquals("local\"name", Text.escapeIllegalJcrChars("local\"name")); } + public void testEscapeXML() { + assertEquals("&<>'"", Text.encodeIllegalXMLCharacters("&<>'\"")); + } + + public void testEscapeHTML() { + assertEquals("&<>'"", Text.encodeIllegalHTMLCharacters("&<>'\"")); + } } diff --git a/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DirListingExportHandler.java b/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DirListingExportHandler.java index 3c5a6994e6f..5e70d5a2334 100644 --- a/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DirListingExportHandler.java +++ b/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DirListingExportHandler.java @@ -145,14 +145,14 @@ public boolean exportContent(ExportContext context, boolean isCollection) throws String repURL = rep.getDescriptor(Repository.REP_VENDOR_URL_DESC); String repVersion = rep.getDescriptor(Repository.REP_VERSION_DESC); writer.print(""); - writer.print(repName); + writer.print(Text.encodeIllegalHTMLCharacters(repName)); writer.print(" "); - writer.print(repVersion); + writer.print(Text.encodeIllegalHTMLCharacters(repVersion)); writer.print(" "); - writer.print(item.getPath()); + writer.print(Text.encodeIllegalHTMLCharacters(item.getPath())); writer.print(""); writer.print("

"); - writer.print(item.getPath()); + writer.print(Text.encodeIllegalHTMLCharacters(item.getPath())); writer.print("


Powered by "); - writer.print(repName); + writer.print(Text.encodeIllegalHTMLCharacters(repName)); writer.print(" version "); - writer.print(repVersion); + writer.print(Text.encodeIllegalHTMLCharacters(repVersion)); writer.print(""); } catch (RepositoryException e) { // should not occur @@ -209,14 +209,14 @@ public boolean exportContent(ExportContext context, DavResource resource) throws String repURL = rep.getDescriptor(Repository.REP_VENDOR_URL_DESC); String repVersion = rep.getDescriptor(Repository.REP_VERSION_DESC); writer.print(""); - writer.print(repName); + writer.print(Text.encodeIllegalHTMLCharacters(repName)); writer.print(" "); - writer.print(repVersion); + writer.print(Text.encodeIllegalHTMLCharacters(repVersion)); writer.print(" "); - writer.print(resource.getResourcePath()); + writer.print(Text.encodeIllegalHTMLCharacters(resource.getResourcePath())); writer.print(""); writer.print("

"); - writer.print(resource.getResourcePath()); + writer.print(Text.encodeIllegalHTMLCharacters(resource.getResourcePath())); writer.print("


Powered by "); - writer.print(repName); + writer.print(Text.encodeIllegalHTMLCharacters(repName)); writer.print(" version "); - writer.print(repVersion); + writer.print(Text.encodeIllegalHTMLCharacters(repVersion)); writer.print(""); } catch (RepositoryException e) { // should not occur