Безопасность на высоте: как защищать API сегодня

da37037dfb27757606993b9d9be848b7.jpg

К 2030 году количество используемых в мире API составит около 2 миллиардов. Это в 8 раз больше, чем в 2018 году. Рост числа открытых точек увеличивает количество уязвимостей, угроз и прогнозируемых атак. По оценкам экспертов, к 2026–2027 годам рост прогнозируемых атак на API составит 156% от сегодняшнего состояния.

Меня зовут Денис Кириллов, я главный архитектор решения Platform V SOWA в СберТехе. Сегодня я хотел бы рассказать о лучших практиках защиты API в современном мире. Эта тема довольно обширная, поэтому я разделил её на два материала. В первой статье рассмотрим принципы безопасности API, спецификации API и как они влияют на безопасность. Поговорим о проверке объектов на соответствие спецификации и о том, как она помогает снизить риски из списка Тор-10 API Security Risks.

Во второй статье расскажу о проблемах валидации API и совместном использовании механизмов валидации и WAF. Выясним, почему необходим отдельный компонент, который реализовывал бы функцию безопасности по отношению к API. И рассмотрим возможности продукта Platform V SOWA, который мы создали для решения этих задач.

Материал будет полезен специалистам в области информационной безопасности, сопровождения и разработки.

Принципы безопасности API

Согласно исследованиям Enterprise Strategy Group, более 91% организаций в 2023 году столкнулись с различными инцидентами, связанными с информационной безопасностью и использованием API. Яркий пример того, к чему могут приводить уязвимости, — случай с Uber. В результате некорректного контроля и невыполнения требований безопасности по отношению к API пострадало 57 миллионов человек. Стоимость использования фактически одной уязвимости достигла 148 миллионов долларов.

Когда мы говорим об обеспечении безопасности API, мы выделяем пятьосновных принципов:

  1. Внедрение стратегии управления API. Думаю, многие сталкивались с понятиями API Governance и API Management. Это первое, что необходимо внедрить, чтобы обеспечить безопасность API. API Governance — это набор концепций, методик, стандартов, связанных с управлением API, в том числе с выполнением функций безопасности. Под API Management обычно подразумевается реализация этих концепций и методик.

  2. Создание единственного источника доверия для обнаружения API. Необходимо обеспечить только одну реперную точку — единое звено, которое гарантирует и отвечает за весь реестр API.

  3. Обеспечение правильного управления версиями и документацией. Мы контролируем отсутствие API, которые не планируем выставлять «наружу», и API с нерелевантным содержимым. Оформляем документацию, доступную соответствующим сторонам.

  4. Предоставление метрик и видимости трафика. Всегда необходимо контролировать, как протекают процессы с точки зрения производительности, потенциального вредоносного трафика, эксплуатации инъекций, использования API.

  5. Масштабируемая безопасность API. Функции безопасности должны быть масштабируемы, как и сами API. Здесь важно то, как будут выполняться функции безопасности при увеличении количества API.

Обеспечивать безопасность API помогают разные инструменты. Я хотел бы поговорить о том из них, которому часто не уделяется достаточное внимание, но который играет довольно серьёзную роль. Речь пойдёт о спецификациях API.

Спецификации API и их роль в безопасности

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

Обычно выделяют человекочитаемые и машиночитаемые спецификации. Первые предназначены для прочтения человеком, а вторые видоизменены так, чтобы их могла прочитать автоматизированная система. Но есть и комбинированный вариант — спецификация Open API. Она будет понятна как человеку, так и информационной системе.

Каким образом API‑спецификации влияют на безопасность?

Во‑первых, они определяют приоритеты и ограничения. Это помогает разработчикам и потребителям понять, какие API должны использоваться в том или ином сервисе, какая у них предполагается структура и как они должны себя вести.

Во‑вторых, правильно описанная спецификация определяет формат передаваемых данных, описывает маршруты запросов и так далее. Это позволяет снизить вероятность рисков и уязвимостей безопасности.

В‑третьих, API‑спецификация фактически определяет, как в целом должен функционировать сервис. А это позволяет моделировать угрозы безопасности.

В идеале спецификация должна охватывать все подробности обеспечения безопасности API. Но, к сожалению, так происходит не всегда. Связано это с тем, как реализуется проверка на соответствие спецификации, зависит ли она от имеющихся механизмов —, а они везде разные. Поэтому не всегда в спецификации можно однозначно определить требования безопасности по отношению к API.

Проверить, соответствуют ли обращения к API и передаваемые данные спецификации, помогает процесс валидации. О нём и поговорим в следующей главе.

Проверка на соответствие спецификации

Проверка на соответствие спецификации решает две основные задачи.

