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

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

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

Начать курс

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

Безопасность Java-приложений — это не просто галочка в чек-листе, а критически важный аспект разработки. По данным OWASP, более 70% современных веб-приложений содержат хотя бы одну критическую уязвимость. В этой статье мы разберем 10 самых распространенных угроз с реальными примерами кода и способами их устранения. Материал будет полезен как начинающим, так и опытным Java-разработчикам.

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

SQL-инъекция остается лидером среди уязвимостей. Атакующий может внедрить вредоносный SQL-код через пользовательский ввод.

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

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

Исправленный код (использование PreparedStatement):

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

2. XSS (Cross-Site Scripting)

XSS-атаки позволяют внедрять клиентские скрипты в веб-страницы. Основная защита — экранирование вывода.

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

<%= request.getParameter("comment") %>

Исправленный код:

<%= Encode.forHtml(request.getParameter("comment")) %>

Используйте библиотеку OWASP Java Encoder для надежного экранирования:

import org.owasp.encoder.Encode;
String safeOutput = Encode.forHtml(userInput);

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

Java-десериализация может привести к удаленному выполнению кода (RCE).

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

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

Рекомендации по защите:

  • Не десериализуйте данные из ненадежных источников
  • Используйте белый список классов при десериализации
  • Применяйте JSON или XML вместо сериализации Java
// Безопасный подход с проверкой класса
ObjectInputStream ois = new ObjectInputStream(inputStream) {
    @Override
    protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
        if (!allowedClasses.contains(desc.getName())) {
            throw new InvalidClassException(desc.getName(), "Unauthorized deserialization");
        }
        return super.resolveClass(desc);
    }
};

4. CSRF (Cross-Site Request Forgery)

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

Защита с помощью токенов (Spring Security):

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    }
}

Добавление токена в форму:

<form action="/transfer" method="POST">
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
    <input type="text" name="amount"/>
    <button type="submit">Перевести</button>
</form>

5. Утечка информации через исключения

Детальные сообщения об ошибках могут раскрыть внутреннюю структуру приложения.

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

try {
    // бизнес-логика
} catch (SQLException e) {
    response.getWriter().println("Ошибка: " + e.getMessage()); // Утечка!
}

Исправленный код:

try {
    // бизнес-логика
} catch (Exception e) {
    logger.error("Ошибка при обработке запроса", e);
    response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Внутренняя ошибка сервера");
}

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

Слабые пароли и отсутствие блокировки после неудачных попыток — частая проблема.

Правильная реализация хеширования паролей:

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String hashedPassword = encoder.encode(plainPassword);

// Проверка пароля
boolean matches = encoder.matches(plainPassword, hashedPassword);

7. Недостаточная проверка доступа

Отсутствие проверки прав на уровне методов может привести к эскалации привилегий.

Использование аннотаций Spring Security:

@PreAuthorize("hasRole('ADMIN')")
@PostMapping("/admin/deleteUser")
public ResponseEntity<String> deleteUser(@RequestParam Long userId) {
    // только для администраторов
    userService.deleteUser(userId);
    return ResponseEntity.ok("Пользователь удален");
}

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

Широкие настройки CORS могут привести к утечке данных.

Опасная конфигурация:

@CrossOrigin(origins = "*") // Разрешает все домены!

Безопасная конфигурация:

@CrossOrigin(origins = "https://trusted-site.com", allowedHeaders = "Authorization")

9. Уязвимости в зависимостях

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

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

  • Регулярно обновляйте зависимости через Maven/Gradle
  • Используйте OWASP Dependency-Check для автоматического сканирования
  • Настройте Dependabot в GitHub для автоматических обновлений
// Пример плагина Maven для проверки зависимостей
<plugin>
    <groupId>org.owasp</groupId>
    <artifactId>dependency-check-maven</artifactId                

Блоги

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