CA3009:查看 XML 注入漏洞的代码

属性
规则 ID CA3009
标题 查看 XML 注入漏洞的代码
类别 安全性
修复是中断修复还是非中断修复 非中断
在 .NET 8 中默认启用

原因

可能有不受信任的 HTTP 请求输入访问原始 XML 输出。

默认情况下,此规则会分析整个代码库,但这是可配置的。

规则说明

处理不受信任的输入时,请注意防范 XML 注入攻击。 攻击者可以使用 XML 注入向 XML 文档中插入特殊字符,使文档变成无效的 XML。 或者,攻击者可能会恶意插入其所选的 XML 节点。

此规则试图查找 HTTP 请求中要访问原始 XML 写入的输入。

注意

此规则无法跨程序集跟踪数据。 例如,如果一个程序集读取 HTTP 请求输入,然后将其传递给另一个会编写原始 XML 的程序集,则此规则不会产生警告。

注意

对于此规则跨方法调用分析数据流的深入程度存在限制,此限制是可配置的。 若要了解如何在 EditorConfig 文件中配置此限制,请参阅分析器配置

如何解决冲突

若要解决此冲突,请使用以下方法之一:

  • 不要编写原始 XML。 改为使用方法或属性对输入执行 XML 编码。
  • 在编写原始 XML 之前,先对输入执行 XML 编码。
  • 使用擦除器执行基元类型转换和 XML 编码,以验证用户输入。

何时禁止显示警告

不要禁止显示此规则的警告。

伪代码示例

冲突

在此示例中,输入设置为根元素的 InnerXml 属性。 如果给定包含有效 XML 的输入,恶意用户可以完全更改文档。 请注意,在将用户输入添加到文档后,不再允许 alice 用户。

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;
}
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

如果攻击者将 some text<allowedUser>oscar</allowedUser> 用于输入,则 XML 文档将为:

<root>some text<allowedUser>oscar</allowedUser>
</root>

解决方案

若要解决此冲突,请将输入设置为根元素的 InnerText 属性,而不是 InnerXml 属性。

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;
}
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

如果攻击者将 some text<allowedUser>oscar</allowedUser> 用于输入,则 XML 文档将为:

<root>some text&lt;allowedUser&gt;oscar&lt;/allowedUser&gt;
<allowedUser>alice</allowedUser>
</root>

配置代码以进行分析

使用下面的选项来配置代码库的哪些部分要运行此规则。

可以仅为此规则、为适用的所有规则或为适用的此类别(安全性)中的所有规则配置这些选项。 有关详细信息,请参阅代码质量规则配置选项

排除特定符号

可以从分析中排除特定符号,如类型和方法。 例如,若要指定规则不应针对名为 MyType 的类型中的任何代码运行,请将以下键值对添加到项目中的 .editorconfig 文件:

dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType

选项值中允许的符号名称格式(用 | 分隔):

  • 仅符号名称(包括具有相应名称的所有符号,不考虑包含的类型或命名空间)。
  • 完全限定的名称,使用符号的文档 ID 格式。 每个符号名称都需要带有一个符号类型前缀,例如表示方法的 M:、表示类型的 T:,以及表示命名空间的 N:
  • .ctor 表示构造函数,.cctor 表示静态构造函数。

示例:

选项值 总结
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType 匹配名为 MyType 的所有符号。
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType1|MyType2 匹配名为 MyType1MyType2 的所有符号。
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS.MyType.MyMethod(ParamType) 匹配带有指定的完全限定签名的特定方法 MyMethod
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS1.MyType1.MyMethod1(ParamType)|M:NS2.MyType2.MyMethod2(ParamType) 匹配带有各自的完全限定签名的特定方法 MyMethod1MyMethod2

排除特定类型及其派生类型

可以从分析中排除特定类型及其派生类型。 例如,若要指定规则不应针对名为 MyType 的类型及其派生类型中的任何代码运行,请将以下键值对添加到项目中的 .editorconfig 文件:

dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType

选项值中允许的符号名称格式(用 | 分隔):

  • 仅类型名称(包括具有相应名称的所有类型,不考虑包含的类型或命名空间)。
  • 完全限定的名称,使用符号的文档 ID 格式,前缀为 T:(可选)。

示例:

选项值 总结
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType 匹配名为 MyType 的所有类型及其所有派生类型。
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType1|MyType2 匹配名为 MyType1MyType2 的所有类型及其所有派生类型。
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS.MyType 匹配带有给定的完全限定名称的特定类型 MyType 及其所有派生类型。
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS1.MyType1|M:NS2.MyType2 匹配带有各自的完全限定名称的特定类型 MyType1MyType2 及其所有派生类型。