Skip to content

Commit 61c40b3

Browse files
committed
Improve the security of XML parsers
Improve the security of XML parsers to prevent XML attacks like XML bombs and XXE attacks. Set default configuration of xml parsers to throw an exception when it find DTD in the XML and implement factory logic to give an opportunity for customer to override the way of creation xml parsers. DEVSIX-3270 Autoported commit. Original commit hash: [0310e5e63] Manual files: forms/src/main/java/com/itextpdf/forms/xfa/XfaForm.java forms/src/main/java/com/itextpdf/forms/xfdf/XfdfFileUtils.java forms/src/test/java/com/itextpdf/forms/xfa/SecurityTestXmlParserFactory.java forms/src/test/java/com/itextpdf/forms/xfa/XXEVulnerabilityTest.java forms/src/test/java/com/itextpdf/forms/xfdf/ExceptionTestXmlParserFactory.java forms/src/test/java/com/itextpdf/forms/xfdf/SecurityTestXmlParserFactory.java kernel/src/main/java/com/itextpdf/kernel/utils/DefaultSafeXmlParserFactory.java kernel/src/main/java/com/itextpdf/kernel/utils/IXmlParserFactory.java kernel/src/main/java/com/itextpdf/kernel/utils/XmlProcessorCreator.java kernel/src/main/java/com/itextpdf/kernel/utils/XmlUtils.java kernel/src/main/java/com/itextpdf/kernel/xmp/impl/XMPMetaParser.java kernel/src/test/java/com/itextpdf/kernel/utils/SecurityTestXmlParserFactory.java kernel/src/test/java/com/itextpdf/kernel/utils/XmlProcessorCreatorSecurityTest.java kernel/src/test/java/com/itextpdf/kernel/xmp/impl/SecurityTestXmlParserFactory.java kernel/src/test/java/com/itextpdf/kernel/xmp/impl/XMPMetaParserTest.java layout/src/main/java/com/itextpdf/layout/hyphenation/PatternParser.java pdftest/src/main/java/com/itextpdf/test/ExceptionTestUtil.java
1 parent 5a25e94 commit 61c40b3

File tree

27 files changed

+1170
-381
lines changed

27 files changed

+1170
-381
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
This file is part of the iText (R) project.
3+
Copyright (c) 1998-2021 iText Group NV
4+
Authors: iText Software.
5+
6+
This program is free software; you can redistribute it and/or modify
7+
it under the terms of the GNU Affero General Public License version 3
8+
as published by the Free Software Foundation with the addition of the
9+
following permission added to Section 15 as permitted in Section 7(a):
10+
FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
11+
ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
12+
OF THIRD PARTY RIGHTS
13+
14+
This program is distributed in the hope that it will be useful, but
15+
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16+
or FITNESS FOR A PARTICULAR PURPOSE.
17+
See the GNU Affero General Public License for more details.
18+
You should have received a copy of the GNU Affero General Public License
19+
along with this program; if not, see http://www.gnu.org/licenses or write to
20+
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21+
Boston, MA, 02110-1301 USA, or download the license from the following URL:
22+
http://itextpdf.com/terms-of-use/
23+
24+
The interactive user interfaces in modified source and object code versions
25+
of this program must display Appropriate Legal Notices, as required under
26+
Section 5 of the GNU Affero General Public License.
27+
28+
In accordance with Section 7(b) of the GNU Affero General Public License,
29+
a covered work must retain the producer line in every PDF that is created
30+
or manipulated using iText.
31+
32+
You can be released from the requirements of the license by purchasing
33+
a commercial license. Buying such a license is mandatory as soon as you
34+
develop commercial activities involving the iText software without
35+
disclosing the source code of your own applications.
36+
These activities include: offering paid services to customers as an ASP,
37+
serving PDFs on the fly in a web application, shipping iText with a closed
38+
source product.
39+
40+
For more information, please contact iText Software Corp. at this
41+
42+
*/
43+
44+
using System;
45+
using System.IO;
46+
using System.Xml;
47+
using iText.Kernel;
48+
using iText.Kernel.Utils;
49+
50+
namespace iText.Forms.Xfa
51+
{
52+
public class SecurityTestXmlParserFactory : IXmlParserFactory
53+
{
54+
private XmlReaderSettings xmlReaderSettings;
55+
56+
public SecurityTestXmlParserFactory()
57+
{
58+
xmlReaderSettings = new XmlReaderSettings();
59+
xmlReaderSettings.DtdProcessing = DtdProcessing.Parse;
60+
xmlReaderSettings.XmlResolver = new TestXmlResolver();
61+
}
62+
63+
public XmlReader CreateXmlReaderInstance(Stream stream, XmlParserContext inputContext)
64+
{
65+
return XmlReader.Create(stream, xmlReaderSettings);
66+
}
67+
68+
public XmlReader CreateXmlReaderInstance(TextReader textReader)
69+
{
70+
return XmlReader.Create(textReader, xmlReaderSettings);
71+
}
72+
73+
private class TestXmlResolver : XmlResolver
74+
{
75+
public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
76+
{
77+
throw new PdfException("Test message");
78+
}
79+
}
80+
}
81+
}

