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

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

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

Начать курс

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

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

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

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

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

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

Защита: Используйте параметризованные запросы или Entity Framework.

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

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

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

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

string comment = Request["comment"];
Response.Write("<div>" + comment + "</div>");

Защита: Всегда кодируйте вывод. Используйте HttpUtility.HtmlEncode():

string comment = Request["comment"];
Response.Write("<div>" + HttpUtility.HtmlEncode(comment) + "</div>");

3. Отсутствие аутентификации и авторизации

Многие новички забывают проверять права доступа к ресурсам. Например, пользователь может получить доступ к чужому профилю, просто изменив ID в URL.

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

public IActionResult Profile(int userId)
{
    var user = _context.Users.Find(userId);
    return View(user);
}

Защита: Всегда проверяйте, что текущий пользователь имеет право на запрошенный ресурс:

public IActionResult Profile(int userId)
{
    var currentUserId = User.FindFirst(ClaimTypes.NameIdentifier).Value;
    if (userId != currentUserId) return Forbid();
    var user = _context.Users.Find(userId);
    return View(user);
}

4. Утечка конфиденциальных данных через исключения

Разработчики часто выводят полную информацию об ошибках, включая стек вызовов и строки подключения.

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

try
{
    // код
}
catch (Exception ex)
{
    Response.Write(ex.ToString()); // ОПАСНО!
}

Защита: В продакшене используйте общие сообщения об ошибках, а детали логируйте в безопасное место:

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

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

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

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

string passwordHash = MD5.Hash(password); // НЕЛЬЗЯ!

Защита: Используйте современные алгоритмы хэширования с солью, например, BCrypt или ASP.NET Core Identity:

var passwordHasher = new PasswordHasher<IdentityUser>();
string passwordHash = passwordHasher.HashPassword(user, password);

6. Недостаточная защита от CSRF (Cross-Site Request Forgery)

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

Защита: В ASP.NET Core используйте антифоржные токены:

// В представлении
@Html.AntiForgeryToken()

// В контроллере
[ValidateAntiForgeryToken]
public IActionResult DeleteAccount() { ... }

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

При десериализации данных из ненадёжного источника злоумышленник может выполнить произвольный код.

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

var serializer = new BinaryFormatter();
using (var stream = new MemoryStream(data))
{
    var obj = serializer.Deserialize(stream); // ОПАСНО!
}

Защита: Избегайте BinaryFormatter, JavaScriptSerializer и LosFormatter. Используйте System.Text.Json с явной моделью:

var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
var user = JsonSerializer.Deserialize<UserDto>(json, options);

8. Небезопасное управление сессиями

Использование предсказуемых или незащищённых идентификаторов сессий, а также их хранение в URL.

Проблема: Сессионный ключ в URL легко перехватить или предугадать.

Защита:

  • Храните идентификатор сессии только в cookies с флагами HttpOnly и Secure.
  • Используйте случайные, длинные идентификаторы.
  • Настройте тайм-аут сессии.
services.AddSession(options =>
{
    options.Cookie.HttpOnly = true;
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    options.IdleTimeout = TimeSpan.FromMinutes(20);
});

9. Отсутствие проверки входных данных

Пользователь может отправить неожиданные данные: слишком длинные строки, отрицательные числа, специальные символы.

Защита: Используйте аннотации данных и валидацию на стороне сервера:

public class UserModel                

Блоги

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