Skip to content
🔵Info0.0

.NET XXE Prevention

Secure XML parsing configuration for .NET Framework, .NET Core, and .NET 5+ applications to prevent XXE vulnerabilities.

CWE-611: Improper Restriction of XML External Entity ReferenceOWASP Top 10:2021 - A05: Security Misconfiguration

Overview

.NET provides multiple XML parsing APIs with varying security defaults. Understanding which API you're using and its default behavior is critical for XXE prevention.

Key .NET XML APIs:

  • XmlDocument - Legacy DOM parser (vulnerable by default in .NET Framework)
  • XmlTextReader - Stream-based reader (vulnerable by default)
  • XmlReader - Abstract base class (secure defaults in .NET 4.5.2+)
  • XDocument (LINQ to XML) - Modern API (secure defaults in .NET 4.5.2+)
  • XmlSerializer - Object serialization (requires configuration)

Security Evolution:

  • .NET Framework < 4.5.2: Vulnerable by default
  • .NET Framework 4.5.2+: Secure defaults for XmlReader
  • .NET Core / .NET 5+: Secure defaults for all parsers

Important: Even with secure defaults, explicit configuration is recommended for defense in depth.

Vulnerable XmlDocument (.NET Framework)

C#VulnerableXMLParser.cs⚠️ Vulnerable
1using System.Xml;
2
3public class VulnerableXMLParser
4{
5    public void ParseXML(string xmlData)
6    {
7        // VULNERABLE in .NET Framework < 4.5.2
8        // XmlResolver enabled by default
9        XmlDocument doc = new XmlDocument();
10        doc.LoadXml(xmlData);
11        
12        // XXE payload will be processed:
13        // External entities loaded and expanded
14        // File disclosure and SSRF possible
15        
16        string content = doc.InnerText;
17        Console.WriteLine(content);
18    }
19}

Secure XmlDocument Configuration

C#SecureXMLParser.csâś“ Secure
1using System.Xml;
2
3public class SecureXMLParser
4{
5    public void ParseXML(string xmlData)
6    {
7        XmlDocument doc = new XmlDocument();
8        
9        // SECURE: Disable XmlResolver (prevents external entity loading)
10        doc.XmlResolver = null;  // Critical security setting
11        
12        // Additional security: Use safe reader settings
13        XmlReaderSettings settings = new XmlReaderSettings
14        {
15            DtdProcessing = DtdProcessing.Prohibit,  // Disallow DTDs completely
16            XmlResolver = null  // Disable external entity resolution
17        };
18        
19        using (StringReader stringReader = new StringReader(xmlData))
20        using (XmlReader reader = XmlReader.Create(stringReader, settings))
21        {
22            doc.Load(reader);
23        }
24        
25        string content = doc.InnerText;
26        Console.WriteLine(content);
27    }
28}

Secure XmlReader Configuration (Recommended)

C#SecureXmlReaderParser.csâś“ Secure
1using System.Xml;
2using System.IO;
3
4public class SecureXmlReaderParser
5{
6    public void ParseXML(string xmlData)
7    {
8        // RECOMMENDED: Use XmlReaderSettings with explicit security
9        XmlReaderSettings settings = new XmlReaderSettings
10        {
11            // Primary defense: Prohibit DTD processing
12            DtdProcessing = DtdProcessing.Prohibit,  // Strongest protection
13            
14            // If DTDs are required, use DtdProcessing.Parse with secure resolver:
15            // DtdProcessing = DtdProcessing.Parse,
16            // XmlResolver = null,  // Disable external entities
17            
18            // Additional security settings
19            XmlResolver = null,           // Disable external entity resolution
20            MaxCharactersFromEntities = 0, // Prevent entity expansion
21            
22            // Optional: Prevent DoS via large documents
23            MaxCharactersInDocument = 10000000  // 10MB limit
24        };
25        
26        using (StringReader stringReader = new StringReader(xmlData))
27        using (XmlReader reader = XmlReader.Create(stringReader, settings))
28        {
29            while (reader.Read())
30            {
31                if (reader.NodeType == XmlNodeType.Element)
32                {
33                    Console.WriteLine($"Element: {reader.Name}");
34                }
35            }
36        }
37    }
38}