Во‑первых, это проверка параметров вызова. Например, если мы говорим об RPC, то речь идёт о перечне ожидаемых кодов состояний и вопросах, связанных с аутентификацией и авторизацией.

Во‑вторых, это непосредственно проверка контента — то есть того содержимого, которое передаётся и содержит определённые бизнес‑данные — на соответствие схеме валидации соответствующего формата данных. Это так называемый логико‑форматный контроль.

Ориентируясь на список OWASP API Top 10 Security Risks 2023, я постарался сопоставить потенциальные риски безопасности и возможности их устранения с помощью процесса валидации. Результаты отражены в таблице ниже.

Потенциальный риск

Возможность устранения при помощи проверки

API3

Отсутствие авторизации на изменение свойств объектов.

Проверка данных на входе и выходе API, авторизация на уровне функций, объектов, свойств объектов, целостность данных, фильтрация на допустимые данные (но НЕ заменяет WAF).

API4

Неограниченное потребление ресурсов.

Противодействие атакам DDoS уровня приложений (L7).

API7

Подделка запросов
на стороне сервера.

Противодействие попыткам передачи избыточных данных (как вход, так и выход).

API8

Некорректная конфигурация.

Ограничение пространства маршрутов запросов и вариантов ответов.

API10

Небезопасное потребление внешних API.

Проверка ответов от сервисов, проверка по белым спискам заголовков с редиректами.

Далее мы подробнее рассмотрим, как проверка помогает устранить перечисленные риски. Но здесь важно помнить о том, что проверка входных данных — это инструмент логико‑форматного контроля. Что это означает? Проверка на соответствие схемам валидации должна производиться первым этапом, до проверки на наличие инъекций. Любая схема валидации — это позитивная модель, которая работает по принципу «что не разрешено — то запрещено». Поэтому логичнее проверить, удовлетворяет ли обращение схеме валидации, вместо того чтобы «искать то, чего не должно быть, в том, что не должно пропускаться».

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

Рассмотрим на конкретных примерах.

API3: отсутствие авторизации на изменение свойств объектов

Здесь OWASP даёт следующие рекомендации. Во‑первых, необходимо определять все наборы данных, которые возвращаются всеми методами API. Во‑вторых, соблюдать принцип минимальной достаточности для возвращаемых данных, то есть возвращать только те данные, которые необходимы как результат выполнения операции. И запрещать передачу свойств, не определённых в схемах.

Если мы изначально придерживаемся модели «никому не доверять» (zero trust model), то мы никогда не знаем, реализованы ли в сервисе авторизационные проверки по отношению к тому или иному вызову и данным. Публикуя новую версию сервиса, мы можем забыть проверить, какие поля могут передаваться, а какие нет. Если у нас в схеме валидации запрещена передача таких данных, это значительно снижает уровень риска.

Вкачестве примера покажу, что бывает, если не ограничивать свойства объекта, которые можно возвращать.

На скриншотах ниже мы видим корректное определение в схеме валидации Open API. Мы чётко перечисляем, какие в объекте должны быть свойства, и запрещаем передачу дополнительных. Справа показано, как генератор создаёт код по этой спецификации. Мы видим, что здесь проверяется соответствие свойствам объекта Order.

97b6110e48d8dbe299da19b4034a8842.png

Далее показано, что будет, если добавить в схему проверка additionalProperties: true, то есть разрешить передавать произвольные свойства.

93098bd02984984b9f33e4927787988d.png

Справа мы видим, что объект body становится обычной мапой из string и object. И передавать в этом случае можно всё, что угодно.

Вопрос об использовании additionalProperties весьма спорный. Многие выступают за возможность их использования, потому что необходимо обеспечить forward compatibility. Но я считаю, что forward compatibility стоит обеспечивать через версионирование, иначе такой вызов становится малоуправляемым.

Рассмотрим, что происходит, если схемы валидации нет. Следующая иллюстрация показывает, что мы ожидаем получения XML‑содержимого с объектом, содержащим идентификатор и значение стоимости. Допустим, у нас есть проверка на возможность изменений. В реальности потенциальный злоумышленник может отправить запрос, который показан на иллюстрации справа.

587822b651e0ba755a6a6ac71a6078ce.png

Как мы видим, здесь добавлен price 0 и пустой идентификатор, и непонятно, как приложение и парсер это обработают. И не получится ли, например, что мы всем объектам поставим цену «ноль». Логико‑форматный контроль, который обеспечивает схема валидации, как раз призван не допустить таких ситуаций.

API4: неограниченное потребление ресурсов

Изначально многие считают, что DDoS — это что‑то вроде L4 сетевого уровня. Или что это атаки, направленные на использование потенциальных возможностей протокола, вроде slow server response. Но на самом деле DDoS — это всегда попытка несанкционированно вызвать большее потребление ресурсов, чем возможно для данной вычислительной системы.

