Prevent XXE fortify issue for TrasnformerFactory - java

I need to fix XXE issue .I am using transformerfactory in code.
Found below fix but i can not see ACCESS_EXTERNAL_DTD attribute in my code.Reason which i got is below code will work for Java7 however i am using Java 6 .Can some one please suggest some other fix
To protect a Java TransformerFactory from XXE, do this:
TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");

I was in to same situation and it is difficult to resolve without updating Java version.
Following is code change that was able to pass fortify scan with same results.
Instead of using TransformerFactory use following code:
DOMImplementationLS domImplementation = (DOMImplementationLS) doc.getImplementation();
LSSerializer lsSerializer = domImplementation.createLSSerializer();
LSOutput lsOutput = domImplementation.createLSOutput( );
lsOutput.setEncoding("UTF-8");
StringWriter stringWriter=new StringWriter();
lsOutput.setCharacterStream(stringWriter);
lsSerializer.write(doc,lsOutput);
return stringWriter.toString();
For reference please review Is there a more elegant way to convert an XML Document to a String in Java than this code?.
And

Related

Convert org.w3c.dom.Document to File file

I have a xml file as object in Java as org.w3c.dom.Document doc and I want to convert this into File file. How can I convert the type Document to File?
thanks
I want to add metadata elements in an existing xml file (standard dita) with type File.
I know a way to add elements to the file, but then I have to convert the file to a org.w3c.dom.Document. I did that with the method loadXML:
private Document loadXML(File f) throws Exception{
DocumentBuilder b = DocumentBuilderFactory.newInstance().newDocumentBuilder();
return builder.parse(f);
After that I change the org.w3c.dom.Document, then I want to continue with the flow of the program and I have to convert the Document doc back to a File file.
What is a efficient way to do that? Or what is a better solution to get some elements in a xml File without converting it?
You can use a Transformer class to output the entire XML content to a File, as showed below:
Document doc =...
// write the content into xml file
DOMSource source = new DOMSource(doc);
FileWriter writer = new FileWriter(new File("/tmp/output.xml"));
StreamResult result = new StreamResult(writer);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(source, result);
With JDK 1.8.0 a short way is to use the built-in XMLSerializer (which was introduced with JDK 1.4 as a fork of Apache Xerces)
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
Document doc = //use your method loadXML(File f)
//change Document
java.io.Writer writer = new java.io.FileWriter("MyOutput.xml");
XMLSerializer xml = new XMLSerializer(writer, null);
xml.serialize(doc);
Use an object of type OutputFormat to configure output, for example like this:
OutputFormat format = new OutputFormat(Method.XML, StandardCharsets.UTF_8.toString(), true);
format.setIndent(4);
format.setLineWidth(80);
format.setPreserveEmptyAttributes(true);
format.setPreserveSpace(true);
XMLSerializer xml = new XMLSerializer(writer, format);
Note that the classes are from com.sun.* package which is not documented and therefore generally is not seen as the preferred way of doing things. However, with javax.xml.transform.OutputKeys you cannot specify the amount of indentation or line width for example. So, if this is important then this solution should help.

Sending XML payloads with HTTP POST request using HttpClient--Java

So I've been doing a lot of looking on both stackoverflow and google in general to try and answer my following question, but I have been unable to find anything that can help me to get this work 100%. I'm pretty sure I have everything except a SMALL error correct, but obviously you guys probably have suggestions anyway, so go for it!
And, here we go: I've been using HTTPClient to test an API on a few different environments, and I got HTTPPost methods to accept JSON payloads but now I'm trying to send payloads using XML and I'm running into some issues. It seems that the XML string that I'm creating (in the code below) is correct... so I'm stumped as to why this isn't working. ALSO: got most of the DOM code from the internet (to build up the XML payload) so feel free to bring that into question as well...
My code is the following:
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element subscription = doc.createElement("subscription");
doc.appendChild(subscription);
subscription.setAttribute("email", "patricia#test.intershop.de");
etc....
etc....
etc....
etc....
DOMSource domSource = new DomSource(doc);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(domSource, result);
String XMLpayload = writer.toString();
[name of my HttpRequest].setEntity(new StringEntity(XMLpayload));
[name of my HttpResponse] = client.execute(request);
now... I'm looking to achieve the payload seen BELOW:
<subscription>
<email>patricia#test.intershop.de</email>
<firstName>Patricia</firstName>
<lastName>Miller</lastName>
<title>Ms.</title>
<gender>Female</gender>
</subscription>
When I print out the payload that I am sending currently it looks like the following:
?xml version="1.0" encoding="UTF-8" standalone="no"? subscription email="patricia#test.intershop.de" firstName="Patricia" gender="Female" lastName="Miller" title="Ms."/
(NOTE: I REMOVED THE < AND > BRACKETS. THEY APPEAR WHERE THEY SHOULD!)
But, I'm receiving a 400 error. Any ideas here? I know I have the proper headers, the URL is correct, etc. It's absolutely something with what I'm doing with the payload. Any thoughts would be greatly appreciated!!
Best!
In your expected payload, 'email','firstname',etc.. are child elements of Subscription element. As per the code, they are added as attributes of your 'subscription' element. If you need 'email','firstname',etc.. as child elements, you should use appendChild() instead of setAttribute().
Element email = doc.createElement("email");
email.appendChild(document.createTextNode("patricia#test.intershop.de"));
subscription.appendChild(email);

Transforming a StAX Source in Java

I have some code like:
XMLInputFactory xif = XMLInputFactory.newInstance()
TransformerFactory tf = TransformerFactory.newInstance("org.apache.xalan.processor.TransformerFactoryImpl", null)
Transformer t = tf.newTransformer()
DOMResult result = new DOMResult()
t.transform(new StAXSource(reader), result)
Which produces the following error:
Caught: javax.xml.transform.TransformerException: Can't transform a Source of type javax.xml.transform.stax.StAXSource
The reader object is of type com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl
So I was stupidly trying the wrong thing. This fixed it:
System.setProperty("javax.xml.transform.TransformerFactory",
"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
I stumbled upon Xml Transformer give me an error when trying to transform a StaxSource into a StreamResult, while looking to solve the very same issue as you.
The answer provided there seems to be working fine for me, i.e. use:
TransformerFactory.newDefaultInstance();
Instead of:
XMLInputFactory.newInstance()

XSL validation while transformation

I'm using the following piece of code to do XSL transformation :
Source source = new StreamSource(new StringReader(request.toString()));
Source xsl = new StreamSource(XSLPath);
StringWriter destination = new StringWriter();
Result result = new StreamResult(destination);
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer;
transformer = transFactory.newTransformer(xsl);
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(source, result);
The XSLPath variable passes the file location to the .xsl file.
I need to know whether the transFactory.newTransformer(xsl) does any kind of internal validation first of the xsl file itself. If not, then is there a way we can do validation of the xsl file, before performing the transformation?
I have a code to validate an xsd file, but, I believe the same code wouldn't work for an xsl. I still tried that as well, but it always throw some or the other SAXException about Non-white spaces not being allowed on most of the lines.
Yes, the first thing the XSLT processor does is to validate and compile the stylesheet. (Why did you have to ask? Just introduce an error, and see what happens!)
You might find it useful to set an ErrorListener to make sure that your application can capture the error messages.
If you are using the same stylesheet repeatedly for many transformations, it is much more efficient to use newTemplates() to create a Templates object so you only do the validation/compilation once. Think of the Templates object as the compiled stylesheet.

Control order of XML attributes in outputed file in Java

How do I control the order that the XML attributes are listed within the output file?
It seems by default they are getting alphabetized, which the program I'm sending this XML to apparently isn't handling.
e.g. I want zzzz to show first, then bbbbb in the following code.
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element root = doc.createElement("requests");
doc.appendChild(root);
root.appendChild(request);
root.setAttribute("zzzzzz", "My z value");
root.setAttribute("bbbbbbb", "My b value");
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(file));
transformer.transform(source, result);
The order of attributes is defined to be insignificant in XML: no conformant XML application should produce results that depend on the order in which attributes appear. Therefore, serializers (code that produces lexical XML as output) will usually give you no control over the order.
Now, it would sometimes be nice to have that control for cosmetic reasons, because XML is designed to be human-readable. So there's a valid reason for wanting the feature. But the fact is, I know of no serializer that offers it.
I had the same issue when I used XML DOM API for writing file. To resolve the problem I had to use XMLStreamWriter. Attributes appear in a xml file in the order you write it using XMLStreamWriter.
XML Canonicalisation results in a consistent attribute ordering, primarily to allow one to check a signature over some or all of the XML, though there are other potential uses. This may suit your purposes.
If you don't want to use another framework just for a custom attribute order you can simply add an order identifier to the attributes.
<someElement a__price="32" b__amount="3"/>
After the XML serializer is done post process the raw XML like so:
public static String removeAttributeOrderIdentifiers(String xml) {
return xml.replaceAll(
" [a-z]__(.+?=\")",
"$1"
);
}
And you will get:
<someElement amount="3" price="32"/>

Categories

Resources