From a961d9a9af5f457a12838aa9e28db385b051603d Mon Sep 17 00:00:00 2001 From: Jonathan Gallimore Date: Tue, 6 Aug 2019 10:36:16 +0100 Subject: [PATCH] Issue #467 provide XML parser with a strong configuration to prevent XXE attacks --- .../xml/XMLSchedulingDataProcessor.java | 9 ++++++- .../xml/XMLSchedulingDataProcessorTest.java | 26 +++++++++++++++++++ .../org/quartz/xml/bad-job-config.xml | 15 +++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100755 quartz-core/src/test/resources/org/quartz/xml/bad-job-config.xml diff --git a/quartz-core/src/main/java/org/quartz/xml/XMLSchedulingDataProcessor.java b/quartz-core/src/main/java/org/quartz/xml/XMLSchedulingDataProcessor.java index 0a074ebb..506651a8 100644 --- a/quartz-core/src/main/java/org/quartz/xml/XMLSchedulingDataProcessor.java +++ b/quartz-core/src/main/java/org/quartz/xml/XMLSchedulingDataProcessor.java @@ -173,7 +173,14 @@ protected void initDocumentParser() throws ParserConfigurationException { docBuilderFactory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema"); docBuilderFactory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource", resolveSchemaSource()); - + + docBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + docBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + docBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false); + docBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + docBuilderFactory.setXIncludeAware(false); + docBuilderFactory.setExpandEntityReferences(false); + docBuilder = docBuilderFactory.newDocumentBuilder(); docBuilder.setErrorHandler(this); diff --git a/quartz-core/src/test/java/org/quartz/xml/XMLSchedulingDataProcessorTest.java b/quartz-core/src/test/java/org/quartz/xml/XMLSchedulingDataProcessorTest.java index 4aeb6464..ae8fc298 100755 --- a/quartz-core/src/test/java/org/quartz/xml/XMLSchedulingDataProcessorTest.java +++ b/quartz-core/src/test/java/org/quartz/xml/XMLSchedulingDataProcessorTest.java @@ -30,6 +30,7 @@ import org.quartz.simpl.SimpleThreadPool; import org.quartz.spi.ClassLoadHelper; import org.quartz.utils.DBConnectionManager; +import org.xml.sax.SAXParseException; /** * Unit test for XMLSchedulingDataProcessor. @@ -204,6 +205,31 @@ public void testQTZ327SimpleTriggerNoRepeat() throws Exception { } } + public void testXmlParserConfiguration() throws Exception { + Scheduler scheduler = null; + try { + StdSchedulerFactory factory = new StdSchedulerFactory("org/quartz/xml/quartz-test.properties"); + scheduler = factory.getScheduler(); + ClassLoadHelper clhelper = new CascadingClassLoadHelper(); + clhelper.initialize(); + XMLSchedulingDataProcessor processor = new XMLSchedulingDataProcessor(clhelper); + processor.processFileAndScheduleJobs("org/quartz/xml/bad-job-config.xml", scheduler); + + + final JobKey jobKey = scheduler.getJobKeys(GroupMatcher.jobGroupEquals("native")).iterator().next(); + final JobDetail jobDetail = scheduler.getJobDetail(jobKey); + final String description = jobDetail.getDescription(); + + + fail("Expected parser configuration to block DOCTYPE. The following was injected into the job description field: " + description); + } catch (SAXParseException e) { + assertTrue(e.getMessage().contains("DOCTYPE is disallowed")); + } finally { + if (scheduler != null) + scheduler.shutdown(); + } + } + private Date dateOfGMT_UTC(int hour, int minute, int second, int dayOfMonth, int month, int year) { final GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT")); calendar.set(year, month, dayOfMonth, hour, minute, second); diff --git a/quartz-core/src/test/resources/org/quartz/xml/bad-job-config.xml b/quartz-core/src/test/resources/org/quartz/xml/bad-job-config.xml new file mode 100755 index 00000000..9aeb5673 --- /dev/null +++ b/quartz-core/src/test/resources/org/quartz/xml/bad-job-config.xml @@ -0,0 +1,15 @@ + + + ]> + + + + xxe + native + &xxe; + org.quartz.xml.XMLSchedulingDataProcessorTest$MyJob + true + false + + + \ No newline at end of file