【问题标题】:Regex to remove onclick="" attributes from HTML elements in ASP.NET C# (Server-side)正则表达式从 ASP.NET C#(服务器端)中的 HTML 元素中删除 onclick="" 属性
【发布时间】:2015-07-15 17:27:33
【问题描述】:

我正在尝试编写一个正则表达式函数来从 HTML 元素中删除 onclick(还有 onload、onmouseover 等)属性。我想在将 HTML 发送到客户端之前在服务器端执行此操作。

我的内容来自富文本编辑器并以 div 的形式显示在屏幕上,我想防止 XSS(跨站点脚本)。显然,我不能使用 Server.HtmlEncode() 对其进行 HTML 编码,因为富文本将文本存储为 HTML 标记,因此我使用了黑名单方法,查找某些元素,例如 <script><style>。我现在正在尝试寻找 onclick、onmouseover 等属性,到目前为止我有以下内容:

returnVal = Regex.Replace(returnVal, @"\<(.*?)(\ on[a-z]+\=\""?.*?\""?)*(.*?)\>",
               "<$1 $3>", RegexOptions.Singleline | RegexOptions.IgnoreCase);

...这不起作用,我尝试了一些变体。基本上我想要这样......

<p style="font-style: italic" onclick="alert('hacked!!');">Hello World</p>

变成了……

<p style="font-style: italic">Hello World</p>

有什么想法吗?干杯!

【问题讨论】:

标签: c# asp.net regex richtextbox xss


【解决方案1】:

试试这个正则表达式:


returnValue = 
    Regex.Replace(
        returnValue,
        @"(<[\s\S]*?) on.*?\=(['""])[\s\S]*?\2([\s\S]*?>)", 
        delegate(Match match)
        {
            return String.Concat(match.Groups[1].Value, match.Groups[3].Value);
        }, RegexOptions.Compiled | RegexOptions.IgnoreCase);

HTH

【讨论】:

  • 哇!几乎完美,除非 onclick 属性在单个元素中出现两次,它只会删除其中一个。我已经使用 Regex.IsMatch( 和你的表达式将该代码卡在一个 while 循环中,它似乎可以工作。我将在这个问题的单独帖子中发布代码,因为代码示例在这些 cmets 中表现不佳.
【解决方案2】:

您可以存储旧的返回值,然后在 while 循环中进行检查以查看是否没有任何变化,如果如此,则跳出循环

if(oldContent.Equals(newContent)) { break; }

【讨论】:

    【解决方案3】:

    这是对“Rubens Farias”回答的回应,其中包含我提出的代码示例。我像这样使用了一个while循环......

    while (Regex.IsMatch(returnVal, @"(<[\s\S]*?) on.*?\=(['""])[\s\S]*?\2([\s\S]*?>)", RegexOptions.Compiled | RegexOptions.IgnoreCase))
    {
        returnVal = Regex.Replace(returnVal, @"(<[\s\S]*?) on.*?\=(['""])[\s\S]*?\2([\s\S]*?>)",
                        delegate(Match match)
                        {
                            return String.Concat(match.Groups[1].Value, match.Groups[3].Value);
                        }, RegexOptions.Compiled | RegexOptions.IgnoreCase);
    }
    

    对于那些感兴趣的人,这是我用来帮助防止 XSS 的整个方法...

    /// <summary>
    ///     'Helps' protect against XSS (Cross Site Scripting attacks) by stripping out known evil HTML elements
    ///     such as script and style. Used for outputing text generated by a Rich Text Editor. Doesn't HTML encode!
    /// </summary>
    /// <param name="input">Input string to strip bad HTML elements from</param>
    public static string XSSProtect(string input)
    {
        string returnVal = input ?? "";
    
        returnVal = Regex.Replace(returnVal, @"\<script(.*?)\>(.*?)\<\/script(.*?)\>", "", RegexOptions.Singleline | RegexOptions.IgnoreCase);
        returnVal = Regex.Replace(returnVal, @"\<style(.*?)\>(.*?)\<\/style(.*?)\>", "", RegexOptions.Singleline | RegexOptions.IgnoreCase);
    
        while (Regex.IsMatch(returnVal, @"(<[\s\S]*?) on.*?\=(['""])[\s\S]*?\2([\s\S]*?>)", RegexOptions.Compiled | RegexOptions.IgnoreCase))
        {
            returnVal = Regex.Replace(returnVal, @"(<[\s\S]*?) on.*?\=(['""])[\s\S]*?\2([\s\S]*?>)",
                            delegate(Match match)
                            {
                                return String.Concat(match.Groups[1].Value, match.Groups[3].Value);
                            }, RegexOptions.Compiled | RegexOptions.IgnoreCase);
        }
    
        return returnVal;
    }
    

    【讨论】:

    • 我必须承认我对这种方法有点紧张,有没有可能导致无限循环的情况?
    • 我也不舒服;您还应该在 = 符号之后和之前添加一个额外的 \s*,避免 onclick = "alert()"
    【解决方案4】:

    像这样。

    if (!String.prototype.replaceAll) {
      (function() {
        String.prototype.replaceAll = function(target, replacement) {
          return this.split(target).join(replacement);
        };
      })();
    };
    
    html = html.replaceAll(/onclick.*?\=(['""])[\s\S]*(['""])/ig,"");
    console.log(html);

    结果:&lt;p style="font-style: italic"&gt;Hello World&lt;/p&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-07
      • 2020-12-04
      • 2012-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-22
      相关资源
      最近更新 更多