Security Considerations (XML Data in Silverlight)
This topic describes security considerations that are specific to processing XML data in Silverlight.
Process DTD with Caution
DTD processing may lead to a denial-of-service attack. For example, the DTD may contain nested entities or complex content models that can take an inordinate amount of time to process.
DTD processing is disabled by default on the XmlReader objects.
DTD processing can be turned on or off using XmlReaderSettings.DtdProcessing. The default value of the DtdProcessing in System.Xml.XmlReaderSettings is Prohibit. If the DTD processing is set to Prohibit and the input document contains a DTD, an exception will be thrown.
If disabling DTDs is not an option, and including DTDs from untrusted sources and DoS is an issue, make sure your XML processing is memory– and time-constrained.
In Silverlight, the new option Ignore allows for processing of XML documents without processing of the DTD. With the Ignore option, the internal subset of the DTD will be skipped and the external DTD will not be opened. In this case, any usage of an entity reference in the XML document that is defined in the ignored DTD will result in an error.
One of the known DTD-related DoS attacks is a document that causes excessive entity expansion. To prevent this, you can set the MaxCharactersFromEntities property, and create a reader that is then limited in the number of characters that result from entity expansion. You then use the reader to create the XML tree.
Protect Against Untrusted XmlReader or XmlWriter Implementations
Limit the Depth of the XML Hierarchy
One possible denial-of-service (DoS) attack happens when a submitted document has excessive depth of hierarchy. To prevent this, you can wrap a XmlReader in your own class that counts the depth of elements. If the depth exceeds a predetermined reasonable level, you can terminate the processing of the malicious document.
Protect Against Random XML Names
Applications that take data from untrusted sources should consider using an XmlReader that is wrapped in custom code to inspect for the possibility of random XML names and namespaces. If such random XML names and namespaces are detected, the application can then terminate the processing of the malicious document.
You might want to limit the number of names in any given namespace (including names in no namespace) to a reasonable limit.
Limit Document Size
Memory usage of an application that uses XmlReader may have a correlation to the size of the parsed XML document. One form of DoS attack is when excessively large XML documents are submitted to be parsed.
Limit the size of the document that can be parsed by setting the MaxCharactersInDocument property.
Use the ReadValueChunk method to handle large streams of textual data. This method reads a small number of characters at a time instead of allocating a single string for the whole value of a text node.
Do not Accept Supporting Components
Do not Accept Encoding Components
Do not accept encoding components from untrusted code.
Avoid Pipelining XmlWriter
User code that passes an instance of the XmlWriter to another application is making the underlying stream vulnerable.
The XmlXapResolver is the default resolver for the XDocument, XmlReader, and the XmlReaderSettings. It resolves resources in the Silverlight application’s XAP package, however, it does not verify that the file requested from the XAP file is valid XML content.
The XmlPreloadedResolver is used to prepopulate the cache with DTDs or XML streams. The fallback resolver is used in the case where a URI is not resolved within the XmlPreloadedResolver. Be aware that preloaded content is serialized along with the XmlPreloadedResolver, thus increasing the size of the serialized object and exposing your application to information sharing.
You should consider the following items when working with resolvers:
XmlResolver objects can contain sensitive information such as pre-loaded XML or DTDs. You should not pass the XmlResolver to an untrusted component because the untrusted component could use the XmlResolver to access data.
If you are designing a class property that uses the XmlResolver class, the property should be defined as a write-only property. The property can be used to specify the XmlResolver to use, but it cannot be used to return an XmlResolver object. This allows an untrusted component to use the class, but does not allow it to retrieve and directly use the XmlResolver object.
If your application accepts XmlResolver objects from untrusted code, you cannot assume that the URI passed into the GetEntity method is the same as that returned by the ResolveUri method. Classes derived from the XmlResolver class can override the GetEntity method and return data that is different than what was contained in the original URI.
Your application can mitigate memory DoS threats to the GetEntity method by implementing a wrapping-implemented IStream that limits the number of bytes read. This helps to guard against situations where malicious code attempts to pass an infinite stream of bytes to the GetEntity method.
LINQ to XML is designed more for programming convenience than for server applications with stringent security requirements. Most XML scenarios consist of processing trusted XML documents, rather than processing untrusted XML documents that are uploaded to a server. LINQ to XML is optimized for these scenarios.
If you must process untrusted data from unknown sources, Microsoft recommends that you use an instance of the XmlReader class that has been configured to filter out known XML DoS attacks.
If you have configured an XmlReader to mitigate DoS attacks, you can use that reader to populate a LINQ to XML tree and still benefit from the programmer productivity enhancements of LINQ to XML. Many mitigation techniques involve creating readers that are configured to mitigate the security issue, and then instantiating an XML tree through the configured reader.
XML is intrinsically vulnerable to DoS attacks because documents are unbounded in size, depth, element name size, and more. Regardless of the component that you use to process XML, you should always be prepared to recycle the application domain if it uses excessive resources.
Periodically Free Objects that Reference XName
To protect against certain kinds of attacks, application programmers should free all objects that reference an XName object in the application domain on a regular basis.
Be Careful when Sharing LINQ to XML Trees
LINQ to XML could be used to build processing pipelines in which different application components load, validate, query, transform, update, and save XML data that is passed between components as LINQ to XML trees. This can help optimize performance, because the overhead of loading and serializing objects to XML text is done only at the ends of the pipeline. Developers must be aware, however, that all annotations and event handlers created by one component are accessible to other components. This can create a number of vulnerabilities if the components have different levels of trust. To build secure pipelines across less-trusted components, you must serialize LINQ to XML objects to XML text before passing the data to an untrusted component.
Some security is provided by the common language runtime (CLR). For example, a component that does not include a private class cannot access annotations keyed by that class. However, annotations can be deleted by components that cannot read them. This could be used as a tampering attack.