/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, version 2 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
*
* Copyright 2006 - 2016 Pentaho Corporation. All rights reserved.
*/
package org.pentaho.platform.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
import org.pentaho.platform.util.xml.w3c.XmlW3CHelper;
import org.w3c.dom.Document;
public class XmlW3CHelperTest {
@Test
public void testXmlW3CDTDsDisabling() throws IOException {
String domString =
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
+ "<!DOCTYPE foo [<!ENTITY xxe SYSTEM \"file:///etc/passwd\" >]>\n"
+ "<root xmlns=\"http://www.pentaho.com\">\n" + "</root>";
Document doc = XmlW3CHelper.getDomFromString( domString );
// should prevent XXE attack
// factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)
// should be set
assertNull( doc );
}
/**
* attack example is from https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing
*
* @throws IOException
*/
@Test
public void testXmlW3CLocalResourceAccessing() throws IOException {
String domString =
"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" + " <!DOCTYPE foo [ \n" + " <!ELEMENT foo ANY >\n"
+ " <!ENTITY xxe SYSTEM \"file:///dev/random\" >]><foo>&xxe;</foo>";
Document doc = XmlW3CHelper.getDomFromString( domString );
// should prevent XXE attack
// factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)
// should be set
assertNull( doc );
}
/**
* attack example is from https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing
*
* @throws IOException
*/
@Test
public void testXmlW3CDisclosingEtcPass() throws IOException {
String domString =
" <?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" + " <!DOCTYPE foo [ \n" + " <!ELEMENT foo ANY >\n"
+ " <!ENTITY xxe SYSTEM \"file:///etc/passwd\" >]><foo>&xxe;</foo>";
Document doc = XmlW3CHelper.getDomFromString( domString );
assertNull( doc );
}
/**
* attack example is from https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing
*
* @throws IOException
*/
@Test
public void testXmlW3CDisclosingEtcShadow() throws IOException {
String domString =
" <?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" + " <!DOCTYPE foo [ \n" + " <!ELEMENT foo ANY >\n"
+ " <!ENTITY xxe SYSTEM \"file:///etc/shadow\" >]><foo>&xxe;</foo>";
Document doc = XmlW3CHelper.getDomFromString( domString );
assertNull( doc );
}
/**
* attack example is from https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing
*
* @throws IOException
*/
@Test
public void testXmlW3CDisclosingCIni() throws IOException {
String domString =
" <?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" + " <!DOCTYPE foo [ \n" + " <!ELEMENT foo ANY >\n"
+ " <!ENTITY xxe SYSTEM \"file:///c:/boot.ini\" >]><foo>&xxe;</foo>";
Document doc = XmlW3CHelper.getDomFromString( domString );
assertNull( doc );
}
/**
* attack example is from https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing
*
* @throws IOException
*/
@Test
public void testXmlW3CDisclosingHttp() throws IOException {
String domString =
" <?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" + " <!DOCTYPE foo [ \n" + " <!ELEMENT foo ANY >\n"
+ " <!ENTITY xxe SYSTEM \"http://www.attacker.com/text.txt\" >]><foo>&xxe;</foo>";
Document doc = XmlW3CHelper.getDomFromString( domString );
assertNull( doc );
}
/**
* attack example is from https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing
*
* @throws IOException
*/
@Test
public void testXmlW3CDisclosingEtcPasswd() throws IOException {
String domString =
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
+ "<!DOCTYPE foo [<!ENTITY xxe SYSTEM \"file:///etc/passwd\" >]>\n"
+ "<root xmlns=\"http://www.pentaho.com\">\n" + "</root>";
Document doc = XmlW3CHelper.getDomFromString( domString );
assertNull( doc );
}
@Test
public void testValidXmlW3C() throws IOException {
String domString = "<root><subroot>this is sub root</subroot></root>";
Document doc = XmlW3CHelper.getDomFromString( domString );
assertNotNull( doc );
}
@Test
public void testNotValidXmlW3C() throws IOException {
String domString = "<root>this is sub root</subroot></root>";
Document doc = XmlW3CHelper.getDomFromString( domString );
assertNull( doc );
}
@Test
public void testXmlW3C() throws IOException {
String path = "src/test/resources/solution/test/xml/query_without_connection.xaction";
byte[] encoded = IOUtils.toByteArray( new FileInputStream( path ) );
String sourceXml = new String( encoded );
Document doc = XmlW3CHelper.getDomFromString( sourceXml );
assertNotNull( doc );
}
@Test
public void testXmlW3CError() {
try {
XmlW3CHelper.getDomFromString( null );
fail( "This should have thrown an exception" );
} catch ( IllegalArgumentException e ) {
assertEquals( "The source string can not be null", e.getMessage() );
}
}
@Test( timeout = 2000 )
public void shouldNotFailAndReturnNullWhenMaliciousXmlIsGiven() throws Exception {
assertNull( XmlW3CHelper.getDomFromString( XmlTestConstants.MALICIOUS_XML ) );
}
@Test
public void shouldNotFailAndReturnNotNullWhenLegalXmlIsGiven() throws Exception {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<element>" + "</element>";
assertNotNull( XmlW3CHelper.getDomFromString( xml ) );
}
}