Основные задачи, которые OWASP здесь выделяет, — определить и применить максимальный размер для всех параметров данных. На уровне той же схемы валидации точно должны определяться, например, ограничения на максимальную длину строк в параметрах и максимальное количество элементов. Для этого необходимо сочетать механизмы задания параметров парсеров, валидаторов и ограничений в схеме валидации.

Пример валидации против L7 DDOS — GraphQL.

07f2697d64709df2193e5c1358d2bb00.png

Мы видим, что для GraphQL на иллюстрации слева возможно использование вложенных запросов. Их количество должно быть ограничено, иначе любой потребитель сможет сформировать запрос с неограниченной глубиной и использовать все ресурсы сервера. Поэтому при валидации необходимо накладывать ограничения на глубину передаваемых запросов.

Справа на иллюстрации другой пример: в качестве параметра передаётся ожидаемый объём результирующей выборки. Здесь мы тоже можем указать любое число, укладывающееся в размерность типа. И загрузить сервер так, что он будет заниматься только обработкой ответов для отправки клиентам.

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

В итоге рассмотренные ограничения можно определить либо как параметры парсера,  либо как параметры объектов схемы валидации.

Другой пример связан с делением на ноль. Никто не знает, насколько корректно ваше приложение обрабатывает такие операции. Возможно, оно падает и перезапускается, потребляя большое количество ресурсов и при этом оставаясь неработоспособным. Чем не DDoS?

На иллюстрации ниже видим, как две разные схемы могут по‑разному обрабатывать такие ситуации. Слева неограниченный тип integerиспользуется для делителя. Передавая ноль, мы потенциально можем получить падение и недоступность приложения и сервиса. А справа видим, как это можно корректно определить в схеме валидации, ограничив тип integer, начиная с 1 и не включая 0. В этом случае падение исключено.

b1ff6b2a606ed09b0ffca0b6020ecfd6.png

API7: подделка запросов на стороне сервера

На этом риске мы не будем останавливаться подробно. Основная задача здесь — с помощью белых списков ограничить обращение информации, которая передаётся и возвращается по паттернам, к вредоносным и потенциально вредоносным ресурсам, а также к несанкционированным внутренним ресурсам.

API8: некорректная конфигурация

Основные задачи — проверка на используемые методы запросов, ограничение на тип и формат содержимого, запрет на отправку излишней информации. В качестве механизмов — всё, что обычно задаётся в спецификации, например, в OpenAPI: возможные белые списки методов, content‑type запросов и ответов. Должны быть определены допустимые статусы ответов, схемы валидации для них и так далее.

Ниже — пример валидации и определения возможных ответов об ошибке.

36ca58f4660589e6239fe292c7ac2cd5.png

На иллюстрации слева мы видим, что в случае ошибки 400 мы явно через enum определяем конкретное сообщение об ошибке. Справа — неудачный вариант того, как это определяется в спецификации. Мы говорим, что нам подойдёт любой ответ 404. Мы не проверяем, нет ли в нём утечек, отсылок на внутренние ресурсы, описанных механизмов, например, credentials, которые могут быть в логах, и так далее.

В идеальном варианте сообщения о возможных ошибках должны строго прописываться либо паттернами,  либо через enum.

API9: некорректное управление ресурсами

Определение спецификации помогает в том числе избежать некорректного управления ресурсами. Спецификация — один из инвентаризационных элементов, который содержит информацию об имеющихся API и параметрах их конфигурации. Он необходим для реализации принципов API Governance/API Management, о которых мы говорили в начале статьи.

API10: небезопасное потребление внешних API

Основные задачи — всегда валидировать и правильно очищать данные, полученные от любых интегрированных API. Необходимо также обеспечить белый список locations, куда могут перенаправлять API. Этот принцип продемонстрирован на схеме ниже. Два сервиса находятся в trusted‑зоне и вроде могли бы доверять и не проверять, что возвращают друг другу. Но на самом деле нет гарантии, что один из этих сервисов не взаимодействует с каким‑то внешним untrusted‑сервисом и корректно валидирует и проверяет передаваемые данные.

72615a9b40f30a2070924d21e224c6c5.png

Соответственно, я рекомендую всегда придерживаться модели нулевого доверия. Нужно проверять то, что возвращает сервис, вне зависимости от того, находится он в trusted‑сегменте или нет.

Мы рассмотрели основные потенциальные угрозы безопасности и разобрались, как помогает их минимизировать проверка на соответствие спецификации.

В следующей части я расскажу о проблемах валидации API и совместном использовании механизмов валидации и WAF. Объясню, почему важно иметь внешний компонент для валидации, и познакомлю вас с продуктом Platform V SOWA, который помогает решить эту задачу.

© Habrahabr.ru