Топ-10 уязвимостей C# приложений и как их избежать

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Безопасность C# приложений: топ-10 уязвимостей, которые должен знать каждый разработчик

Разработка на C# и платформе .NET — мощный инструмент для создания корпоративных и веб-приложений. Однако даже самый надежный код может содержать бреши, которые приведут к утечке данных, потере репутации и финансовым убыткам. В этой статье мы разберем 10 самых распространенных уязвимостей C# приложений, основанных на OWASP Top 10, с практическими примерами и способами защиты.

1. SQL-инъекции (SQL Injection)

Это одна из старейших, но до сих пор актуальных угроз. Уязвимость возникает, когда пользовательский ввод напрямую конкатенируется в SQL-запрос.

Уязвимый код:

string userName = Request.QueryString["name"];
string query = "SELECT * FROM Users WHERE Name = '" + userName + "'";
SqlCommand cmd = new SqlCommand(query, connection);

Безопасный код (параметризованные запросы):

string userName = Request.QueryString["name"];
string query = "SELECT * FROM Users WHERE Name = @name";
SqlCommand cmd = new SqlCommand(query, connection);
cmd.Parameters.AddWithValue("@name", userName);

Рекомендация: Всегда используйте параметризованные запросы или Entity Framework, который автоматически экранирует ввод.

2. Межсайтовый скриптинг (XSS)

XSS-атаки позволяют злоумышленнику внедрить вредоносный скрипт в веб-страницу. В C# это часто происходит при выводе непроверенных данных через @Html.Raw().

Уязвимый код:

@Html.Raw(Model.Comment)

Безопасный код (кодирование вывода):

@Html.Encode(Model.Comment)

Рекомендация: Используйте Razor-синтаксис @Model.Comment (он автоматически кодирует HTML) и никогда не применяйте @Html.Raw() без проверки.

3. Подделка межсайтовых запросов (CSRF)

CSRF заставляет авторизованного пользователя выполнить нежелательное действие на сайте (например, перевод денег). В ASP.NET Core защита встроена, но ее нужно правильно включить.

Уязвимый код (отсутствие антифоргового токена):

<form method="post" action="/Account/Delete">
    <button type="submit">Удалить аккаунт</button>
</form>

Безопасный код (с AntiForgeryToken):

<form method="post" action="/Account/Delete">
    @Html.AntiForgeryToken()
    <button type="submit">Удалить аккаунт</button>
</form>

Рекомендация: Добавьте атрибут [ValidateAntiForgeryToken] к вашим POST-методам и используйте @Html.AntiForgeryToken() в формах.

4. Небезопасное хранение паролей

Хранение паролей в открытом виде или с использованием слабых хешей (MD5, SHA1) — грубая ошибка.

Уязвимый код:

string passwordHash = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(password));

Безопасный код (использование bcrypt/Argon2):

using BCrypt.Net;
string passwordHash = BCrypt.HashPassword(password, workFactor: 12);

Рекомендация: Используйте библиотеки BCrypt.Net или Microsoft.AspNetCore.Identity, которые автоматически генерируют соль и используют современные алгоритмы.

5. Раскрытие конфиденциальных данных в исключениях

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

Уязвимый код (в production):

catch (Exception ex)
{
    return Content(ex.ToString());
}

Безопасный код:

catch (Exception ex)
{
    _logger.LogError(ex, "Ошибка при обработке запроса");
    return StatusCode(500, "Внутренняя ошибка сервера");
}

Рекомендация: Включите UseDeveloperExceptionPage() только в среде разработки. В production используйте глобальную обработку ошибок с логированием.

6. Небезопасная десериализация

Десериализация данных из ненадежных источников (например, из запроса) может привести к выполнению произвольного кода.

Уязвимый код:

var formatter = new BinaryFormatter();
using (var stream = Request.Body)
{
    var obj = formatter.Deserialize(stream);
}

Безопасный код (использование JSON с валидацией):

var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
var model = JsonSerializer.Deserialize<MyModel>(Request.Body, options);

Рекомендация: Избегайте BinaryFormatter, SoapFormatter и JavaScriptSerializer. Используйте System.Text.Json или Newtonsoft.Json с явными контрактами.

7. Использование уязвимых компонентов

Старые версии библиотек и фреймворков содержат известные CVE (Common Vulnerabilities and Exposures).

Пример проблемы:

Библиотека Newtonsoft.Json версии 12.0.1 имеет уязвимость, позволяющую выполнить десериализацию с произвольным кодом.

Решение:

// Обновление через NuGet Package Manager
Update-Package Newtonsoft.Json -Version 13.0.3

Рекомендация: Используйте dotnet list package --vulnerable для аудита и настройте автоматическое обновление через Dependabot или Renovate.

8. Недостатки аутентификации и управления сессиями

Слабые пароли, отсутствие MFA, неправильная настройка JWT и кук — частые проблемы.

Блоги

Рекомендаций по книгам