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:

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

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:

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);

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("<b>", "<b>");
sb.Replace("</b>", "</b>");
sb.Replace("<i>", "<i>");
sb.Replace("</i>", "</i>");
literalXss.Text = "Twój wpis to: " + sb.ToString();

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,
@"(<[\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 result;
}
Jej użycie jest bardzo proste:
literalXss.Text = "Twój wpis to: " + RemoveXss(textBoxXss.Text);


