Ataki XSS i formy obrony

Ataki XSS, polegają najczęściej na przekazaniu skryptu JavaScript, którego zadaniem jest zaszkodzić. Bronić się przed nimi można na wiele sposobów. W tym wpisie wykorzystuje ASP WebForms, ale wszystko co zostanie opisane można zastosować w aplikacjach ASP MVC.
Domyślnie strony ASP są chronione przed atakami XSS. Możemy się o tym przekonać budując prosty formularz z polem tekstowym w który można wpisać skrypt:

xss1

Przy próbie przesłania takiego formularza, serwer zwróci błąd:

xss2

Jest to spowodowane pewnym wpisem, lub jego brakiem (domyśla wartość true) w pliku web.config:
Niekiedy istnieje potrzeba wyłączenia tego mechanizmu (najczęściej na pojedynczych stronach w obrębie aplikacji), np. kiedy chcemy umożliwić użytkowniki formatowanie wpisów przy pomocy znacznik HTML.

Mam prosty formularz:

<form id="form1">
<div>Wpis</div>
</form>

 Jego obsługa:

protected void buttonSaveClick(Object sender, EventArgs e)
{
  if(!string.IsNullOrEmpty(textBoxXss.Text))
  {
    literalXss.Text = "Twój wpis to: " + textBoxXss.Text;
  }
}

Całość po wpisaniu skryptu JavaScript wygląda tak:

xss3

Jak się bronić? Jest wiele sposobów. Jednym z nich jest użycie funkcji Server.HtmlEncode:

literalXss.Text = "Twój wpis to: " + Server.HtmlEncode(textBoxXss.Text);
xss4

Jak widać działa, ale co zrobić gdy chcemy formatować tekst np. przy pomocy znaczników „<b>” czy „<i>”? Można zrobić taki trik:

StringBuilder sb = new StringBuilder(HttpUtility.HtmlEncode(textBoxXss.Text));
                
sb.Replace("&lt;b&gt;", "<b>");
sb.Replace("&lt;/b&gt;", "</b>");
sb.Replace("&lt;i&gt;", "<i>");
sb.Replace("&lt;/i&gt;", "</i>");

literalXss.Text = "Twój wpis to: " + sb.ToString();
xss5

Wybiórcze dodawanie dozwolonych tagów, może być nieco kłopotliwe, w miarę zwiększania ich ilości. Żeby temu zaradzić można napisać metodę RemoveXss, która wykorzystuje wyrażenia regularne:

public string RemoveXss(string input)
{
  string result = RemoveXssHtmlTags(input);
  result = RemoveOnXssAttribute(result);
  
  return result;
}

public string RemoveXssHtmlTags(string input)
{
  string result = Regex.Replace(
                input,
                @"<!--?(?i:applet|body|embed|frame|script|frameset|html|iframe|img|style|layer|link|ilayer|meta|object)(.|\n|\s)*?-->",
                string.Empty,
                RegexOptions.Singleline | RegexOptions.IgnoreCase
            );

  return result;
}

public string RemoveOnXssAttribute(string input)
{
  string result = Regex.Replace(
                input,
                @"(&lt;[\s\S]*?) on.*?\=(['""])[\s\S]*?\2([\s\S]*?&gt;)",
                delegate(Match match)
                {
                    return String.Concat(match.Groups[1].Value, match.Groups[3].Value);
                }, RegexOptions.Compiled | RegexOptions.IgnoreCase);

  return result;
}

Jej użycie jest bardzo proste:

literalXss.Text = "Twój wpis to: " + RemoveXss(textBoxXss.Text);
xss6
Share Button

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Time limit is exhausted. Please reload the CAPTCHA.