返回

.NET C# 过滤从富文本编辑器html里的Javascript脚本

2025-04-01 .NET C# JavaScript 1342 0

富文本编辑器在允许用户输入丰富内容的同时,也带来了跨站脚本攻击(XSS)的风险。过滤提交的 HTML 中的 <script> 脚本是防止跨站脚本攻击(XSS)的关键步骤。在 .NET C# 服务端过滤 <script> 脚本主要有以下几种方法:

1. 使用 HTML Agility Pack 库

HTML Agility Pack 是一个强大的 .NET 库,用于解析和操作 HTML 文档。您可以使用它来遍历 HTML 节点,并删除或转义 <script> 标签。

using HtmlAgilityPack;

public static string SanitizeHtml(string html)
{
    var doc = new HtmlDocument();
    doc.LoadHtml(html);

    // 删除 <script> 标签
    var scriptNodes = doc.DocumentNode.SelectNodes("//script");
    if (scriptNodes != null)
    {
        foreach (var scriptNode in scriptNodes)
        {
            scriptNode.Remove();
        }
    }

    // 转义危险属性(例如:onclick、onerror)
    var nodesWithAttributes = doc.DocumentNode.SelectNodes("//*[@onclick or @onerror]");
    if (nodesWithAttributes != null)
    {
        foreach (var node in nodesWithAttributes)
        {
            if (node.Attributes["onclick"] != null) node.Attributes["onclick"].Value = "";
            if (node.Attributes["onerror"] != null) node.Attributes["onerror"].Value = "";
        }
    }

    return doc.DocumentNode.OuterHtml;
}

2. 使用 AntiXss HtmlSanitizer 库

AntiXss 库由 Microsoft 开发,专门用于防止 XSS 攻击。它提供了一系列编码器和清理器,可以帮助您安全地处理 HTML 内容。

using Microsoft.Security.Application;

public static string SanitizeHtml(string html)
{
    return Sanitizer.GetSafeHtmlFragment(html);
}

目前 AntiXss 库已经过时,.NET项目建议使用 HtmlSanitizer 库。HtmlSanitizer 库用法示例:

using Ganss.XSS;

public static string SanitizeHtml(string html)
{
    var sanitizer = new HtmlSanitizer();
    return sanitizer.Sanitize(html);
}

3. 使用白名单机制

白名单机制是最安全的方法。您可以定义一个允许的 HTML 标签和属性列表,并移除或转义所有其他标签和属性。

using HtmlAgilityPack;
using System.Collections.Generic;

public static string SanitizeHtml(string html)
{
    var doc = new HtmlDocument();
    doc.LoadHtml(html);

    var allowedTags = new HashSet<string> { "p", "b", "i", "u", "a", "img", "br" };
    var allowedAttributes = new HashSet<string> { "href", "src", "alt", "title" };

    RemoveUnallowedNodes(doc.DocumentNode, allowedTags, allowedAttributes);

    return doc.DocumentNode.OuterHtml;
}

private static void RemoveUnallowedNodes(HtmlNode node, HashSet<string> allowedTags, HashSet<string> allowedAttributes)
{
    for (int i = node.ChildNodes.Count - 1; i >= 0; i--)
    {
        var childNode = node.ChildNodes[i];
        if (childNode.NodeType == HtmlNodeType.Element)
        {
            if (!allowedTags.Contains(childNode.Name))
            {
                childNode.Remove();
            }
            else
            {
                // 移除不允许的属性
                for (int j = childNode.Attributes.Count - 1; j >= 0; j--)
                {
                    var attribute = childNode.Attributes[j];
                    if (!allowedAttributes.Contains(attribute.Name))
                    {
                        childNode.Attributes.Remove(attribute);
                    }
                }
                RemoveUnallowedNodes(childNode, allowedTags, allowedAttributes);
            }
        }
    }
}

4. 使用正则表达式(不推荐)

您可以使用正则表达式来移除 <script> 标签。但是,正则表达式容易被绕过,并且难以处理复杂的 HTML 结构。

using System.Text.RegularExpressions;

public static string SanitizeHtml(string html)
{
    return Regex.Replace(html, "<script.*?</script>", "", RegexOptions.Singleline | RegexOptions.IgnoreCase);
}

安全建议

  • 服务端验证:始终在服务端进行 HTML 清理。
  • 白名单机制:尽可能使用白名单机制。
  • 使用成熟的库:利用成熟的库(如 HTML Agility Pack 或 AntiXss),来处理 HTML 清理。
  • 内容安全策略 (CSP):CSP 是一个强大的安全工具,可以有效防止 XSS 攻击。
  • 最小权限原则:只授予用户必要的 HTML 编辑权限。
  • 内容审核:对用户提交的 HTML 内容进行人工审核,特别是来自不受信任用户的输入。
顶部