Безопасность Java приложений: топ-10 уязвимостей и как их избежать

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

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

Начать курс

Введение: Почему безопасность Java-приложений — это не опция, а необходимость

Java остается одним из самых популярных языков для разработки корпоративных и веб-приложений. Однако популярность влечет за собой и повышенное внимание со стороны злоумышленников. По данным OWASP (Open Web Application Security Project), уязвимости в коде ежегодно приводят к утечкам данных и финансовым потерям на миллиарды долларов. В этой статье мы разберем топ-10 уязвимостей Java-приложений, покажем реальные примеры кода и дадим конкретные рекомендации по защите. Материал будет полезен как начинающим, так и опытным разработчикам, стремящимся писать безопасный код.

1. Инъекции: SQL, LDAP и Command Injection

Инъекции остаются королем уязвимостей. Самый частый случай — SQL-инъекция, когда пользовательский ввод напрямую конкатенируется в SQL-запрос.

Пример уязвимого кода

String query = "SELECT * FROM users WHERE username = '" + request.getParameter("user") + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);

Если злоумышленник передаст admin' OR '1'='1, он получит доступ ко всем пользователям.

Как защититься

  • Используйте PreparedStatement: параметризованные запросы автоматически экранируют ввод.
  • Валидируйте входные данные на стороне сервера (белые списки).
  • Для LDAP и команд ОС применяйте экранирование и избегайте вызова Runtime.exec() с пользовательскими данными.
// Безопасный вариант
String query = "SELECT * FROM users WHERE username = ?";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(1, request.getParameter("user"));
ResultSet rs = pstmt.executeQuery();

2. Нарушение аутентификации и управления сессиями

Слабая аутентификация — вторая по опасности уязвимость. Часто встречаются: отсутствие ограничения на количество попыток входа, хранение паролей в открытом виде, предсказуемые session ID.

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

  • Храните пароли только в виде хешей с солью (например, bcrypt или Argon2).
  • Используйте SecureRandom для генерации сессионных токенов.
  • Установите таймауты сессий и механизм «запомнить меня» с безопасным токеном.
// Генерация безопасного session ID
import java.security.SecureRandom;
String sessionId = new SecureRandom().ints(48, 122)
    .filter(i -> Character.isLetterOrDigit(i))
    .limit(64)
    .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
    .toString();

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

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

Пример уязвимости

<div>${userComment}</div>

Если userComment содержит <script>alert('XSS')</script>, код выполнится в браузере.

Защита

  • Экранируйте вывод: в JSP используйте c:out или fn:escapeXml().
  • Для Thymeleaf — th:utext опасен, используйте th:text.
  • Применяйте Content Security Policy (CSP) заголовки.

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

Java-десериализация — одна из самых критичных уязвимостей, позволяющая выполнить произвольный код (RCE). Злоумышленник может подменить поток байтов и внедрить вредоносный объект.

Пример атаки

ObjectInputStream ois = new ObjectInputStream(request.getInputStream());
Object obj = ois.readObject(); // Опасность!

Как защититься

  • Не десериализуйте данные из ненадежных источников.
  • Используйте белые списки классов (например, через ValidatingObjectInputStream из библиотеки Apache Commons IO).
  • Рассмотрите замену на JSON/XML (Jackson, Gson) с ограничением типов.
// Использование ValidatingObjectInputStream
ValidatingObjectInputStream vois = new ValidatingObjectInputStream(inputStream);
vois.accept(User.class, Order.class);
Object obj = vois.readObject();

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

CSRF-атака заставляет авторизованного пользователя выполнить нежелательное действие (например, перевод денег) без его ведома.

Защита

  • Используйте CSRF-токены в формах и AJAX-запросах.
  • Spring Security предоставляет встроенную защиту — включите csrf().enable().
  • Проверяйте заголовки Origin и Referer.

6. Небезопасная конфигурация

Уязвимости часто возникают из-за стандартных настроек: открытые порты, слабые пароли, включенные режимы отладки, устаревшие библиотеки.

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

  • Регулярно обновляйте зависимости (используйте OWASP Dependency-Check).
  • Отключайте JSP source debugging в production.
  • Не храните пароли и API-ключи в коде — используйте переменные окружения или Vault.

7. Недостатки контроля доступа

Нарушение прав доступа (IDOR — Insecure Direct Object References) позволяет пользователю получить данные другого пользователя, просто изменив ID в URL.

Пример

GET /api/user/12345

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

Блоги

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