Очистить HTML-кодированный текст (#decimal нотация) из вывода AntiXSS v3 - PullRequest
2 голосов
/ 28 декабря 2008

Я завязываю комментировать в движке блога XSS-safe. Перепробовал много разных подходов, но найти это очень сложно.

Когда я отображаю комментарии, я впервые использую Microsoft AntiXss 3.0 для HTML-кодирования всего этого. Затем я пытаюсь html декодировать безопасные теги с использованием подхода белого списка.

Рассматривал пример Стива Даунинга в ветке Этвуда "Sanitize HTML" в refactormycode.

Моя проблема в том, что библиотека AntiXss кодирует значения в & # DECIMAL; нотации, и я не знаю, как переписать пример Стива, так как мои знания регулярных выражений ограничены.

Я попробовал следующий код, где я просто заменил сущности на десятичную форму, но она не работает должным образом.

< with <
> with >

Моя перезапись:

class HtmlSanitizer
{
    /// <summary>
    /// A regex that matches things that look like a HTML tag after HtmlEncoding.  Splits the input so we can get discrete
    /// chunks that start with &lt; and ends with either end of line or &gt;
    /// </summary>
    private static Regex _tags = new Regex("&#60;(?!&#62;).+?(&#62;|$)", RegexOptions.Singleline | RegexOptions.ExplicitCapture | RegexOptions.Compiled);


    /// <summary>
    /// A regex that will match tags on the whitelist, so we can run them through 
    /// HttpUtility.HtmlDecode
    /// FIXME - Could be improved, since this might decode &gt; etc in the middle of
    /// an a/link tag (i.e. in the text in between the opening and closing tag)
    /// </summary>
    private static Regex _whitelist = new Regex(@"
^&#60;/?(a|b(lockquote)?|code|em|h(1|2|3)|i|li|ol|p(re)?|s(ub|up|trong|trike)?|ul)&#62;$
|^&#60;(b|h)r\s?/?&#62;$
|^&#60;a(?!&#62;).+?&#62;$
|^&#60;img(?!&#62;).+?/?&#62;$",


      RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace |
      RegexOptions.ExplicitCapture | RegexOptions.Compiled);

    /// <summary>
    /// HtmlDecode any potentially safe HTML tags from the provided HtmlEncoded HTML input using 
    /// a whitelist based approach, leaving the dangerous tags Encoded HTML tags
    /// </summary>
    public static string Sanitize(string html)
    {

        string tagname = "";
        Match tag;
        MatchCollection tags = _tags.Matches(html);
        string safeHtml = "";

        // iterate through all HTML tags in the input
        for (int i = tags.Count - 1; i > -1; i--)
        {
            tag = tags[i];
            tagname = tag.Value.ToLowerInvariant();

            if (_whitelist.IsMatch(tagname))
            {
                // If we find a tag on the whitelist, run it through 
                // HtmlDecode, and re-insert it into the text
                safeHtml = HttpUtility.HtmlDecode(tag.Value);
                html = html.Remove(tag.Index, tag.Length);
                html = html.Insert(tag.Index, safeHtml);
            }

        }

        return html;
    }

}

Мой входной тестовый html:

<p><script language="javascript">alert('XSS')</script><b>bold should work</b></p>

После AntiXss оно превращается в:

&#60;p&#62;&#60;script language&#61;&#34;javascript&#34;&#62;alert&#40;&#39;XSS&#39;&#41;&#60;&#47;script&#62;&#60;b&#62;bold should work&#60;&#47;b&#62;&#60;&#47;p&#62;

Когда я запускаю версию Sanitize (строка html) выше, она дает мне:

<p><script language="javascript">alert&#40;&#39;XSS&#39;&#41;</script><b>bold should work</b></p>

Регулярное выражение соответствует сценарию из белого списка, который мне не нужен. Любая помощь с этим будет высоко ценится.

Ответы [ 5 ]

1 голос
/ 28 декабря 2008

Ваша проблема в том, что C # неправильно интерпретирует ваше регулярное выражение. Вам нужно уйти от знака #. Без побега это слишком много.

private static Regex _whitelist = new Regex(@"
    ^&\#60;(&\#47;)? (a|b(lockquote)?|code|em|h(1|2|3)|i|li|ol|p(re)?|s(ub|up|trong|trike)?|ul)&\#62;$
    |^&\#60;(b|h)r\s?(&\#47;)?&\#62;$
    |^&\#60;a(?!&\#62;).+?&\#62;$
    |^&\#60;img(?!&\#62;).+?(&\#47;)?&\#62;$",

    RegexOptions.Singleline |
    RegexOptions.IgnorePatternWhitespace |
    RegexOptions.ExplicitCapture 
    RegexOptions.Compiled
 );

Обновление 2: Вы можете быть заинтересованы в этом xss и regexp сайте.

1 голос
/ 28 декабря 2008

Да, я использую редактор WMD с уценкой, но я хочу, чтобы пользователи могли публиковать HTML и примеры кода, как в Stack Overflow, поэтому я не хочу полностью запрещать HTML.

Я просматривал HTML Tidy , но еще не пробовал. Однако я использую Html Agility Pack , чтобы убедиться, что HTML-код правильный (без лишних тегов). Это сделано до запуска AntiXss.

Я опробую HTML Tidy, если не смогу заставить свое текущее решение работать так, как мне нравится, спасибо за предложение.

1 голос
/ 28 декабря 2008

Рассматривали ли вы использование Markdown или VBCode или несколько подобных подходов, чтобы пользователи могли пометить свои комментарии? Тогда вы можете запретить весь HTML.

Если вам нужно разрешить HTML, я бы подумал об использовании HTML-парсера (в духе HTMLTidy) и сделал бы белый список там.

0 голосов
/ 28 декабря 2008

Я опубликую здесь полный код снова (слегка переработанный и с обновленными комментариями), если кто-то заинтересован в использовании этого.

Я также решил удалить тег img из белого списка, поскольку @Pez и @some указали, что это может быть опасно.

Также необходимо указать, что я не проверил это должным образом на предмет возможных атак XSS. Я просто хочу сказать, насколько хорошо работает этот метод.

class HtmlSanitizer
{
    /// <summary>
    /// A regex that matches things that look like a HTML tag after HtmlEncoding to &#DECIMAL; notation. Microsoft AntiXSS 3.0 can be used to preform this. Splits the input so we can get discrete
    /// chunks that start with &#60; and ends with either end of line or &#62;
    /// </summary>
    private static readonly Regex _tags = new Regex(@"&\#60;(?!&\#62;).+?(&\#62;|$)", RegexOptions.Singleline | RegexOptions.ExplicitCapture | RegexOptions.Compiled);


    /// <summary>
    /// A regex that will match tags on the whitelist, so we can run them through 
    /// HttpUtility.HtmlDecode
    /// FIXME - Could be improved, since this might decode &#60; etc in the middle of
    /// an a/link tag (i.e. in the text in between the opening and closing tag)
    /// </summary>

    private static readonly Regex _whitelist = new Regex(@"
^&\#60;(&\#47;)? (a|b(lockquote)?|code|em|h(1|2|3)|i|li|ol|p(re)?|s(ub|up|trong|trike)?|ul)&\#62;$
|^&\#60;(b|h)r\s?(&\#47;)?&\#62;$
|^&\#60;a(?!&\#62;).+?&\#62;$",


      RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace |
      RegexOptions.ExplicitCapture | RegexOptions.Compiled);

    /// <summary>
    /// HtmlDecode any potentially safe HTML tags from the provided HtmlEncoded HTML input using 
    /// a whitelist based approach, leaving the dangerous tags Encoded HTML tags
    /// </summary>
    public static string Sanitize(string html)
    {
        Match tag;
        MatchCollection tags = _tags.Matches(html);

        // iterate through all HTML tags in the input
        for (int i = tags.Count - 1; i > -1; i--)
        {
            tag = tags[i];
            string tagname = tag.Value.ToLowerInvariant();

            if (_whitelist.IsMatch(tagname))
            {
                // If we find a tag on the whitelist, run it through 
                // HtmlDecode, and re-insert it into the text
                string safeHtml = HttpUtility.HtmlDecode(tag.Value);
                html = html.Remove(tag.Index, tag.Length);
                html = html.Insert(tag.Index, safeHtml);
            }
        }
        return html;
    }
}
0 голосов
/ 28 декабря 2008

Я на Mac, поэтому я не могу проверить ваш код C #. Но мне кажется, что регулярное выражение _whitelist должно работать только с именами тегов. Это может означать, что вы должны сделать два прохода, один для открытия и один для закрытия тегов. Но это сделает это намного проще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...