[Asp.Net Core] 网站中的XSS跨站脚本攻击和防范

漏洞说明: 跨站脚本攻击(Cross Site Scripting),为了不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。恶意攻击者往Web页面里插入恶意Web脚本代码(html、javascript、css等),当用户浏览该页面时,嵌入其中的Web脚本代码会被执行,从而达到恶意攻击用户的特殊目的。

测试步骤 访问系统网站,点击基础报告库进行编辑,使用Burp抓包并重新构造数据包

重新访问,成功触发了XSS弹窗

解决方法:

将危险内容过滤去除,用HTML转义字符串(Escape Sequence)表达的则保留 添加脚本过滤类

代码语言:javascript
复制
    /// <summary>
    /// Html 脚本过滤
    /// </summary>
    public class NHtmlFilter
    {
        protected static readonly RegexOptions REGEX_FLAGS_SI = RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled;
    private static string P_COMMENTS = &#34;&lt;!--(.*?)--&gt;&#34;;
    private static Regex P_COMMENT = new Regex(&#34;^!--(.*)--$&#34;, REGEX_FLAGS_SI);
    private static string P_TAGS = &#34;&lt;(.*?)&gt;&#34;;
    private static Regex P_END_TAG = new Regex(&#34;^/([a-z0-9]+)&#34;, REGEX_FLAGS_SI);
    private static Regex P_START_TAG = new Regex(&#34;^([a-z0-9]+)(.*?)(/?)$&#34;, REGEX_FLAGS_SI);
    private static Regex P_QUOTED_ATTRIBUTES = new Regex(&#34;([a-z0-9|(a-z0-9\\-a-z0-9)]+)=([\&#34;&#39;])(.*?)\\2&#34;, REGEX_FLAGS_SI);
    private static Regex P_UNQUOTED_ATTRIBUTES = new Regex(&#34;([a-z0-9]+)(=)([^\&#34;\\s&#39;]+)&#34;, REGEX_FLAGS_SI);
    private static Regex P_PROTOCOL = new Regex(&#34;^([^:]+):&#34;, REGEX_FLAGS_SI);
    private static Regex P_ENTITY = new Regex(&#34;&amp;#(\\d+);?&#34;);
    private static Regex P_ENTITY_UNICODE = new Regex(&#34;&amp;#x([0-9a-f]+);?&#34;);
    private static Regex P_ENCODE = new Regex(&#34;%([0-9a-f]{2});?&#34;);
    private static Regex P_VALID_ENTITIES = new Regex(&#34;&amp;([^&amp;;]*)(?=(;|&amp;|$))&#34;);
    private static Regex P_VALID_QUOTES = new Regex(&#34;(&gt;|^)([^&lt;]+?)(&lt;|$)&#34;, RegexOptions.Singleline | RegexOptions.Compiled);
    private static string P_END_ARROW = &#34;^&gt;&#34;;
    private static string P_BODY_TO_END = &#34;&lt;([^&gt;]*?)(?=&lt;|$)&#34;;
    private static string P_XML_CONTENT = &#34;(^|&gt;)([^&lt;]*?)(?=&gt;)&#34;;
    private static string P_STRAY_LEFT_ARROW = &#34;&lt;([^&gt;]*?)(?=&lt;|$)&#34;;
    private static string P_STRAY_RIGHT_ARROW = &#34;(^|&gt;)([^&lt;]*?)(?=&gt;)&#34;;
    private static string P_AMP = &#34;&amp;&#34;;
    private static string P_QUOTE = &#34;\&#34;&#34;;
    private static string P_LEFT_ARROW = &#34;&lt;&#34;;
    private static string P_RIGHT_ARROW = &#34;&gt;&#34;;
    private static string P_BOTH_ARROWS = &#34;&lt;&gt;&#34;;

    // @xxx could grow large... maybe use sesat&#39;s ReferenceMap
    private static Dictionary&lt;string, string&gt; P_REMOVE_PAIR_BLANKS = new Dictionary&lt;string, string&gt;();
    private static Dictionary&lt;string, string&gt; P_REMOVE_SELF_BLANKS = new Dictionary&lt;string, string&gt;();
    /** 
     * flag determining whether to try to make tags when presented with &#34;unbalanced&#34;
     * angle brackets (e.g. &#34;&lt;b text &lt;/b&gt;&#34; becomes &#34;&lt;b&gt; text &lt;/b&gt;&#34;).  If set to false,
     * unbalanced angle brackets will be html escaped.
     */
    protected static bool alwaysMakeTags = true;

    /**
     * flag determing whether comments are allowed in input String.
     */
    protected static bool stripComment = true;


    /// &lt;summary&gt;
    /// 不允许
    /// &lt;/summary&gt;
    private string[] vDisallowed { get; set; }
    /// &lt;summary&gt;
    /// 允许
    /// &lt;/summary&gt;
    protected Dictionary&lt;string, List&lt;string&gt;&gt; vAllowed { get; set; }

    /** counts of open tags for each (allowable) html element **/
    protected Dictionary&lt;string, int&gt; vTagCounts;

    /** html elements which must always be self-closing (e.g. &#34;&lt;img /&gt;&#34;) **/
    protected string[] vSelfClosingTags;

    /** html elements which must always have separate opening and closing tags (e.g. &#34;&lt;b&gt;&lt;/b&gt;&#34;) **/
    protected string[] vNeedClosingTags;

    /** attributes which should be checked for valid protocols **/
    protected string[] vProtocolAtts;

    /** allowed protocols **/
    protected string[] vAllowedProtocols;

    /** tags which should be removed if they contain no content (e.g. &#34;&lt;b&gt;&lt;/b&gt;&#34; or &#34;&lt;b /&gt;&#34;) **/
    protected string[] vRemoveBlanks;

    /** entities allowed within html markup **/
    protected string[] vAllowedEntities;


    /// &lt;summary&gt;
    /// 是否为调试
    /// &lt;/summary&gt;
    protected bool vDebug;

    public NHtmlFilter() : this(false) { }

    public NHtmlFilter(bool debug)
    {
        //List&lt;Item&gt; vAllowed = new List&lt;Item&gt;();
        vAllowed = new Dictionary&lt;string, List&lt;string&gt;&gt;();
        #region 允许通过数组

        vAllowed.Add(&#34;a&#34;, new List&lt;string&gt;() { &#34;target&#34;, &#34;href&#34;, &#34;title&#34;, &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;addr&#34;, new List&lt;string&gt;() { &#34;title&#34;, &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;address&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;area&#34;, new List&lt;string&gt;() { &#34;shape&#34;, &#34;coords&#34;, &#34;href&#34;, &#34;alt&#34; });
        vAllowed.Add(&#34;article&#34;, new List&lt;string&gt;() { });
        vAllowed.Add(&#34;aside&#34;, new List&lt;string&gt;() { });
        vAllowed.Add(&#34;audio&#34;, new List&lt;string&gt;() { &#34;autoplay&#34;, &#34;controls&#34;, &#34;loop&#34;, &#34;preload&#34;, &#34;src&#34;, &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;b&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;bdi&#34;, new List&lt;string&gt;() { &#34;dir&#34; });
        vAllowed.Add(&#34;bdo&#34;, new List&lt;string&gt;() { &#34;dir&#34; });
        vAllowed.Add(&#34;big&#34;, new List&lt;string&gt;() { });
        vAllowed.Add(&#34;blockquote&#34;, new List&lt;string&gt;() { &#34;cite&#34;, &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;br&#34;, new List&lt;string&gt;() { });
        vAllowed.Add(&#34;caption&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;center&#34;, new List&lt;string&gt;() { });
        vAllowed.Add(&#34;cite&#34;, new List&lt;string&gt;() { });
        vAllowed.Add(&#34;code&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;col&#34;, new List&lt;string&gt;() { &#34;align&#34;, &#34;valign&#34;, &#34;span&#34;, &#34;width&#34;, &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;colgroup&#34;, new List&lt;string&gt;() { &#34;align&#34;, &#34;valign&#34;, &#34;span&#34;, &#34;width&#34;, &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;dd&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;del&#34;, new List&lt;string&gt;() { &#34;datetime&#34; });
        vAllowed.Add(&#34;details&#34;, new List&lt;string&gt;() { &#34;open&#34; });
        vAllowed.Add(&#34;div&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;dl&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;dt&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;em&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;font&#34;, new List&lt;string&gt;() { &#34;color&#34;, &#34;size&#34;, &#34;face&#34; });
        vAllowed.Add(&#34;footer&#34;, new List&lt;string&gt;() { });
        vAllowed.Add(&#34;h1&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;h2&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;h3&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;h4&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;h5&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;h6&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;header&#34;, new List&lt;string&gt;() { });
        vAllowed.Add(&#34;hr&#34;, new List&lt;string&gt;() { });
        vAllowed.Add(&#34;i&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;img&#34;, new List&lt;string&gt;() { &#34;src&#34;, &#34;alt&#34;, &#34;title&#34;, &#34;style&#34;, &#34;width&#34;, &#34;height&#34;, &#34;id&#34;, &#34;_src&#34;, &#34;loadingclass&#34;, &#34;class&#34;, &#34;data-latex&#34;, &#34;data-id&#34;, &#34;data-type&#34;, &#34;data-s&#34; });
        vAllowed.Add(&#34;ins&#34;, new List&lt;string&gt;() { &#34;datetime&#34; });
        vAllowed.Add(&#34;li&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;mark&#34;, new List&lt;string&gt;() { });
        vAllowed.Add(&#34;nav&#34;, new List&lt;string&gt;() { });
        vAllowed.Add(&#34;ol&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;p&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;pre&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;s&#34;, new List&lt;string&gt;() { });
        vAllowed.Add(&#34;section&#34;, new List&lt;string&gt;() { });
        vAllowed.Add(&#34;small&#34;, new List&lt;string&gt;() { });
        vAllowed.Add(&#34;span&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;sub&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;sup&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;strong&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;table&#34;, new List&lt;string&gt;() { &#34;width&#34;, &#34;border&#34;, &#34;align&#34;, &#34;valign&#34;, &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;tbody&#34;, new List&lt;string&gt;() { &#34;align&#34;, &#34;valign&#34;, &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;td&#34;, new List&lt;string&gt;() { &#34;width&#34;, &#34;rowspan&#34;, &#34;colspan&#34;, &#34;align&#34;, &#34;valign&#34;, &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;tfoot&#34;, new List&lt;string&gt;() { &#34;align&#34;, &#34;valign&#34;, &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;th&#34;, new List&lt;string&gt;() { &#34;width&#34;, &#34;rowspan&#34;, &#34;colspan&#34;, &#34;align&#34;, &#34;valign&#34;, &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;thead&#34;, new List&lt;string&gt;() { &#34;align&#34;, &#34;valign&#34;, &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;tr&#34;, new List&lt;string&gt;() { &#34;rowspan&#34;, &#34;align&#34;, &#34;valign&#34;, &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;tt&#34;, new List&lt;string&gt;() { });
        vAllowed.Add(&#34;u&#34;, new List&lt;string&gt;() { });
        vAllowed.Add(&#34;ul&#34;, new List&lt;string&gt;() { &#34;class&#34;, &#34;style&#34; });
        vAllowed.Add(&#34;video&#34;, new List&lt;string&gt;() { &#34;autoplay&#34;, &#34;controls&#34;, &#34;loop&#34;, &#34;preload&#34;, &#34;src&#34;, &#34;height&#34;, &#34;width&#34;, &#34;class&#34;, &#34;style&#34; });
        #endregion


        vDebug = debug;
        vTagCounts = new Dictionary&lt;string, int&gt;();

        vSelfClosingTags = new string[] { &#34;img&#34; };
        vNeedClosingTags = new string[] { &#34;a&#34;, &#34;b&#34;, &#34;strong&#34;, &#34;i&#34;, &#34;em&#34; };
        vDisallowed = new string[] { &#34;script&#34; };
        vAllowedProtocols = new string[] { &#34;http&#34;, &#34;mailto&#34; }; // no ftp.
        vProtocolAtts = new string[] { &#34;src&#34;, &#34;href&#34; };
        vRemoveBlanks = new string[] { &#34;a&#34;, &#34;b&#34;, &#34;strong&#34;, &#34;i&#34;, &#34;em&#34; };
        vAllowedEntities = new string[] { &#34;amp&#34;, &#34;gt&#34;, &#34;lt&#34;, &#34;quot&#34; };
        stripComment = true;
        alwaysMakeTags = true;
    }


    protected void reset()
    {
        vTagCounts = new Dictionary&lt;string, int&gt;();
    }

    protected void debug(string msg)
    {
        if (vDebug)
            System.Diagnostics.Debug.WriteLine(msg);
    }

    //---------------------------------------------------------------
    // my versions of some PHP library functions

    public static string chr(int dec)
    {
        return &#34;&#34; + (char)dec;
    }

    /// &lt;summary&gt;
    /// 转换成实体字符
    /// &lt;/summary&gt;
    /// &lt;param name=&#34;str&#34;&gt;&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public static string htmlSpecialChars(string str)
    {
        str = str.Replace(P_QUOTE, &#34;\&#34;&#34;);

        str = str.Replace(P_LEFT_ARROW, &#34;&lt;&#34;);
        str = str.Replace(P_RIGHT_ARROW, &#34;&gt;&#34;);
        str = str.Replace(&#34;\n&#34;, &#34;&lt;br&gt;&#34;);
        return str;
    }

    //---------------------------------------------------------------

    /**
     * given a user submitted input String, filter out any invalid or restricted
     * html.
     * 
     * @param input text (i.e. submitted by a user) than may contain html
     * @return &#34;clean&#34; version of input, with only valid, whitelisted html elements allowed
     */
    public string filter(string input)
    {
        reset();
        string s = input;

        debug(&#34;************************************************&#34;);
        debug(&#34;              INPUT: &#34; + input);

        s = escapeComments(s);
        debug(&#34;     escapeComments: &#34; + s);

        s = balanceHTML(s);
        debug(&#34;        balanceHTML: &#34; + s);

        s = checkTags(s);
        debug(&#34;          checkTags: &#34; + s);

        s = processRemoveBlanks(s);
        debug(&#34;processRemoveBlanks: &#34; + s);

        s = validateEntities(s);
        debug(&#34;    validateEntites: &#34; + s);

        debug(&#34;************************************************\n\n&#34;);
        return s;
    }

    protected string escapeComments(string s)
    {
        return Regex.Replace(s, P_COMMENTS, new MatchEvaluator(ConverMatchComments), RegexOptions.Singleline);
    }

    protected string regexReplace(string regex_pattern, string replacement, string s)
    {
        return Regex.Replace(s, regex_pattern, replacement);
    }

    protected string balanceHTML(string s)
    {
        if (alwaysMakeTags)
        {
            //
            // try and form html
            //
            s = regexReplace(P_END_ARROW, &#34;&#34;, s);
            s = regexReplace(P_BODY_TO_END, &#34;&lt;$1&gt;&#34;, s);
            s = regexReplace(P_XML_CONTENT, &#34;$1&lt;$2&#34;, s);

        }
        else
        {
            //
            // escape stray brackets
            //
            s = regexReplace(P_STRAY_LEFT_ARROW, &#34;&lt;$1&#34;, s);
            s = regexReplace(P_STRAY_RIGHT_ARROW, &#34;$1$2&gt;&lt;&#34;, s);

            //
            // the last regexp causes &#39;&lt;&gt;&#39; entities to appear
            // (we need to do a lookahead assertion so that the last bracket can
            // be used in the next pass of the regexp)
            //
            s = s.Replace(P_BOTH_ARROWS, &#34;&#34;);
        }
        return s;
    }

    protected string checkTags(string s)
    {
        //替换不允许标签
        foreach (var item in vDisallowed)
        {
            s = Regex.Replace(s, string.Format(@&#34;&lt;{0}\b(.)*?&gt;(.)+?&lt;/{0}&gt;&#34;, item), &#34;&#34;);
        }
        s = Regex.Replace(s, P_TAGS, new MatchEvaluator(ConverMatchTags), RegexOptions.Singleline);

        // these get tallied in processTag
        // (remember to reset before subsequent calls to filter method)
        foreach (string key in vTagCounts.Keys)
        {
            for (int ii = 0; ii &lt; vTagCounts[key]; ii++)
            {
                s += &#34;&lt;/&#34; + key + &#34;&gt;&#34;;
            }
        }

        return s;
    }

    protected string processRemoveBlanks(string s)
    {
        foreach (string tag in vRemoveBlanks)
        {
            s = regexReplace(&#34;&lt;&#34; + tag + &#34;(\\s[^&gt;]*)?&gt;&lt;/&#34; + tag + &#34;&gt;&#34;, &#34;&#34;, s);
            s = regexReplace(&#34;&lt;&#34; + tag + &#34;(\\s[^&gt;]*)?/&gt;&#34;, &#34;&#34;, s);
        }
        return s;
    }

    private string processTag(string s)
    {
        // ending tags
        Match m = P_END_TAG.Match(s);
        if (m.Success)
        {
            string name = m.Groups[1].Value.ToLower();
            if (allowed(name))
            {
                if (!inArray(name, vSelfClosingTags))
                {
                    if (vTagCounts.ContainsKey(name))
                    {
                        vTagCounts[name] = vTagCounts[name] - 1;
                        return &#34;&lt;/&#34; + name + &#34;&gt;&#34;;
                    }
                }
            }
        }


        // starting tags
        m = P_START_TAG.Match(s);
        if (m.Success)
        {
            string name = m.Groups[1].Value.ToLower();
            string body = m.Groups[2].Value;
            string ending = m.Groups[3].Value;

            //debug( &#34;in a starting tag, name=&#39;&#34; + name + &#34;&#39;; body=&#39;&#34; + body + &#34;&#39;; ending=&#39;&#34; + ending + &#34;&#39;&#34; );
            if (allowed(name))
            {
                string params1 = &#34;&#34;;

                MatchCollection m2 = P_QUOTED_ATTRIBUTES.Matches(body);
                MatchCollection m3 = P_UNQUOTED_ATTRIBUTES.Matches(body);
                List&lt;string&gt; paramNames = new List&lt;string&gt;();
                List&lt;string&gt; paramValues = new List&lt;string&gt;();
                foreach (Match match in m2)
                {
                    paramNames.Add(match.Groups[1].Value); //([a-z0-9]+)
                    paramValues.Add(match.Groups[3].Value); //(.*?)
                }
                foreach (Match match in m3)
                {
                    paramNames.Add(match.Groups[1].Value); //([a-z0-9]+)
                    paramValues.Add(match.Groups[3].Value); //([^\&#34;\\s&#39;]+)
                }

                string paramName, paramValue;
                for (int ii = 0; ii &lt; paramNames.Count; ii++)
                {
                    paramName = paramNames[ii].ToLower();
                    paramValue = paramValues[ii];

                    if (allowedAttribute(name, paramName))
                    {
                        if (inArray(paramName, vProtocolAtts))
                        {
                            paramValue = processParamProtocol(paramValue);
                        }
                        params1 += &#34; &#34; + paramName + &#34;=\&#34;&#34; + paramValue + &#34;\&#34;&#34;;
                    }
                }

                if (inArray(name, vSelfClosingTags))
                {
                    ending = &#34; /&#34;;
                }

                if (inArray(name, vNeedClosingTags))
                {
                    ending = &#34;&#34;;
                }

                if (ending == null || ending.Length &lt; 1)
                {
                    if (vTagCounts.ContainsKey(name))
                    {
                        vTagCounts[name] = vTagCounts[name] + 1;
                    }
                    else
                    {
                        vTagCounts.Add(name, 1);
                    }
                }
                else
                {
                    ending = &#34; /&#34;;
                }
                return &#34;&lt;&#34; + name + params1 + ending + &#34;&gt;&#34;;
            }
            else
            {
                return &#34;&#34;;
            }
        }

        // comments
        m = P_COMMENT.Match(s);
        if (!stripComment &amp;&amp; m.Success)
        {
            return &#34;&lt;&#34; + m.Value + &#34;&gt;&#34;;
        }

        return &#34;&#34;;
    }

    private string processParamProtocol(string s)
    {
        s = decodeEntities(s);
        Match m = P_PROTOCOL.Match(s);
        if (m.Success)
        {
            string protocol = m.Groups[1].Value;
            if (!inArray(protocol, vAllowedProtocols))
            {
                // bad protocol, turn into local anchor link instead
                s = &#34;#&#34; + s.Substring(protocol.Length + 1, s.Length - protocol.Length - 1);
                if (s.StartsWith(&#34;#//&#34;))
                {
                    s = &#34;#&#34; + s.Substring(3, s.Length - 3);
                }
            }
        }
        return s;
    }

    private string decodeEntities(string s)
    {

        s = P_ENTITY.Replace(s, new MatchEvaluator(ConverMatchEntity));

        s = P_ENTITY_UNICODE.Replace(s, new MatchEvaluator(ConverMatchEntityUnicode));

        s = P_ENCODE.Replace(s, new MatchEvaluator(ConverMatchEntityUnicode));

        s = validateEntities(s);
        return s;
    }

    private string validateEntities(string s)
    {
        s = P_VALID_ENTITIES.Replace(s, new MatchEvaluator(ConverMatchValidEntities));
        s = P_VALID_QUOTES.Replace(s, new MatchEvaluator(ConverMatchValidQuotes));
        return s;
    }

    private static bool inArray(string s, string[] array)
    {
        foreach (string item in array)
        {
            if (item != null &amp;&amp; item.Equals(s))
            {
                return true;
            }
        }
        return false;
    }

    private bool allowed(string name)
    {
        return (vAllowed.Count == 0 || vAllowed.ContainsKey(name)) &amp;&amp; !inArray(name, vDisallowed);
    }

    private bool allowedAttribute(string name, string paramName)
    {
        return allowed(name) &amp;&amp; (vAllowed.Count == 0 || vAllowed[name].Contains(paramName));
    }

    private string checkEntity(string preamble, string term)
    {

        return &#34;;&#34;.Equals(term) &amp;&amp; isValidEntity(preamble)
                ? &#39;&amp;&#39; + preamble
                : &#34;&amp;&#34; + preamble;
    }
    private bool isValidEntity(string entity)
    {
        return inArray(entity, vAllowedEntities);
    }
    private static string ConverMatchComments(Match match)
    {
        string matchValue = &#34;&lt;!--&#34; + htmlSpecialChars(match.Groups[1].Value) + &#34;--&gt;&#34;;
        return matchValue;
    }

    private string ConverMatchTags(Match match)
    {
        string matchValue = processTag(match.Groups[1].Value);
        return matchValue;
    }

    private string ConverMatchEntity(Match match)
    {
        string v = match.Groups[1].Value;
        int decimal1 = int.Parse(v);
        return chr(decimal1);
    }

    private string ConverMatchEntityUnicode(Match match)
    {
        string v = match.Groups[1].Value;
        int decimal1 = Convert.ToInt32(&#34;0x&#34; + v, 16);
        return chr(decimal1);
    }

    private string ConverMatchValidEntities(Match match)
    {
        string one = match.Groups[1].Value; //([^&amp;;]*)
        string two = match.Groups[2].Value; //(?=(;|&amp;|$))
        return checkEntity(one, two);
    }
    private string ConverMatchValidQuotes(Match match)
    {
        string one = match.Groups[1].Value; //(&gt;|^)
        string two = match.Groups[2].Value; //([^&lt;]+?)
        string three = match.Groups[3].Value;//(&lt;|$)
        return one + regexReplace(P_QUOTE, &#34;\&#34;&#34;, two) + three;
    }

    public bool isAlwaysMakeTags()
    {
        return alwaysMakeTags;
    }

    public bool isStripComments()
    {
        return stripComment;
    }

    class Item
    {
        public string name { get; set; }
        public List&lt;string&gt; parameter { get; set; }
    }

}

在请求时对参数的内容进行过滤:

代码语言:javascript
复制
var nHtmlFilter = new NHtmlFilter(false);
surveyPayload.PayloadContent = nHtmlFilter.filter(surveyPayload.PayloadContent);

再次请求时,已将危险代码转成HTML转义字符串的形式了