Secure XDocument (LINQ to XML)

C#SecureXDocumentParser.csâś“ Secure
1using System.Xml.Linq;
2using System.Xml;
3using System.IO;
4
5public class SecureXDocumentParser
6{
7    public void ParseXML(string xmlData)
8    {
9        // XDocument is secure by default in .NET 4.5.2+
10        // But explicit configuration is recommended
11        
12        XmlReaderSettings settings = new XmlReaderSettings
13        {
14            DtdProcessing = DtdProcessing.Prohibit,
15            XmlResolver = null
16        };
17        
18        using (StringReader stringReader = new StringReader(xmlData))
19        using (XmlReader reader = XmlReader.Create(stringReader, settings))
20        {
21            XDocument doc = XDocument.Load(reader);
22            
23            // Process XML safely with LINQ
24            var elements = from elem in doc.Descendants()
25                          where elem.Name == "data"
26                          select elem.Value;
27            
28            foreach (var value in elements)
29            {
30                Console.WriteLine(value);
31            }
32        }
33    }
34}

Secure XmlSerializer

C#SecureXmlSerializerParser.csâś“ Secure
1using System.Xml.Serialization;
2using System.Xml;
3using System.IO;
4
5public class Person
6{
7    public string Name { get; set; }
8    public int Age { get; set; }
9}
10
11public class SecureXmlSerializerParser
12{
13    public Person DeserializeXML(string xmlData)
14    {
15        XmlSerializer serializer = new XmlSerializer(typeof(Person));
16        
17        // Secure XmlReader settings
18        XmlReaderSettings settings = new XmlReaderSettings
19        {
20            DtdProcessing = DtdProcessing.Prohibit,
21            XmlResolver = null,
22            MaxCharactersFromEntities = 0
23        };
24        
25        using (StringReader stringReader = new StringReader(xmlData))
26        using (XmlReader reader = XmlReader.Create(stringReader, settings))
27        {
28            // Deserialize with secure reader
29            Person person = (Person)serializer.Deserialize(reader);
30            return person;
31        }
32    }
33}

DtdProcessing Options Explained

DtdProcessing.Prohibit (Recommended):

  • Completely disallows DTD processing
  • Parser throws XmlException if DTD found
  • Strongest protection against XXE and DoS
  • Use this unless DTD validation required

DtdProcessing.Ignore:

  • Skips over DTD declarations without processing
  • Less safe than Prohibit
  • Can still be vulnerable in some scenarios
  • Not recommended

DtdProcessing.Parse:

  • Allows DTD processing
  • Only use with XmlResolver = null
  • Required if you need DTD validation
  • Must be explicitly secured

Best Practice: Always use DtdProcessing.Prohibit unless you have a specific requirement for DTD validation. If DTDs are needed, use DtdProcessing.Parse with XmlResolver = null.

ASP.NET Configuration

C#XmlController.csâś“ Secure
1using Microsoft.AspNetCore.Mvc;
2using System.Xml;
3using System.IO;
4
5[ApiController]
6[Route("api/[controller]")]
7public class XmlController : ControllerBase
8{
9    [HttpPost]
10    public IActionResult ProcessXml([FromBody] string xmlData)
11    {
12        try
13        {
14            // Secure XML processing in ASP.NET Core
15            XmlReaderSettings settings = new XmlReaderSettings
16            {
17                DtdProcessing = DtdProcessing.Prohibit,
18                XmlResolver = null,
19                MaxCharactersFromEntities = 0,
20                MaxCharactersInDocument = 10000000,  // 10MB limit
21                
22                // Additional ASP.NET security
23                ConformanceLevel = ConformanceLevel.Document,
24                IgnoreComments = true,
25                IgnoreProcessingInstructions = true
26            };
27            
28            using (StringReader stringReader = new StringReader(xmlData))
29            using (XmlReader reader = XmlReader.Create(stringReader, settings))
30            {
31                XmlDocument doc = new XmlDocument();
32                doc.XmlResolver = null;  // Always set this for XmlDocument
33                doc.Load(reader);
34                
35                // Process safely
36                return Ok(new { status = "success" });
37            }
38        }
39        catch (XmlException ex)
40        {
41            // Don't leak XML parse details in error messages
42            return BadRequest(new { error = "Invalid XML format" });
43        }
44    }
45}

