Карта / Угрозы (OWASP) / Валидация, prepared statements

Валидация, prepared statements

Никогда не доверяй входным данным. Любые данные от пользователя (формы, URL-параметры, заголовки, JSON) могут содержать вредоносный контент. Валидация и параметризованные запросы — первая линия защиты.

Prepared statements (параметризованные запросы) — защита от SQL-инъекций:

// ОПАСНО — конкатенация строк:
String query = "SELECT * FROM users WHERE email = '" + email + "'";

// БЕЗОПАСНО — prepared statement:
PreparedStatement ps = conn.prepareStatement(
    "SELECT * FROM users WHERE email = ?"
);
ps.setString(1, email);  // email вставляется как данные, не как SQL

JPA/Hibernate по умолчанию используют prepared statements — ещё одна причина предпочитать их нативному SQL.

Валидация входных данных в Spring Boot:

public record CreateUserDto(
    @NotBlank String username,
    @Email String email,
    @Size(min = 8, max = 64) String password,
    @Pattern(regexp = "^[a-zA-Z0-9_]+$") String nickname
) {}

@PostMapping("/users")
public ResponseEntity<UserDto> create(@Valid @RequestBody CreateUserDto dto) {
    // если dto не прошёл — автоматически 400 Bad Request
}
Копнуть глубже

Два уровня валидации. Валидация на клиенте (JavaScript в браузере) — для UX, не для безопасности. Её легко обойти (curl, Postman, browser devtools). Валидация на сервере — обязательна, это единственная надёжная защита. Проверяйте всё что пришло от клиента, даже если ваш UI «не позволяет» ввести неправильные данные.

Whitelist vs Blacklist. Blacklist-подход: «запрещу ввод <script> тегов» — легко обойти альтернативным кодированием (<scr\x69pt>, Unicode). Whitelist-подход: «разрешу только то, что точно безопасно» — позитивные шаблоны @Pattern(regexp = "^[a-zA-Z0-9]+$"). Whitelist надёжнее.

Output encoding — дополнительная защита. Даже если вредоносные данные попали в БД, их нужно безопасно вывести:

  • В HTML: эскейпинг <&lt; (Thymeleaf делает автоматически через th:text)
  • В JSON: стандартная сериализация Jackson безопасна
  • В SQL: prepared statements

Bean Validation стандартные аннотации (javax.validation / jakarta.validation):

  • @NotNull, @NotEmpty, @NotBlank — разница: NotNull не проверяет пустую строку, NotEmpty проверяет длину ≥ 1, NotBlank — непустую строку без пробелов
  • @Min, @Max, @Positive, @PositiveOrZero — числовые границы
  • @Past, @Future — для дат
  • @Valid на вложенных объектах — каскадная валидация
🎤 Закрыл тему, если можешь объяснить:
• почему конкатенация строк в SQL опасна и как prepared statements защищают;
• разницу whitelist и blacklist подходов к валидации (если дошёл до 2-го слоя).