Безопасность 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);
});
});