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

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

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

Начать курс

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

Java остается одним из самых популярных языков программирования для создания корпоративных и веб-приложений. Однако, как и любой другой язык, он подвержен атакам. Для начинающих разработчиков понимание основ безопасности — это не просто хороший тон, а жизненно необходимый навык. В этой статье мы разберем топ-10 самых распространенных уязвимостей Java-приложений, приведем примеры кода и расскажем, как защитить ваш проект.

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

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

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

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

Злоумышленник может передать в userInput значение типа ' OR '1'='1, что приведет к возврату всех данных из таблицы.

Как защититься: Всегда используйте PreparedStatement.

String query = "SELECT * FROM users WHERE username = ?";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(1, userInput);
ResultSet rs = pstmt.executeQuery();

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

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

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

out.println("<p>Привет, " + request.getParameter("name") + "</p>");

Как защититься: Экранируйте HTML-символы или используйте современные шаблонизаторы (например, Thymeleaf или JSP с JSTL).

// Используем библиотеку Apache Commons Lang
String safeInput = StringEscapeUtils.escapeHtml4(userInput);
out.println("<p>Привет, " + safeInput + "</p>");

3. Межсайтовая подделка запросов (CSRF)

CSRF заставляет пользователя выполнить нежелательное действие на сайте, где он авторизован. Например, перевести деньги или сменить пароль.

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

<img src="https://bank.com/transfer?amount=1000&to=hacker" />

Как защититься: Используйте CSRF-токены. В Spring Security это делается автоматически при включении защиты.

// Включаем CSRF защиту в Spring Security
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());

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

Java позволяет восстанавливать объекты из байтовых потоков. Если злоумышленник может передать вредоносный сериализованный объект, это может привести к выполнению произвольного кода.

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

ObjectInputStream ois = new ObjectInputStream(request.getInputStream());
Object obj = ois.readObject(); // Потенциально опасная операция

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

  • Не десериализуйте данные из ненадежных источников.
  • Используйте белые списки классов.
  • Применяйте альтернативы, такие как JSON (Jackson/Gson) с валидацией.

5. Уязвимости в библиотеках (Dependency Vulnerabilities)

Современные Java-проекты используют десятки сторонних библиотек (Maven, Gradle). Устаревшие или уязвимые версии — частая причина взломов.

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

  • Регулярно обновляйте зависимости.
  • Используйте инструменты анализа: OWASP Dependency-Check, Snyk, GitHub Dependabot.
  • Добавьте проверку в CI/CD пайплайн.

6. Небезопасная аутентификация и управление сессиями

Слабые пароли, отсутствие блокировки после неудачных попыток входа, незащищенные cookie сессий — все это открывает путь к атакам.

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

  • Используйте BCrypt или Argon2 для хеширования паролей.
  • Установите флаги HttpOnly и Secure для куки.
  • Внедрите механизм блокировки аккаунта после 3-5 неудачных попыток.
// Пример хеширования с BCrypt
String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt());

7. Раскрытие конфиденциальных данных

Часто разработчики случайно оставляют в коде пароли, ключи API или строки подключения к базе данных. Также опасно выводить стектрейсы ошибок пользователю.

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

  • Храните секреты в переменных окружения или в Vault (например, HashiCorp Vault).
  • Никогда не используйте системные переменные типа System.getenv() напрямую в коде для логов.
  • Настройте глобальный обработчик ошибок, который возвращает общее сообщение, а не детали.

8. XML External Entity (XXE)

Если ваше приложение парсит XML, злоумышленник может внедрить внешнюю сущность, которая прочитает файлы на сервере или вызовет DoS-атаку.

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

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(inputStream); // Опасно!

Как защититься: Отключите поддержку внешних сущностей.

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);

Блоги

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