Framework-Specific Guidance

.NET Framework 4.5.1 and Earlier:

  • All XML parsers vulnerable by default
  • MUST explicitly set XmlResolver = null
  • MUST set DtdProcessing = DtdProcessing.Prohibit
  • Upgrade to 4.5.2+ if possible

.NET Framework 4.5.2 - 4.8:

  • XmlReader secure by default (XmlResolver = null)
  • XmlDocument still requires XmlResolver = null
  • Explicit configuration still recommended
  • Consider migrating to .NET Core/.NET 5+

.NET Core 2.0+ / .NET 5+:

  • All XML parsers secure by default
  • XmlResolver = null by default
  • DTD processing disabled by default for most APIs
  • Still use explicit settings for defense in depth

Web.config Settings (.NET Framework):

<configuration>
  <appSettings>
    <!-- These don't directly affect XML parsing -->
    <!-- Must configure parsers in code -->
  </appSettings>
</configuration>

Testing XXE Prevention

C#XXEPreventionTests.csâś“ Secure
1using Xunit;
2using System.Xml;
3using System;
4
5public class XXEPreventionTests
6{
7    [Fact]
8    public void TestXXEBlocked()
9    {
10        string xxePayload = @"
11            <?xml version=""1.0"" encoding=""UTF-8""?>
12            <!DOCTYPE root [
13              <!ENTITY xxe SYSTEM ""file:///etc/passwd"">
14            ]>
15            <root>
16              <data>&xxe;</data>
17            </root>";
18        
19        XmlReaderSettings settings = new XmlReaderSettings
20        {
21            DtdProcessing = DtdProcessing.Prohibit,
22            XmlResolver = null
23        };
24        
25        // Should throw XmlException
26        Assert.Throws<XmlException>(() =>
27        {
28            using (StringReader stringReader = new StringReader(xxePayload))
29            using (XmlReader reader = XmlReader.Create(stringReader, settings))
30            {
31                while (reader.Read()) { }
32            }
33        });
34    }
35    
36    [Fact]
37    public void TestValidXMLAccepted()
38    {
39        string validXml = @"<root><data>valid content</data></root>";
40        
41        XmlReaderSettings settings = new XmlReaderSettings
42        {
43            DtdProcessing = DtdProcessing.Prohibit,
44            XmlResolver = null
45        };
46        
47        // Should parse without error
48        using (StringReader stringReader = new StringReader(validXml))
49        using (XmlReader reader = XmlReader.Create(stringReader, settings))
50        {
51            while (reader.Read())
52            {
53                Assert.NotNull(reader);
54            }
55        }
56    }
57}

.NET XXE Prevention Checklist

âś… Code Configuration:

  • Set DtdProcessing = DtdProcessing.Prohibit on all XmlReaderSettings
  • Set XmlResolver = null on all XmlDocument instances
  • Set MaxCharactersFromEntities = 0 to prevent entity expansion
  • Use XmlReader.Create() with secure settings instead of direct parsers

âś… Framework Version:

  • Identify which .NET version you're using
  • Understand default security posture for that version
  • Upgrade to .NET Core/.NET 5+ if possible
  • Apply security patches regularly

âś… Input Validation:

  • Reject XML containing <!DOCTYPE if not needed
  • Validate XML against expected schema
  • Limit XML document size before parsing
  • Sanitize error messages (don't leak XML parse details)

âś… Testing:

  • Unit tests with XXE payloads (should throw exception)
  • Integration tests with valid XML (should succeed)
  • Security scanning with XXE detection tools
  • Regular penetration testing

âś… Defense in Depth:

  • Network egress filtering (block outbound connections)
  • File system permissions (limit file access)
  • Least privilege (run app with minimal permissions)
  • Monitoring and alerting for XXE attempts