jer*_*emy 5 asp.net security asp.net-mvc
平台:ASP.NET 4.0 MVC 4 C# jQuery
这就是我想做的。
我正在为我的产品建立一个简单的论坛。我想为用户提供一个文本区域来输入他们的帖子或评论。
有什么聪明的方法可以做到这一点吗?例如,我可以允许不安全的文本并在服务器端检查它,但我怀疑我是否能够正确清理它并可能打开安全漏洞。
最好要避免重型插件。
谢谢!
(PS - 我最糟糕的后备方案是我只允许安全文本,即保持 ASP.NET 安全性,然后对链接使用特殊标记 - 例如 [link] [b] [i])
更新(2020 年 2 月): Microsoft 的 AntiXSS 库在其 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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您应该使用 [AllowHtml] 和 [RemoveScript] 属性来装饰您想要 HTML 的模型属性,如下所示:
public class MyModel
{
[AllowHtml, RemoveScript]
public string StringProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这将只允许 <a>、<b>、<i> 和 <p> html 标签获取它。所有其他标签都将被删除,但它足够智能,可以保留标签的内部文本。例如,如果您发送:
“这是 <b>富文本<b>,由 <u>John Smith</u> 输入。”
你最终会得到这个:
“这是 John Smith 输入的<b>富文本<b>。”
将更多 HTML 标签列入白名单也很容易。例如,如果您想接受 <u></u>、<br /> 和 <hr />,请更改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; }
Run Code Online (Sandbox Code Playgroud)
无论您使用哪种方法,您都需要假设输入该字段的所有内容都是恶意的,即不信任任何数据。
我不会太在意 JavaScript/jQuery 中的任何客户端验证。它会很复杂,只需要在服务器端重做。
服务器端要采取白名单的方式,即如果不在列表中,则无效。您将无法使用 XML 处理器,因为用户的文本可能不会生成有效的 XML,而您可能希望使用正则表达式。
我会定义一组有效的标签(你说过p、a、b和i,但我会对最后两个感到厌倦,因为你几乎永远不会在“狂野”html中得到它们),然后我会定义是否以及哪些属性对这些标签有效。我猜你至少需要一个关于 a 的 href。
您可以删除标签中不匹配的任何文本...我的正则表达式技能不太好,但这似乎找到了您想要保留的所有标签,需要将其反转。
\<a\shref\=".[^\"]*\"\>|\</?[abip]\s?\>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6263 次 |
| 最近记录: |