TGViewer
Искусство. Код... ИИ? Искусство. Код... ИИ? @art_code_ai · 706 subscribers
Post #115 1.35K
🧩 Принципы и паттерны безопасной разработки: ISP

Часть 3.

А у нас на очереди, принцип разделения интерфейсов (Interface Segregation Principle, ISP — пожалуй, один из наиболее простых в SOLID), гласящий:

Клиенты не должны зависеть от интерфейсов, которые они не используют.


Проще говоря, лучше несколько узкоспециализированных интерфейсов, чем один «толстый», навязывающий потребителю кучу лишнего.

С точки зрения безопасности, ISP напрямую перекликается с принципом наименьших привилегий (Least Privilege). «Толстый» интерфейс — это расширенная поверхность атаки: клиент получает доступ к методам, которые ему для работы не нужны. Если один из таких методов оказывается привилегированной операцией, а её защита оказывается слабее ожидаемой, то любой потребитель интерфейса внезапно получает доступ к критичному функционалу.

💡Тривиальный пример:

interface IUserService {
User getProfile(Long id);
void updateProfile(User u);
void resetPassword(String email);
void deleteUser(Long id);
void assignRole(Long id, Role r);
List<User> exportAll();
}


Потребитель, которому нужно лишь отображать профиль, вынужден зависеть от deleteUser, assignRole и exportAll. Если защита реализована на уровне имплементации, а не интерфейса, то одна ошибка авторизации — и профильный компонент может удалять пользователей.

❗Что делать?

Нарушения ISP порождают целый ряд CWE, связанных с чрезмерно широким доступом:

• CWE-749: Exposed Dangerous Method or Function
• CWE-306: Missing Authentication for Critical Function
• CWE-250: Execution with Unnecessary Privileges

В примере выше правильнее ввести два интерфейса, соответствующие уровням привилегий принятой в приложении модели доступа:

interface IUserProfile {
User getProfile(Long id);
void updateProfile(User u);
}

interface IUserAdmin {
void deleteUser(Long id);
void assignRole(Long id, Role r);
List<User> exportAll();
}


Компоненту, работающему с профилями, IUserAdmin будет попросту недоступен, даже при наличии бага в авторизации.

Разделение интерфейсов можно (и нужно) также проводить, и по границам доверия: один интерфейс не должен обслуживать функциональность по обе стороны от любой из границ, определенных моделью угроз.

В плане соблюдения ISP, среди мейнстримовых языков здесь выгодно выделяются два:

💻 Go — не запрещает «толстые» интерфейсы, но поощряет их дробление через удобство композиции и интерфейсы потребителей. Стандартную библиотеку этого языка вполне можно рассматривать, как эталон соблюдения ISP.

👣 Rust — та же композиционная история, но через трейты и необходимость соблюдения «orphan rule».

Забавно, что в этих языках есть и явный анти-паттерн, который не запрещен: пустой интерфейс (interface{} в Go / dyn Any в Rust). Это нарушение ISP: клиент зависит от всего и ни от чего одновременно. Они существуют для низкоуровневых нужд, и их использования стоит по-возможности избегать.

🐛 Жизненное

CVE-2023-22515 — Atlassian Confluence (Broken Access Control, CVSS 10.0).

Confluence использовал фреймворк XWork2 для маршрутизации HTTP-запросов. Через единый веб-интерфейс были доступны как пользовательские действия (просмотр/редактирование страниц), так и привилегированные операции первичной настройки (/setup/setupadministrator.action). В терминах ISP — один «толстый» интерфейс маршрутизации обслуживал и рядовых пользователей, и административный мастер установки.

Атакующий отправлял запрос, манипулирующий свойством bootstrapStatusProvider.applicationConfig.setupComplete через механизм привязки параметров XWork2, «сбрасывая» флаг завершённости установки. После этого endpoint создания администратора становился доступен без аутентификации — атакующий создавал собственный админский аккаунт и получал полный контроль.

Если бы интерфейс маршрутизации был сегрегирован (setup-эндпоинты физически изолированы от пользовательских, с отдельным middleware авторизации), манипуляция параметрами одного интерфейса не открыла бы доступ к другому.

В патче (разбор) эндпоинты, относящиеся к установочным действиям, блокируются после первичной установки, а маршрутизация разделена.

Часть 5.

⚠ TL;DR: «Толстый» интерфейс — расширенная поверхность атаки. Если клиент видит метод, то рано или поздно кто-то найдёт способ его вызвать. Стоит разделять интерфейсы, как по привилегиям, так и по границам доверия.

#безопасность_кода #гайд
  • ❤ 4
  • 👍 3
More from @art_code_ai
  1. Sep 29, 2026Объяснили с Раддой Юрьевой на Хабре, почему смешивать формальные и ИИшные подходы в задача…
  2. Sep 27, 2026🔗 Старый добрый аппсек, часть 2 Продолжаем вспоминать ключевые вехи аппсека и смежных обл…
  3. Sep 26, 2026Post #155
  4. Sep 24, 2026🔗 Старый добрый аппсек, часть 1 ...совершенно незаслуженно задвинутый на второй план ИИ-х…
  5. Sep 23, 2026Post #153
  6. Sep 21, 2026👨‍💻 Продуктивные выходные Как-то незаметно (и неожиданно) для себя с удовольствием провё…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →