Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 30 additions & 111 deletions docs/fundamentals/code-analysis/quality-rules/ca3009.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "CA3009: Review code for XML injection vulnerabilities (code analysis)"
description: "Learn about code analysis rule CA3009: Review code for XML injection vulnerabilities"
ms.date: 07/21/2020
ms.date: 07/19/2023
ms.topic: reference
author: dotpaul
ms.author: paulming
Expand Down Expand Up @@ -38,139 +38,58 @@ This rule attempts to find input from HTTP requests reaching a raw XML write.

## How to fix violations

Don't write raw XML. Instead, use methods or properties that XML-encode their input.
To fix a violation, use one of the following techniques:

Or, XML-encode input before writing raw XML.

Or, validate user input by using sanitizers for primitive type conversion and XML encoding.
- Don't write raw XML. Instead, use methods or properties that XML-encode their input.
- XML-encode input before writing raw XML.
- Validate user input by using sanitizers for primitive type conversion and XML encoding.

## When to suppress warnings

Don't suppress warnings from this rule.

## Configure code to analyze

Use the following options to configure which parts of your codebase to run this rule on.

- [Exclude specific symbols](#exclude-specific-symbols)
- [Exclude specific types and their derived types](#exclude-specific-types-and-their-derived-types)
## Pseudo-code examples

You can configure these options for just this rule, for all rules it applies to, or for all rules in this category ([Security](security-warnings.md)) that it applies to. For more information, see [Code quality rule configuration options](../code-quality-rule-options.md).
### Violation

[!INCLUDE[excluded-symbol-names](../includes/excluded-symbol-names.md)]
In this example, the input is set to the <xref:System.Xml.XmlElement.InnerXml> property of the root element. Given input that contains valid XML, a malicious user can then completely alter the document. Notice that `alice` is no longer an allowed user after the user input is added to the document.

[!INCLUDE[excluded-type-names-with-derived-types](../includes/excluded-type-names-with-derived-types.md)]
:::code language="csharp" source="snippets/csharp/netfx/ca3009.cs" id="violation" highlight="12":::

## Pseudo-code examples
:::code language="vb" source="snippets/vb/netfx/ca3009.vb" id="violation" highlight="11":::

### Violation
If an attacker uses this for input: `some text<allowedUser>oscar</allowedUser>`, then the XML document will be:

```csharp
using System;
using System.Xml;

public partial class WebForm : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string input = Request.Form["in"];
XmlDocument d = new XmlDocument();
XmlElement root = d.CreateElement("root");
d.AppendChild(root);

XmlElement allowedUser = d.CreateElement("allowedUser");
root.AppendChild(allowedUser);

allowedUser.InnerXml = "alice";

// If an attacker uses this for input:
// some text<allowedUser>oscar</allowedUser>
// Then the XML document will be:
// <root>some text<allowedUser>oscar</allowedUser></root>
root.InnerXml = input;
}
}
```xml
<root>some text<allowedUser>oscar</allowedUser>
</root>
```

```vb
Imports System
Imports System.Xml
### Solution

Public Partial Class WebForm
Inherits System.Web.UI.Page
To fix this violation, set the input to the <xref:System.Xml.XmlElement.InnerText> property of the root element instead of the <xref:System.Xml.XmlElement.InnerXml> property.

Sub Page_Load(sender As Object, e As EventArgs)
Dim input As String = Request.Form("in")
Dim d As XmlDocument = New XmlDocument()
Dim root As XmlElement = d.CreateElement("root")
d.AppendChild(root)
:::code language="csharp" source="snippets/csharp/netfx/ca3009.cs" id="fix" highlight="12":::

Dim allowedUser As XmlElement = d.CreateElement("allowedUser")
root.AppendChild(allowedUser)
:::code language="vb" source="snippets/vb/netfx/ca3009.vb" id="fix" highlight="11":::

allowedUser.InnerXml = "alice"
If an attacker uses this for input: `some text<allowedUser>oscar</allowedUser>`, then the XML document will be:

' If an attacker uses this for input:
' some text<allowedUser>oscar</allowedUser>
' Then the XML document will be:
' <root>some text<allowedUser>oscar</allowedUser></root>
root.InnerXml = input
End Sub
End Class
```xml
<root>some text&lt;allowedUser&gt;oscar&lt;/allowedUser&gt;
<allowedUser>alice</allowedUser>
</root>
```

### Solution

```csharp
using System;
using System.Xml;

public partial class WebForm : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string input = Request.Form["in"];
XmlDocument d = new XmlDocument();
XmlElement root = d.CreateElement("root");
d.AppendChild(root);

XmlElement allowedUser = d.CreateElement("allowedUser");
root.AppendChild(allowedUser);

allowedUser.InnerText = "alice";

// If an attacker uses this for input:
// some text<allowedUser>oscar</allowedUser>
// Then the XML document will be:
// <root>&lt;allowedUser&gt;oscar&lt;/allowedUser&gt;some text<allowedUser>alice</allowedUser></root>
root.InnerText = input;
}
}
```

```vb
Imports System
Imports System.Xml
## Configure code to analyze

Public Partial Class WebForm
Inherits System.Web.UI.Page
Use the following options to configure which parts of your codebase to run this rule on.

Sub Page_Load(sender As Object, e As EventArgs)
Dim input As String = Request.Form("in")
Dim d As XmlDocument = New XmlDocument()
Dim root As XmlElement = d.CreateElement("root")
d.AppendChild(root)
- [Exclude specific symbols](#exclude-specific-symbols)
- [Exclude specific types and their derived types](#exclude-specific-types-and-their-derived-types)

Dim allowedUser As XmlElement = d.CreateElement("allowedUser")
root.AppendChild(allowedUser)
You can configure these options for just this rule, for all rules it applies to, or for all rules in this category ([Security](security-warnings.md)) that it applies to. For more information, see [Code quality rule configuration options](../code-quality-rule-options.md).

allowedUser.InnerText = "alice"
[!INCLUDE[excluded-symbol-names](../includes/excluded-symbol-names.md)]

' If an attacker uses this for input:
' some text<allowedUser>oscar</allowedUser>
' Then the XML document will be:
' <root>&lt;allowedUser&gt;oscar&lt;/allowedUser&gt;some text<allowedUser>alice</allowedUser></root>
root.InnerText = input
End Sub
End Class
```
[!INCLUDE[excluded-type-names-with-derived-types](../includes/excluded-type-names-with-derived-types.md)]
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.Xml;

public partial class WebForm1 : System.Web.UI.Page
{
// <violation>
protected void Page_Load(object sender, EventArgs e)
{
XmlDocument d = new XmlDocument();
XmlElement root = d.CreateElement("root");
d.AppendChild(root);

XmlElement allowedUser = d.CreateElement("allowedUser");
root.AppendChild(allowedUser);
allowedUser.InnerXml = "alice";

string input = Request.Form["in"];
root.InnerXml = input;
}
// </violation>
}

public partial class WebForm2 : System.Web.UI.Page
{
// <fix>
protected void Page_Load(object sender, EventArgs e)
{
XmlDocument d = new XmlDocument();
XmlElement root = d.CreateElement("root");
d.AppendChild(root);

XmlElement allowedUser = d.CreateElement("allowedUser");
root.AppendChild(allowedUser);
allowedUser.InnerText = "alice";

string input = Request.Form["in"];
root.InnerText = input;
}
// </fix>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net48</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Reference Include="System.Web" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

Imports System
Imports System.Xml

Public Partial Class WebForm1
Inherits System.Web.UI.Page

' <violation>
Sub Page_Load(sender As Object, e As EventArgs)
Dim d As XmlDocument = New XmlDocument()
Dim root As XmlElement = d.CreateElement("root")
d.AppendChild(root)

Dim allowedUser As XmlElement = d.CreateElement("allowedUser")
root.AppendChild(allowedUser)
allowedUser.InnerXml = "alice"

Dim input As String = Request.Form("in")
root.InnerXml = input
End Sub
' </violation>
End Class

Public Partial Class WebForm2
Inherits System.Web.UI.Page

' <fix>
Sub Page_Load(sender As Object, e As EventArgs)
Dim d As XmlDocument = New XmlDocument()
Dim root As XmlElement = d.CreateElement("root")
d.AppendChild(root)

Dim allowedUser As XmlElement = d.CreateElement("allowedUser")
root.AppendChild(allowedUser)
allowedUser.InnerText = "alice"

Dim input As String = Request.Form("in")
root.InnerText = input
End Sub
' </fix>
End Class
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net48</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Reference Include="System.Web" />
</ItemGroup>

</Project>