Защита ASP.NET приложений от взлома

ASP.NET MVC — не самый хайповый, но довольно популярный стек в среде веб-разработчиков. С точки зрения (анти)хакера, его стандартная функциональность дает тебе кое-какой базовый уровень безопасности, но для предохранения от абсолютного большинства хакерских трюков нужна дополнительная защита. В этой статье мы рассмотрим основы, которые должен знать о безопасности ASP.NET-разработчик (будь то Core, MVC, MVC Razor или Web Forms).


plyr8u235oyo1jfxc5d-vtkrgh4.jpeg


Примечание: мы продолжаем серию публикаций полных версий статей из журнала Хакер. Орфография и пунктуация автора сохранены.


Передаю слово автору.


Я думаю со мной согласятся многие, что ASP.NET MVC это стек довольно популярных технологий. Хоть технология давно не на пике хайпа, но спрос на .NET-овских веб-разработчиков довольно высок.


Вместе с тем, при разработке обязательно следует учитывать аспекты безопасности. Хоть какой-то функционал и спасает от классических всем известных атак, но от довольно большого количества хакерских трюков требуется дополнительная защита. Давайте рассмотрим популярные виды атак и способы защиты. Must know для ASP.NET разработчика (будь то Core, MVC, MVC Razor или WebForms).


Начнем со всем известных видов атак.


SQL Injection


Как ни странно, но в 2017-ом году Injection и в частности SQL Injection находится на первом месте среди Top-10 рисков безопасности OWASP (Open Web Application Security Project) Этот вид атаки подразумевает, что данные, введенные пользователем используются на серверной стороне в качестве параметров запроса.


Пример классической SQL инъекции скорее характерен именно для приложений Web Forms.
От атак помогает защититься использование параметров в качестве значений запроса:


string commandText = "UPDATE Users SET Status = 1 WHERE CustomerID = @ID;";
SqlCommand command = new SqlCommand(commandText, connectionString);
command.Parameters.AddWithValue("@ID", customerID);


Если вы разрабатываете MVC приложение, то Entity Framework прикрывает некоторые уязвимости. Для того, чтобы в MVC/EF приложении сработала SQL инъекция нужно умудриться. Однако это возможно если вы выполняете SQL код с помощью ExecuteQuery или вызываете плохо написанные хранимые процедуры.


Несмотря на то, что ORM позволяет избежать SQL Injection (за исключением приведенных выше примеров), рекомендуется ограничивать атрибутами значения, которые могут принимать поля модели, а значит и формы. Например, если подразумевается, что в поле может быть введен только текст, то с помощью Regex выражения укажите диапазон от ^[a-zA-Z]+$
Если в поле должны быть введены цифры, то укажите это как требование:


[RegularExpression(@"\d{5}", ErrorMessage = "Индекс должен содержать 5 цифр")]
public  string Zip {  get;  set; }


В WebForms ограничить возможные значения можно с помощью валидаторов. Пример:




Начиная с .NET 4.5 WebForms используют Unobtrusive Validation. А это значит, что не требуется написание какого-то дополнительного кода для проверки значения формы.


Валидация данных частности помочь защититься от еще одной всем известной уязвимости под названием Cross-Site Scripting (XSS).


XSS


Типичный пример XSS — добавление скрипта в комментарий или запись в гостевую книгу. Например, такого:



Как вы понимаете, в данном примере куки с вашего сайта передают в качестве параметра на какой-то хакерский сайт.


В Web Forms можно совершить ошибку с помощью примерно такого кода:


Извините <%= username %>, но пароль ошибочный


Понятно, что вместо username может быть скрипт. Чтобы избежать выполнения скрипта можно как минимум использовать другое ASP.NET выражение: <%: username %>, которое энкодит свое содержимое.


Если вы используете Razor, то строки автоматически энкодируются. Так что чтобы получить XSS нужно постараться и совершить ошибку. Например, использовать Html.Raw (Model.username). Или в вашей модели использовать MvcHtmlString вместо string


Для дополнительной защиты от XSS данные кодируются еще и в коде C#. В .NET Core можно использовать следующие кодеры из пространства имен System.Text.Encodings.Web: HtmlEncoder, JavaScriptEncoder и UrlEncoder


Следующий пример вернет строку »