【问题标题】:Building an input text area to allow HTML but prevent security / script attacks构建输入文本区域以允许 HTML 但防止安全/脚本攻击
【发布时间】:2012-08-26 19:45:53
【问题描述】:

平台:ASP.NET 4.0 MVC 4 C# jQuery

这就是我想要做的。

我正在为我的产品建立一个简单的论坛。我想给用户一个文本区域来输入他们的帖子或 cmets。

  1. 我想允许基本的文本格式 HTML 和链接 - 例如 p、a、b、i
  2. 不想要任何其他 html 样式 - 即 div、span 等。
  3. 不希望任何脚本访问

有没有聪明的方法来做到这一点?例如,我可以允许不安全的文本并在服务器端对其进行检查,但我怀疑我是否能够正确清理它并且可能会打开安全漏洞。

最好避免使用重型插件。

谢谢!

(PS - 我最糟糕的后备是我只允许安全文本,即保持 ASP.NET 安全,然后对链接使用特殊标记 - 例如 [link] [b] [i])

【问题讨论】:

标签: asp.net asp.net-mvc security


【解决方案1】:

更新(2020 年 2 月): Microsoft's AntiXSS library 在其 Sanitizer 类上包含一个名为 GetSafeHtmlFragment 的静态方法,这似乎是做生意的。 (@exploring.cheerily.impresses建议)


在 .NET 4.5+ 或通过将 System.Web.Security.AntiXss 添加到旧版本的 .NET 中,有一种解决此问题的好方法。我们可以同时使用[AllowHtml] 和自定义注解属性。该方法应将字符串中的 HTML 标记列入白名单并验证请求。

这是此作业的自定义注释属性:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = true, AllowMultiple = false)]
public sealed class RemoveScriptAttribute : ValidationAttribute
{
    public const string DefaultRegexPattern = @"\<((?=(?!\b(a|b|i|p)\b))(?=(?!\/\b(a|b|i|p)\b))).*?\>";

    public string RegexPattern { get; }

    public RemoveScriptAttribute(string regexPattern = null)
    {
        RegexPattern = regexPattern ?? DefaultRegexPattern;
    }

    protected override ValidationResult IsValid(object value, ValidationContext ctx)
    {
        var valueStr = value as string;
        if (valueStr != null)
        {
            var newVal = Regex.Replace(valueStr, RegexPattern, "", RegexOptions.IgnoreCase, new TimeSpan(0, 0, 0, 0, 250));

            if (newVal != valueStr)
            {
                var prop = ctx.ObjectType.GetProperty(ctx.MemberName);
                prop.SetValue(ctx.ObjectInstance, newVal);
            }
        }

        return null;
    }
}

然后你应该使用 [AllowHtml] 和 [RemoveScript] 属性来装饰你想要在其中包含 HTML 的模型属性,如下所示:

public class MyModel
{
    [AllowHtml, RemoveScript]
    public string StringProperty { get; set; }
}

这将只允许

html 标记获取它。所有其他标签都将被删除,但它足够聪明,可以保留标签的内部文本。例如。如果你发送:

“这是John Smith输入的富文本。”

你最终会得到这个:

“这是由 John Smith 输入的富文本。”

将更多 HTML 标签列入白名单也很容易。例如。如果你想接受


,更改 DefaultRegexPattern(全局影响)或将修改后的 regexPattern 传递给 RemoveScriptAttribute 的实例,如下所示:

[AllowHtml]
[RemoveScript(regexPattern: @"\<((?=(?!\b(a|b|i|p|u|br|hr)\b))(?=(?!\/\b(a|b|i|p|u)\b))).*?\>")]
public string Body { get; set; }

【讨论】:

  • 目前我不确定解决方案是什么,但我想我会指出这种方法仍然容易受到通过 JS 事件属性进行脚本注入的攻击,例如,您可以提交:&lt;p onclick="alert('XSS vulnerability exploited')"&gt;Click here for free stuff!&lt;/p&gt;当生成的 HTML 呈现时,如果用户点击该段落,注入的 JS 就会执行。
  • Microsoft 的AntiXSS library 在其Sanitizer 类上包含一个名为GetSafeHtmlFragment 的静态方法,这似乎是在做生意。 @Tohid,我建议更新这个答案以使用它而不是正则表达式。
【解决方案2】:

无论您使用何种方法,您都需要假设输入该字段的所有内容都是恶意的,即不信任任何数据。

我不会为 JavaScript/jQuery 中的任何客户端验证操心太多。它会很复杂,只需要重做服务器端。

服务器端你想采取白名单的方法,即如果它不在名单上,它是无效的。您将无法使用 XML 处理器,因为用户的文本可能不会生成有效的 XML,而是您可能希望使用正则表达式。

我会定义一组有效的标签(你说过 p、a、b 和 i,但我会厌倦最后两个,因为你几乎永远不会在 'wild' html 中得到它们),我然后将定义是否以及哪些属性对这些标签有效。我猜你至少想要a上的href。

您可以删除标签中不匹配的任何文本...我的正则表达式技能不是很好,但这似乎找到了您想要保留的所有标签,需要反转。

\<a\shref\=".[^\"]*\"\>|\</?[abip]\s?\>

【讨论】:

    【解决方案3】:

    有大量在线编辑器可供您使用。我在 google 中输入了“免费在线文本编辑器”,得到了一堆编辑器来审核。

    如果您必须在标记中使用 html,那么当您发现不“安全”的标签时,您将需要解析提交的文本以拒绝该文本。

    仅供参考,您可能对此感兴趣 https://meta.stackexchange.com/questions/121981/stackoverflow-official-wmd-editor

    【讨论】:

      【解决方案4】:

      我将 joocer 的回答标记为“回答”,因为它帮助我形成了自己的观点(尽管他说的不是我最终所做的)

      我决定了一个简单的规则 - 我将链接 http://.... 链接并禁止任何其他 html(这对我的应用程序来说很好)。这样,我让 ASP.NET 框架进行所有错误检查并禁止任何 HTML 标记。然后,当我在客户端上呈现文本时,我只识别并修改了 http:// 链接,方法是用标记装饰,而 HTML 对其他所有内容进行安全编码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-02-24
        • 2018-01-01
        • 2015-04-01
        • 2011-09-07
        • 2020-04-21
        • 1970-01-01
        • 1970-01-01
        • 2010-12-26
        相关资源
        最近更新 更多