Here is the code snippet for a DomParser which I am using, The DomParser which I am using is of Oracle.
import oracle.xml.parser.v2.DOMParser;
DOMParser domParser = new DOMParser();
domParser.parse(new StringReader(xmlPayload));
Document doc = domParser.getDocument();
doc.getDocumentElement().normalize();
System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
NodeList nList = doc.getElementsByTagName("student");
Recently our Security team has raised a concern that the above DOM parser is vulnerable to security attack and has come up with a recommendation on setting two attributes
domParser.setAttribute("RESOLVE_ENTITY_DEFAULT", true);
domParser.setAttribute("DEFAULT_ENTITY_EXPANSION_DEPTH", 150);
But on setting these attributes, I am getting the below error,
Exception in thread "main" java.lang.IllegalArgumentException
at oracle.xml.parser.v2.XMLParser.setAttribute(XMLParser.java:870)
at oracle.xml.parser.v2.DOMParser.setAttribute(DOMParser.java:538)
at DomParserExample.main(DomParserExample.java:20)
kindly let me know how can I prevent XML Entity Expansion injection and XXE attacks. I have tried looking into OWASP XEE Cheat Sheet and browsed through various questions and answers for XXE attack, but could not find a solution for this.
try this
domParser.setAttribute(XMLParser.RESOLVE_ENTITY_DEFAULT, true);
domParser.setAttribute(XMLParser.DEFAULT_ENTITY_EXPANSION_DEPTH, 150);
The proper way to handle XXE in Oracle DOMParser is documented here.
https://docs.oracle.com/en/database/oracle/oracle-database/18/adxdk/security-considerations-oracle-xml-developers-kit.html#GUID-45303542-41DE-4455-93B3-854A826EF8BB
// Extend oracle.xml.parser.v2.XMLParser
DOMParser domParser = new DOMParser();
// Do not expand entity references
domParser.setAttribute(DOMParser.EXPAND_ENTITYREF, false);
// dtdObj is an instance of oracle.xml.parser.v2.DTD
domParser.setAttribute(DOMParser.DTD_OBJECT, dtdObj);
// Do not allow more than 11 levels of entity expansion
domParser.setAttribute(DOMParser.ENTITY_EXPANSION_DEPTH, 12);
what will be the maven dependencies version to use XMLParser and DOMParser to get resolve the fortify fix for DOM Parser.
Related
I'm working with XML for the first time, trying to generate XML to send over to a client and I'm having a hell of a time doing it. Whenever I try to pass a URL, I get an INVALID_CHARACTER_ERR and nothing I've tried so far works.
I tried using replacements like & #123; and so on for the curly braces, and tried escaping everything that wasn't a letter, resulting in the abomination under my code. It seems to throw the error if I have any kind of character that isn't a letter. Another thing that I noticed is that the document's InputEncoding is null, but that seems to be because I'm creating it in code, does that mean that it actually doesn't have an encoding type? I haven't been able to find an easy way to set it either.
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document orders = dBuilder.newDocument();
Element order = orders.createElement("{https://secure.targeturl.com/foo/bar}tagpayload");
Element tOrder = orders.createElement("tagorder");
order.appendChild(tOrder);
Element header = orders.createElement("orderheader");
tOrder.appendChild(header);
Element billto = orders.createElement("billto");
header.appendChild(billto); ```
``` "& #123;https& #58;& #47;& #47;secure& #46;targeturl& #46;com/foo& #47;bar& #125;tagpayload" ```
This is not the correct way to create a namespaced element:
Element order = orders.createElement("{https://secure.targeturl.com/foo/bar}tagpayload");
Instead, use the createElementNS method:
Element order = orders.createElementNS("https://secure.targeturl.com/foo/bar", "tagpayload");
You are seeing an exception because { is not a legal character in an XML element name. createElement has no awareness of namespaces or the “{uri}name” namespace notation.
I'm parsing a XML string to generate nodes. Sometimes the tag comes with a namespace & sometimes without namespace. How can I ignore this and
I tried in the following way, but it didnt work.
//NodeList idDetails = doc.getDocumentElement().getElementsByTagNameNS("*", "details");
NodeList idDetails = doc.getElementsByTagName("ns2:details");
Any ideas on how to do it?
First one shall work.
NodeList nodes = doc.getDocumentElement().getElementsByTagNameNS("*", str);
But you have to also call DocumentBuilderFactory.setNamespaceAware(true) for this to work, otherwise namespaces will not be detected.
I've been renaming xml nodes using the document.renameNode() method:
Document document = loadXml(xml);
NodeList list = document.getElementsByTagName("Entry1");
for (int i=0; i < list.getLength();)
{
document.renameNode(list.item(i), "", "Entry");
}
However, the Java version I'm deploying to (1.5.0_09-b03) doesn't support the renameNode method. Any ideas how I could write the above in a way that's compatible with this version of Java?
Thanks in advance.
Hmm... the Java 1.5 API doc says renameNode() is supported. Are you sure you don't have access to that method? Are you using org.w3c.dom classes?
As mentioned in my comment I was able to do a replaceAll on the string replacing "Entry1" with "Entry" and then loading that as xml.
Thanks.
TASK : I have an existing xml document (UTF-8) which uses xml namespaces and xml schema. I need to parse to a particular element, append content (that also needs to use xml namespace prefixes) to this element and then write out the Document again.
which is the best XML parser library that I should be using for this TASK ?
I've seen a previous thread (Best XML parser for Java) but was not sure if dom4j or JDOM is any good for namespaces/xmlSchema and good support for UTF-8 characters.
Some parsers that seems like a task for
JDom
Dom4J
XOM
WoodStock
Any idea which one is the best ? :-) I use JDK 6 and would prefer NOT to use the built-in SAX/DOM facilities to do this job because that requires me to write too much code.
Would help to have some examples of doing such a task.
Using JDOM, taking an InputStream and making it a Document:
InputStream inputStream = (InputStream)httpURLConnection.getContent();
DocumentBuilderFactory docbf = DocumentBuilderFactory.newInstance();
docbf.setNamespaceAware(true);
DocumentBuilder docbuilder = docbf.newDocumentBuilder();
Document document = docbuilder.parse(inputStream, baseUrl);
At that point, you have the XML in a Java object. Done. Easy.
You can either use the document object and the Java API to just walk through it, or also use XPath, which I find easier (once I learned it).
Build an XPath object, which takes a bit:
public static XPath buildXPath() {
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
xpath.setNamespaceContext(new AtomNamespaceContext());
return xpath;
}
public class AtomNamespaceContext implements NamespaceContext {
public String getNamespaceURI(String prefix) {
if (prefix == null)
throw new NullPointerException("Null prefix");
else if ("a".equals(prefix))
return "http://www.w3.org/2005/Atom";
else if ("app".equals(prefix))
return "http://www.w3.org/2007/app";
else if ("os".equals(prefix))
return "http://a9.com/-/spec/opensearch/1.1/";
else if ("x".equals(prefix))
return "http://www.w3.org/1999/xhtml";
else if ("xml".equals(prefix))
return XMLConstants.XML_NS_URI;
return XMLConstants.NULL_NS_URI;
}
// This method isn't necessary for XPath processing.
public String getPrefix(String uri) {
throw new UnsupportedOperationException();
}
// This method isn't necessary for XPath processing either.
public Iterator getPrefixes(String uri) {
throw new UnsupportedOperationException();
}
}
Then just use it, which (thankfully) doesn't take much time at all:
return Integer.parseInt(xpath.evaluate("/a:feed/os:totalResults/text()", document));
Use XSLT. Seriously. This is a perfect job for it. Just use a copy template to copy everything as is except for the place where you need to add more xml. You can even add the XML by actually writing XML instead of DOM manipulation.
This is the copy template:
<xsl:template match="node() | #*">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
I know a lot of people hate XSLT, but this is a task where it would really shine and take almost no code. Also, you could just use what's in the JDK.
Since writing too much code is the main issue for you, you might want to consider jOOX:
http://code.google.com/p/joox/
I have created jOOX to be a port of jQuery to Java. The underlying technology is Java's standard DOM. Some sample code:
// Find the order at index for and add an element "paid"
$(document).find("orders").children().eq(4)
.append("<paid>true</paid>");
// Find those orders that are paid and flag them as "settled"
$(document).find("orders").children().find("paid")
.after("<settled>true</settled>");
// Add a complex element
$(document).find("orders").append(
$("order", $("date", "2011-08-14"),
$("amount", "155"),
$("paid", "false"),
$("settled", "false")).attr("id", "13");
Note: Namespaces are not yet explicitly supported, but you can work around that
It sounds like you can write an xslt style sheet to do what you want.
I'll point out now, that I'm new to using saxon, and I've tried following the docs and examples in the package, but I'm just not having luck with this problem.
Basically, I'm trying to do some xml processing in java using saxon v8. In order to get something working, I took one of the sample files included in the package and modified to my needs. It works so long as I'm not using namespaces, and that is my question. How can I get around the namespace problem? I don't really care to use it, but it exists in my xml, so I either have to use it or ignore it. Either solution is fine.
Anyway, here is my starter code. It doesn't do anything but take an xpath query try to use it against the hard coded xml doc.
public static void main(String[] args) {
String query = args[0];
File XMLStream=null;
String xmlFileName="doc.xml";
OutputStream destStream=System.out;
XQueryExpression exp=null;
Configuration C=new Configuration();
C.setSchemaValidation(false);
C.setValidation(false);
StaticQueryContext SQC=new StaticQueryContext(C);
DynamicQueryContext DQC=new DynamicQueryContext(C);
QueryProcessor processor = new QueryProcessor(SQC);
Properties props=new Properties();
try{
exp=processor.compileQuery(query);
XMLStream=new File(xmlFileName);
InputSource XMLSource=new InputSource(XMLStream.toURI().toString());
SAXSource SAXs=new SAXSource(XMLSource);
DocumentInfo DI=SQC.buildDocument(SAXs);
DQC.setContextNode(DI);
SequenceIterator iter = exp.iterator(DQC);
while(true){
Item i = iter.next();
if(i != null){
System.out.println(i.getStringValue());
}
else break;
}
}
catch (Exception e){
System.err.println(e.getMessage());
}
}
An example XML file is here...
<?xml version="1.0"?>
<ns1:animal xmlns:ns1="http://my.catservice.org/">
<cat>
<catId>8889</catId>
<fedStatus>true</fedStatus>
</cat>
</ns1:animal>
If I run this with a query including the namespace, I get an error. For example:
/ns1:animal/cat/ gives the error: "Prefix ns1 has not been declared".
If I remove the ns1: from the query, it gives me nothing. If I doctor the xml to remove the "ns1:" prepended to "animal" I can run the query /animal/cat/ with success.
Any help would be greatly appreciated. Thanks.
Error message correctly points out that your xpath expression does not indicate what namespace prefix "ns1" means (binds to). Just because document to operate on happens to use binding for "ns1" does not mean it is what should be used: this because in XML, it's the namespace URI that matters, and prefixes are just convenient shortcuts to the real thing.
So: how do you define the binding? There are 2 generic ways; either provide a context that can resolve the prefix, or embed actual URI within XPath expression.
Regarding the first approach, this email from Saxon author mentions JAXP method XPath.setNamespaceContext(), similarly, Jaxen XPath processor FAQ has some sample code that could help
That's not very convenient, as you have to implement NamespaceContext, but once you have an implementation you'll be set.
So the notation approach... let's see: Top Ten Tips to Using XPath and XPointer shows this example:
to match element declared with namespace like:
xmlns:book="http://my.example.org/namespaces/book"
you use XPath name like:
{http://my.example.org/namespaces/book}section
which hopefully is understood by Saxon (or Jaxen).
Finally, I would recommend upgrading to Saxon9 if possible, if you have any trouble using one of above solutions.
If you want to have something working out of the box, you can check out embedding-xquery-in-java. There's github project, which uses Saxon to evaluate some sample XQuery expressions.
Regards