I have a project scanner complaining with a Warning about
XmlDataDocument serializedContent = new XmlDataDocument();
and
serializedContent.Load(objStream);
and giving this recommendation to use:
The best way to prevent XXE attacks is to disable XML entity
resolution by disabling inline DD setting DtdProcessing to
DtdProcessing.Prohibit or by disabling XML Entity resolution setting
the XmlReaderSettings.XmlResolver property to null:
XmlReaderSettings settings = new XmlReaderSettings () ;
settings.DtdProcessing = DtdProcessing. Prohibit;
settings.XmlResolver = null;
XmlReader reader = XmlReader.Create(stream, settings);
Here's the code that I have:
[Serializable]
...
XmlTextWriter objSerializer = new XmlSerializer(...);
MemoryStream objStream = new MemoryStream();
XmlTextWriter objwriter = null;
XmlDataDocument objSerializedContent = new XmlDataDocument(); // it complains here
objWriter = new XmlTextWriter (objStream, System.Text.Encoding.UTF8);
...
objSerializedContent.Load(objStream); // it complains here
How can I apply that scan recommendation using reader if I'm using XmlTextWriter & XmlDataDocument?
If you use
XmlReaderSettings settings = new XmlReaderSettings () ;
settings.DtdProcessing = DtdProcessing. Prohibit;
settings.XmlResolver = null;
and
using (XmlReader xr = XmlReader.Create(objStream, settings)) {
objSerializedContent.Load(xr);
}
instead of objSerializedContent.Load(objStream) your code uses an XmlReader over the MemoryStream where the XmlReader has the settings you want or need.
Related
I have to transform .xml two times with different .xslt files and I know how to transform it once, but don't have idea, how to repeat it, because when I my output was something like html string and i changed my code, by using XmlWriter instead of StringWriter (commented), but it generates an empty Xml so it can't be transferred again.
public static HtmlString RenderXml(this HtmlHelper helper, string xml, string transformXsltPath, string xsltPath)
{
xml = System.IO.File.ReadAllText(("C:/Users/Student/Documents/Visual Studio 2010/Projects/MvcApplication2/MvcApplication2/schemat.xsd"));
XsltArgumentList args = new XsltArgumentList();
XslCompiledTransform t = new XslCompiledTransform();
t.Load(transformXsltPath);
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;;
using (XmlReader reader = XmlReader.Create(new StringReader(xml), settings))
{
//StringWriter writer = new StringWriter();
XmlWriter writer = XmlWriter.Create(new StringWriter());
t.Transform(reader, args, writer);
XslCompiledTransform t2 = new XslCompiledTransform();
t2.Load(xsltPath);
XmlReader reader2 = XmlReader.Create(new StringReader(writer.ToString()), settings);
StringWriter writer2 = new StringWriter();
t2.Transform(reader2, args, writer2);
HtmlString htmlString = new HtmlString(writer2.ToString());
return htmlString;
}
}
We are doing security analysis of our code using veracode and its showing XXE flaw for below code, specifically where Deserialize() is invoked. How can we prevent serializer from accessing external entities. My attempt below to set XMLresolver to null for XMLReader is not working.
public static T DeserializeObject(string xml, string Namespace)
{
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T), Namespace);
MemoryStream stream =
new MemoryStream(Encoding.Default.GetBytes(xml));
XmlReaderSettings settings = new XmlReaderSettings();
// allow entity parsing but do so more safely
settings.DtdProcessing = DtdProcessing.Ignore;
settings.XmlResolver = null;
using (XmlReader reader = XmlReader.Create(stream, settings))
{
return serializer.Deserialize(reader) as T;
}
}
Can anyone suggest what I might be missing or if there is something else to try.
I had the similar issue. You need to change xmlReader with xmlTextReader as you are reading from the string.
something like this -
public static T DeserializeObject(string xml, string Namespace)
{
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T), Namespace);
//**** I don't think you need this block of code *********
//MemoryStream stream = new MemoryStream(Encoding.Default.GetBytes(xml));
//XmlReaderSettings settings = new XmlReaderSettings();
// allow entity parsing but do so more safely
//settings.DtdProcessing = DtdProcessing.Ignore;
//settings.XmlResolver = null;
//*********************************************
XmlTextReader reader = new XmlTextReader(xml)
{
XmlResolver = null
};
return serializer.Deserialize(reader) as T;
}
All the best!
I am currently running a live 'in-memory' XSLT transformation using the following code
XmlDocument XmlDoc = new XmlDocument();
XmlDoc.LoadXml(DS.GetXml());
XslCompiledTransform XsltTranformation = new XslCompiledTransform();
XsltTranformation.Load(#"C:\Users\maskew\Desktop\XSLTMapping.xsl");
Stream XmlStream = new MemoryStream();
XmlDoc.Save(XmlStream); //Stream is still blank after this line
XmlReader XmlRdr = XmlReader.Create(XmlStream);
MemoryStream stm = new MemoryStream();
XsltTranformation.Transform(XmlRdr, null, stm);
stm.Position = 1;
StreamReader sr = new StreamReader(stm);
string Output = sr.ReadToEnd();
Output = Output.Substring(2);
XmlDoc.LoadXml(Output);
XmlWriter XmlWrtr = XmlWriter.Create(#"C:\Users\maskew\Desktop\XmlMapping.xml");
XmlDoc.WriteTo(XmlWrtr);
XmlWrtr.Flush();
XmlWrtr.Close();
However, when I move the file from XmlDocument to MemoryStream in line 6 the stream contains nothing when checked and thus stopping the whole program from running.
Does anyone have any idea why this would be occuring?
UPDATED: The stream is containing information now, however the XmlReader object is receiving none of it still.
Try a simplyfying
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = true;
xmlDoc.LoadXml(DS.GetXml());
// Create a writer for writing the transformed file.
XmlWriter writer = XmlWriter.Create(#"C:\Users\maskew\Desktop\XmlMapping.xml");
// Create and load the transform with script execution enabled.
XslCompiledTransform transform = new XslCompiledTransform();
XsltSettings settings = new XsltSettings();
settings.EnableScript = true;
transform.Load(#"C:\Users\maskew\Desktop\XSLTMapping.xsl", settings, null);
// Execute the transformation.
transform.Transform(xmlDoc, writer);
Try flushing and resetting the stream:
XmlDoc.Save(XmlStream);
XmlStream.Flush();
XmlStream.Position = 0;
XmlReader XmlRdr = XmlReader.Create(XmlStream);
Stream XmlStream = new MemoryStream();
How there can be something in it ? You are constructing an empty memoryStream...
EDIT :
You should try to clarify it by using the 'using' instruction (http://msdn.microsoft.com/fr-fr/library/yh598w02). Basically, class like StreamReader, MemeryStream, etc.. implement the IDisposable interface. If you wrap them with using, it will dispose the object automatically for you.
I am using the following code to create an xml document -
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
new XmlSerializer(typeof(docket)).Serialize(Console.Out, i, ns);
this works great in creating the xml file with no namespace attributes. i would like to also have no encoding attribute in the root element, but I cannot find a way to do it. Does anyone have any idea if this can be done?
Thanks
Old answer removed and update with new solution:
Assuming that it's ok to remove the xml declaration completly, because it makes not much sense without the encoding attribute:
XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", "");
using (XmlWriter writer = XmlWriter.Create(Console.Out, new XmlWriterSettings { OmitXmlDeclaration = true}))
{
new XmlSerializer(typeof (SomeType)).Serialize(writer, new SomeType(), ns);
}
To remove encoding from XML header pass TextWriter with null encoding to XmlSerializer:
MemoryStream ms = new MemoryStream();
XmlTextWriter w = new XmlTextWriter(ms, null);
s.Serialize(w, vs);
Explanation
XmlTextWriter uses encoding from TextWriter passed in constructor:
// XmlTextWriter constructor
public XmlTextWriter(TextWriter w) : this()
{
this.textWriter = w;
this.encoding = w.Encoding;
..
It uses this encoding when generating XML:
// Snippet from XmlTextWriter.StartDocument
if (this.encoding != null)
{
builder.Append(" encoding=");
...
string withEncoding;
using (System.IO.MemoryStream memory = new System.IO.MemoryStream()) {
using (System.IO.StreamWriter writer = new System.IO.StreamWriter(memory)) {
serializer.Serialize(writer, obj, null);
using (System.IO.StreamReader reader = new System.IO.StreamReader(memory)) {
memory.Position = 0;
withEncoding= reader.ReadToEnd();
}
}
}
string withOutEncoding= withEncoding.Replace("<?xml version=\"1.0\" encoding=\"utf-8\"?>", "");
Credit to this blog for helping me with my code
http://blog.dotnetclr.com/archive/2008/01/29/removing-declaration-and-namespaces-from-xml-serialization.aspx
here's my solution, same idea, but in VB.NET and a little clearer in my opinion.
Dim sw As StreamWriter = New, StreamWriter(req.GetRequestStream,System.Text.Encoding.ASCII)
Dim xSerializer As XmlSerializer = New XmlSerializer(GetType(T))
Dim nmsp As XmlSerializerNamespaces = New XmlSerializerNamespaces()
nmsp.Add("", "")
Dim xWriterSettings As XmlWriterSettings = New XmlWriterSettings()
xWriterSettings.OmitXmlDeclaration = True
Dim xmlWriter As XmlWriter = xmlWriter.Create(sw, xWriterSettings)
xSerializer.Serialize(xmlWriter, someObjectT, nmsp)
Here's a quick question I've been banging my head against today.
I'm trying to convert a .Net dataset into an XML stream, transform it with an xsl file in memory, then output the result to a new XML file.
Here's the current solution:
string transformXML = #"pathToXslDocument";
XmlDocument originalXml = new XmlDocument();
XmlDocument transformedXml = new XmlDocument();
XslCompiledTransform transformer = new XslCompiledTransform();
DataSet ds = new DataSet();
string filepath;
originalXml.LoadXml(ds.GetXml()); //data loaded prior
StringBuilder sb = new StringBuilder();
XmlWriter writer = XmlWriter.Create(sb);
transformer.Load(transformXML);
transformer.Transform(originalXml, writer); //no need to select the node
transformedXml.LoadXml(sb.ToString());
transformedXml.Save(filepath);
writer.Close();
Here's the original code:
BufferedStream stream = new BufferedStream(new MemoryStream());
DataSet ds = new DataSet();
da.Fill(ds);
ds.WriteXml(stream);
StreamReader sr = new StreamReader(stream, true);
stream.Position = 0; //I'm not certain if this is necessary, but for the StreamReader to read the text the position must be reset.
XmlReader reader = XmlReader.Create(sr, null); //Problem is created here, the XmlReader is created with none of the data from the StreamReader
XslCompiledTransform transformer = new XslCompiledTransform();
transformer.Load(#"<path to xsl file>");
transformer.Transform(reader, null, writer); //Exception is thrown here, though the problem originates from the XmlReader.Create(sr, null)
For some reason in the transformer.Transform method, the reader has no root node, in fact the reader isn't reading anything from the StreamReader.
My questions is what is wrong with this code? Secondarily, is there a better way to convert/transform/store a dataset into XML?
Edit: Both answers were helpful and technically aku's was closer. However I am leaning towards a solution that more closely resembles Longhorn's after trying both solutions.
I'm not sure but it seems that you didn't reset position in stream before passing it to XmlReader. Try to seek at the beginning of your stream before trying to read from it. Also it may be necessary to close\flush stream after you wrote some data to it.
EDIT:
Just tried following code and it worked perfectly:
BufferedStream stream = new BufferedStream(new MemoryStream());
stream.Write(Encoding.ASCII.GetBytes("<xml>foo</xml>"), 0, "<xml>foo</xml>".Length);
stream.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(stream);
XmlReader reader = XmlReader.Create(sr);
while (reader.Read())
{
Console.WriteLine(reader.Value);
}
stream.Close();
You must select the root node. This doesn't use Datasets, but I use this function everyday and it works great.
System.Xml.XmlDocument orgDoc = new System.Xml.XmlDocument();
orgDoc.LoadXml(orgXML);
// MUST SELECT THE ROOT NODE
XmlNode transNode = orgDoc.SelectSingleNode("/");
System.Text.StringBuilder sb = new System.Text.StringBuilder();
XmlWriter writer = XmlWriter.Create(sb);
System.IO.StringReader stream = new System.IO.StringReader(transformXML);
XmlReader reader = XmlReader.Create(stream);
System.Xml.Xsl.XslCompiledTransform trans = new System.Xml.Xsl.XslCompiledTransform();
trans.Load(reader);
trans.Transform(transNode, writer);
XmlDocument doc = new XmlDocument();
doc.LoadXml(sb.ToString());
return doc;
please look it and use..
using (MemoryStream memStream = new MemoryStream())
{
memStream.Write(Encoding.UTF8.GetBytes(xmlBody), 0, xmlBody.Length);
memStream.Seek(0, SeekOrigin.Begin);
using (StreamReader reader = new StreamReader(memStream))
{
// xml reader setting.
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings()
{
IgnoreComments = true,
IgnoreWhitespace = true,
};
// xml reader create.
using (XmlReader xmlReader = XmlReader.Create(reader, xmlReaderSettings))
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(LoginInfo));
myObject = (LoginInfo)xmlSerializer.Deserialize(xmlReader);
}
}
}