itext.tests/itext.forms.tests/itext/forms/xfa/XXEVulnerabilityTest.cs

Lines changed: 0 additions & 126 deletions
This file was deleted.
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*
2+
This file is part of the iText (R) project.
3+
Copyright (c) 1998-2021 iText Group NV
4+
Authors: iText Software.
5+
6+
This program is free software; you can redistribute it and/or modify
7+
it under the terms of the GNU Affero General Public License version 3
8+
as published by the Free Software Foundation with the addition of the
9+
following permission added to Section 15 as permitted in Section 7(a):
10+
FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
11+
ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
12+
OF THIRD PARTY RIGHTS
13+
14+
This program is distributed in the hope that it will be useful, but
15+
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16+
or FITNESS FOR A PARTICULAR PURPOSE.
17+
See the GNU Affero General Public License for more details.
18+
You should have received a copy of the GNU Affero General Public License
19+
along with this program; if not, see http://www.gnu.org/licenses or write to
20+
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21+
Boston, MA, 02110-1301 USA, or download the license from the following URL:
22+
http://itextpdf.com/terms-of-use/
23+
24+
The interactive user interfaces in modified source and object code versions
25+
of this program must display Appropriate Legal Notices, as required under
26+
Section 5 of the GNU Affero General Public License.
27+
28+
In accordance with Section 7(b) of the GNU Affero General Public License,
29+
a covered work must retain the producer line in every PDF that is created
30+
or manipulated using iText.
31+
32+
You can be released from the requirements of the license by purchasing
33+
a commercial license. Buying such a license is mandatory as soon as you
34+
develop commercial activities involving the iText software without
35+
disclosing the source code of your own applications.
36+
These activities include: offering paid services to customers as an ASP,
37+
serving PDFs on the fly in a web application, shipping iText with a closed
38+
source product.
39+
40+
For more information, please contact iText Software Corp. at this
41+
42+
*/
43+
using System;
44+
using System.IO;
45+
using iText.Forms;
46+
using iText.Kernel;
47+
using iText.Kernel.Pdf;
48+
using iText.Kernel.Utils;
49+
using iText.Test;
50+
51+
namespace iText.Forms.Xfa {
52+
public class XfaSecurityTest : ExtendedITextTest {
53+
private static readonly String SOURCE_FOLDER = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext
54+
.CurrentContext.TestDirectory) + "/resources/itext/forms/xfa/XfaSecurityTest/";
55+
56+
private static readonly String DTD_EXCEPTION_MESSAGE = ExceptionTestUtil.GetDoctypeIsDisallowedExceptionMessage
57+
();
58+
59+
private const String XFA_WITH_DTD_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!DOCTYPE foo>\n"
60+
+ "\n" + "<xdp:xdp xmlns:xdp=\"http://ns.adobe.com/xdp/\" timeStamp=\"2018-03-08T12:50:19Z\"\n" + " uuid=\"36ac5111-55c5-4172-b0c1-0cbd783e2fcf\">\n"
61+
+ "</xdp:xdp>\n";
62+
63+
[NUnit.Framework.SetUp]
64+
public virtual void ResetXmlParserFactoryToDefault() {
65+
XmlProcessorCreator.SetXmlParserFactory(new DefaultSafeXmlParserFactory());
66+
}
67+
68+
[NUnit.Framework.Test]
69+
public virtual void XfaExternalFileTest() {
70+
XfaSecurityExceptionTest(SOURCE_FOLDER + "xfaExternalFile.pdf");
71+
}
72+
73+
[NUnit.Framework.Test]
74+
public virtual void XfaExternalConnectionTest() {
75+
XfaSecurityExceptionTest(SOURCE_FOLDER + "xfaExternalConnection.pdf");
76+
}
77+
78+
[NUnit.Framework.Test]
79+
public virtual void XfaInternalEntityTest() {
80+
XfaSecurityExceptionTest(SOURCE_FOLDER + "xfaInternalEntity.pdf");
81+
}
82+
83+
[NUnit.Framework.Test]
84+
public virtual void XfaExternalFileCustomFactoryTest() {
85+
String inFileName = SOURCE_FOLDER + "xfaExternalFile.pdf";
86+
XmlProcessorCreator.SetXmlParserFactory(new SecurityTestXmlParserFactory());
87+
using (PdfDocument pdfDoc = new PdfDocument(new PdfReader(inFileName), new PdfWriter(new MemoryStream()))) {
88+
NUnit.Framework.Assert.That(() => {
89+
PdfAcroForm.GetAcroForm(pdfDoc, true);
90+
}
91+
, NUnit.Framework.Throws.InstanceOf<PdfException>().With.Message.EqualTo(ExceptionTestUtil.GetXxeTestMessage()))
92+
;
93+
}
94+
}
95+
96+
[NUnit.Framework.Test]
97+
public virtual void XfaExternalFileXfaFormTest() {
98+
String inFileName = SOURCE_FOLDER + "xfaExternalFile.pdf";
99+
using (PdfDocument pdfDoc = new PdfDocument(new PdfReader(inFileName))) {
100+
NUnit.Framework.Assert.That(() => {
101+
new XfaForm(pdfDoc);
102+
}
103+
, NUnit.Framework.Throws.InstanceOf<PdfException>().With.Message.EqualTo(DTD_EXCEPTION_MESSAGE))
104+
;
105+
}
106+
}
107+
108+
[NUnit.Framework.Test]
109+
public virtual void XfaWithDtdXfaFormTest() {
110+
using (Stream inputStream = new MemoryStream(XFA_WITH_DTD_XML.GetBytes(System.Text.Encoding.UTF8))) {
111+
NUnit.Framework.Assert.That(() => {
112+
new XfaForm(inputStream);
113+
}
114+
, NUnit.Framework.Throws.InstanceOf<PdfException>().With.Message.EqualTo(DTD_EXCEPTION_MESSAGE))
115+
;
116+
}
117+
}
118+
119+
[NUnit.Framework.Test]
120+
public virtual void FillXfaFormTest() {
121+
using (Stream inputStream = new MemoryStream(XFA_WITH_DTD_XML.GetBytes(System.Text.Encoding.UTF8))) {
122+
XfaForm form = new XfaForm();
123+
NUnit.Framework.Assert.That(() => {
124+
form.FillXfaForm(inputStream, true);
125+
}
126+
, NUnit.Framework.Throws.InstanceOf<PdfException>().With.Message.EqualTo(DTD_EXCEPTION_MESSAGE))
127+
;
128+
}
129+
}
130+
131+
private void XfaSecurityExceptionTest(String inputFileName) {
132+
using (PdfDocument pdfDoc = new PdfDocument(new PdfReader(inputFileName), new PdfWriter(new MemoryStream()
133+
))) {
134+
NUnit.Framework.Assert.That(() => {
135+
PdfAcroForm.GetAcroForm(pdfDoc, true);
136+
}
137+
, NUnit.Framework.Throws.InstanceOf<PdfException>().With.Message.EqualTo(DTD_EXCEPTION_MESSAGE))
138+
;
139+
}
140+
}
141+
}
142+
}

0 commit comments

Comments
 (0)