Безопасность C# приложений: топ-10 уязвимостей и защита в .NET

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

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

Начать курс

Безопасность C# приложений: топ-10 уязвимостей и методы защиты в .NET

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

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

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

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

string query = "SELECT * FROM Users WHERE Username = '" + username + "'";
SqlCommand cmd = new SqlCommand(query, connection);

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

string query = "SELECT * FROM Users WHERE Username = @username";
SqlCommand cmd = new SqlCommand(query, connection);
cmd.Parameters.AddWithValue("@username", username);

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

Атака, при которой злоумышленник внедряет вредоносный скрипт в веб-страницу. В ASP.NET Core важно кодировать вывод.

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

<div>@Model.UserInput</div>

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

<div>@Html.Encode(Model.UserInput)</div>
// Или в ASP.NET Core используйте @Model.UserInput, если не используете HtmlString

В ASP.NET Core Razor по умолчанию кодирует вывод, но при использовании @Html.Raw() или возврате ContentResult с непроверенными данными риск возвращается.

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

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

Защита в ASP.NET Core:

// В ConfigureServices
services.AddAntiforgery(options => options.HeaderName = "X-CSRF-TOKEN");

// В контроллере
[AutoValidateAntiforgeryToken]
public class AccountController : Controller
{
    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult ChangePassword(ChangePasswordModel model)
    {
        // код
    }
}

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

Опасная уязвимость, особенно при использовании BinaryFormatter, SoapFormatter или Newtonsoft.Json с TypeNameHandling.All.

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

var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
var obj = JsonConvert.DeserializeObject(json, settings);

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

// Используйте System.Text.Json (по умолчанию безопасен)
var obj = JsonSerializer.Deserialize<MyType>(json);
// Или ограничьте TypeNameHandling в Newtonsoft
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.None };

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

Включает слабые пароли, отсутствие блокировки аккаунта, незащищенные куки.

Рекомендации:

  • Используйте ASP.NET Core Identity с политиками паролей.
  • Настройте защиту куки: HttpOnly, Secure, SameSite.
  • Включите блокировку после N неудачных попыток.
services.ConfigureApplicationCookie(options =>
{
    options.Cookie.HttpOnly = true;
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    options.Cookie.SameSite = SameSiteMode.Strict;
    options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
    options.SlidingExpiration = true;
});

6. Раскрытие чувствительных данных

Хранение паролей в открытом виде, передача данных по HTTP, логирование секретов.

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

// Хеширование паролей
var passwordHasher = new PasswordHasher<User>();
string hash = passwordHasher.HashPassword(user, password);

// Использование Data Protection API для шифрования
var protector = dataProtectionProvider.CreateProtector("MyApp.Secrets");
string encrypted = protector.Protect(secret);

7. Некорректная обработка ошибок и исключений

Вывод стека вызовов или внутренних деталей в production-среде.

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

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

8. Раскрытие информации через HTTP-заголовки

Заголовки Server, X-AspNet-Version, X-Powered-By могут выдать версию фреймворка.

Защита:

// Удаление заголовка Server
webBuilder.UseKestrel(options => options.AddServerHeader = false);

// В ASP.NET Core
builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.AddServerHeader = false;
});

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

Библиотеки с известными CVE (Common Vulnerabilities and Exposures).

Рекомендации:

  • Регулярно обновляйте NuGet-пакеты.
  • Используйте dotnet list package --vulnerable для проверки.
  • Настройте Dependabot или аналогичные инструменты.

10. Недостаточная защита API и эндпоинтов

Отсутствие rate limiting, проверки прав доступа, валидации входных данных.

Безопасный код (rate limiting в .NET 7+):

builder.Services.AddRateLimiter(options =>
{
    options.AddFixedWindowLimiter("Fixed", opt =>
    {
        opt.PermitLimit = 10;
        opt.Window = TimeSpan.FromMinutes(1);
    });
});                

Блоги

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