Pull to refresh
46.9

Защищаем API – что важно знать?

Reading time12 min
Views14K

В фундаменте каждой информационной защиты лежит глубокое понимание технологии целевой системы. В этой статье речь пойдет о защите API (Application Programming Interface) — важнейшего набора функций для каждого прогера.

Интересно узнать об актуальных инструментах защиты API и о том, почему их важно применять? Го под кат!

Что за зверь такой — API?

Давайте разберемся для начала, что в наше время подразумевается под API.  На данном этапе развития человечества актуальными в b2b-среде считаются микросервисные архитектуры, веб-приложения, бессерверные вычисления и т.д. Для того, чтобы весь механизм работал, необходим понятный и безусловный операнд (аргумент операции). Но что, если этих аргументов нужно больше? Правильным ответом будет передача функции.

Звучит достаточно просто и понятно: приложение А должно передать приложению Б набор функций для выполнения определенных действий. Пример: веб-приложение разработчика написано на Java, но есть клиентский агент, написанный на C++, и для передачи данных о клиентском агенте необходима выборка информации. Клиент с помощью функций генерирует JSON файл с содержанием этих данных и сервер веб-приложения, переваривая эту информацию, выводит в веб-интерфейс данные об этом клиенте.

Упоминая JSON файл, я забежал вперед. Для начала считаю необходимым описать возможные категоризации API:

По принципу распространения:

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

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

  • Внешние — API используются сторонними разработчиками, в основном для публичного взаимодействия с системами. Ярким примером является API ВКонтакте для внедрения разработчиками игр своего кода непосредственно в маркетплейс VK.

Исторически сложилось, что изначально API использовались разработчиками приватно в рамках компаний или партнерских отношений, но в 2000-х компания «Saleforce» впервые использовала API для своих веб-приложений. Эту идею быстро подхватили будущие мастодонты рынка — eBay, Amazon и т.д. Таким образом идея использования API получила широкое распространение в сети Интернет.  

Сейчас почти каждая компания, вне зависимости от ее размеров, так или иначе делает API доступным. Спектр использования весьма разнообразен: это и рынок IoT, и наши с вами смартфоны, и все переносимые устройства. Да, даже ваш умный пылесос от Xiaomi (не реклама) (который топ за свои деньги) также обладает открытым API.

Все ранее описанное нужно для понимания масштаба использования API. Но вот что я вам скажу, приведя красивую цитату: «Взломать можно все, особенно, если это придумано человеком». В подкрепление своих слов привожу статистику с сайта https://salt.security/api-security-trends:

Как можно наблюдать с ростом количества API вызовов растет и рост интереса злоумышленников к данному вектору атаки.

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

Итак, среди существующих общедоступных и общеизвестных API, актуальными являются API на базе следующих архитектур:

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

    o   Ресурс является частью URL

    o   Для каждого ресурса создается два URL, один для коллекции, один для экземпляра коллекции, /users и users/123.

    o   HTTP-методы GET, POST, PATCH и DELETE информируют сервер о том, какое действие нужно совершить над данным ресурсом. Различные методы, примененные к одному и тому же ресурсу, выполняют различную функциональность.

  • SOAP — расширение протокола XML-RPC. Первоначально предназначался для RPC (вызова удаленных процедур), сейчас чаще используется для обмена сообщениями в формате XML. Чаще всего встречается в сервисах типа мессенджеров (см. Mattermost).

  • RPC — самый просто тип API, когда вызов передается в качестве полезной нагрузки в запросе, например:

    POST /api/conversations.archive

    HOST slack.com

    Content-Type: application/x-www-form-urlencoded

    Authorization: token OAUTH-TOKEN

    channel=C01234

Почему важно защищать API?

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

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

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

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

Среди известных атак на API существуют:

  • Атака на параметры: наиболее распространенный тип атаки, нацеленный на манипуляцию десериализатора движка целевого сервера веб-приложения.

  • Атака для раскрытия данных (Exposure data): разумеется, компрометация данных и их дальнейшее использование, неважно со злым или добрым намерением является также одним из векторов атак.

  • Атаки MITM (Man in the middle): атака по середине между API сервером и клиентом.

  • Абуз приложений (Злоупотребление если по-русски, тем не менее абуз слово наиболее подходящее): не столь популярный тип атаки, тем не менее о нем необходимо упомянуть. Пример: у вас есть приложение по букингу билетов. С помощью приложения на телефоне человек может забронировать определенные билеты в определенных местах зала. Делается это очевидно с помощью API. Так как это общедоступное приложение, появляется маневр для злоупотребления (абуза) данного функционала. С помощью ботов или просто вручную можно забронировать все места в зале, соответственно нарушив бизнес-процесс.

Также более подробно можно познакомиться тут.

Какие уязвимости у API?

Когда мы говорим об архитектуре REST чаще всего на ум приходит — JSON (хотя RESTfull API подразумевает под собой необязательно передачу только JSON файла, но тем не менее).

Вот тут крутая статья, кто вообще не понимает, что здесь происходит.

JSON уязвимости и их защита

Необходимо пояснить, что, разумеется, большинство атак на API нацелены именно на внутренние движки приложений и в полезной нагрузке (пейлоаде) могут быть любые сигнатуры (SQL инъекции, RCE, XSS, DoS и т.д.). Здесь я опишу именно специфичные уязвимости самих технологий API.

Как ранее упоминалось в статье, одна из атак нацелена на параметры. Как же это происходит?

На примере JSON в рамках официального RFC существует открытое руководство по некоторым темам, таким как обработка повторяющихся ключей и представление чисел. Хотя и в стандарте есть пункт об отказе совместимости, множество пользователей даже не знают о них.

Итак, первая категория уязвимостей JSON:

Неопределенный приоритет повторяющихся ключей.

Что будет если просто продублировать JSON ключ?

Например:

Test = { “bro”:1, “bro”:2}

Какое значение для bro будет итоговым при генерации такого запроса: 1 или 2, или будет ошибка?  Согласно официальному стандарту оба варианта возможны (J).  Причина, почему так возможно, кроется, как мне кажется, в том, что стандарт заранее сделан таким образом, чтобы не нарушать обратную совместимость с анализаторами предварительной спецификации.

Какая разница 2 или 1, или ошибка? Представим, что у вас сервис с платежной системой, можно покупать объекты для определенного ВАШЕГО аккаунта. Вы хотите купить пачку чипсов и 5 пачек жвачки:

POST /cart/checkout HTTP/1.1
...
Content-Type: application/json
{
    "orderId": 10,
    "paymentInfo": {
        //...
    },
    "shippingInfo": {
        //... 
    },
    "cart": [
        {
            "id": 0,
            "qty": 5
        },
        {
            "id": 1,
            "qty": -1,
            "qty": 1
        }
    ]
}

Где id чипсов — 1, id жвачки - 0 а их количество — qty. Пачка чипсов стоит при этом 100 рублей. При отправке такого запроса к веб-серверу, который использует для анализа JSON стандартную библиотеку Python, будет использоваться приоритет последнего ключа. Такой запрос успешно валидируется данным парсером и сырые данные отправляются дальше в систему генерации платежной квитанции, которая в свою очередь использует Golang для анализа (например, buger/jsonparser).

id, _ := jsonparser.GetInt(value, "id")
qty, _ := jsonparser.GetInt(value, "qty")
total = total + productDB[id]["price"].(int64) * qty;

Он же (Golang) использует приоритет первого ключа. Таким образом, если мы отправим запрос на 5 пачек жвачки стоимостью 500 рублей и чипсов стоимостью 100 рублей с дубликатом ключа, парсер веб-сервера проанализировав запрос (относительно json схемы) примет его как валидный, а данные, отправленные на сервис платежной системы сформируют квитанцию для qty размером -1.

Таким образом, при формировании платежной квитанции нам будет отправлено 5 пачек жвачки и 1 пачка чипсов стоимостью 500 рублей, но с нас возьмут 400 рублей, т.к. при qty -1 для пачки чипсов - их цена в чеке будет вычтена парсером Golang.

Следующий тип атаки — коллизия значений.

Некоторые парсеры JSON сокращают спецсимволы, когда они появляются в строковом значении, но некоторые этого не делают, и в таком случае парсер может принять дублируемое значение переменной. Например, JSON следующего типа:

{"test": 1, "test\[raw \x0d byte]": 2} 
{"test": 1, "test\ud800": 2}
{"test": 1, "test"": 2}
{"test": 1, "te\st": 2} 

Эти строковые значения обычно не устойчивы к нескольким этапам сереализации и десереализации. Так, U+D800 и U+DFFF являются непарными суррогатными кодовыми точками в UTF-16 и пока они могут быть закодированы в UTF-8 байтовую строку, это будет уязвимостью. Предположим, что у нас есть приложение, в котором администратор приложения может создавать роли и пользователей через API. Также пользователи с повышенными правами имеют роль — superuser. Формат создания пользователя такой:

POST /user/create HTTP/1.1
...
Content-Type: application/json

{
   "user": "NoviiPolzak", 
   "roles": [
       "superuser"
   ]
}

HTTP/1.1 401 Not Authorized
...
Content-Type: application/json
{"Error": "Assignment of internal role 'superuser' is forbidden"}

Как мы видим, при попытке добавления пользователя “NoviiPolzak” с ролью “superuser” сервер отвечает ошибкой 401 и контентом, что доступ запрещен. Теперь самое интересное, с помощью API мы добавим новую роль следующим образом:

POST /role/create HTTP/1.1
...
Content-Type: application/json

{
   "name": "superuser\ud888"
}

HTTP/1.1 200 OK
...
Content-type: application/json

{"result": "OK: Created role 'superuser\ud888'"}

Также создадим еще раз пользователя:

POST /user/create HTTP/1.1
...
Content-Type: application/json

{
   "user": "NoviiPolzak", 
   "roles": [
       "superuser\ud888"
   ]
}

HTTP/1.1 200 OK
...
Content-Type: application/json

{"result": "OK: Created user “NoviiPolzak”}

Таким образом в системе на данный момент создан пользователь NoviiPolzak с ролью superuser\ud888 и при использовании парсера, который сокращает запрещенные кодовые точки система будет принимать просто роль “superuser”. То есть, когда с созданной записью пользователя мы будем обращаться, например, к панели администратора, система даст нам повышенные права.

Как известно, многие библиотеки JSON поддерживают комментирование из JavaScript интерпретатора, например /*,*/. Благодаря этому один запрос может быть обработан двумя разными парсерами по-разному:

obj = {"description": "Коллизия с помощью комментирования ", "test": 2, "extra": /*, "test": 1, "extra2": */}

GoLang распарсит так:

Description: “Коллизия с помощью комментирования”
Test= 2 
Extra= “”

Java JSON-iterator — вот так:

Description:
Extra=”/*”
Extra2=”*/”
Test= 1

Выходит, основные уязвимости JSON связаны непосредственно с парсерами данных на стороне приложения во время их кодировки и декодирования. Такие уязвимости достаточно тяжело обнаружить, и они требуют общего подхода к их устранению — как со стороны разработчика, так и от команды ИБ. Ниже я опишу, какие существуют средства защиты API, а сейчас переходим к SOAP.

SOAP уязвимости

SOAP, как известно, в своем фундаменте имеет XML и основные уязвимости вытекают отсюда.

SOAP injection — самая простая, но тяжело детектируемая атака, непосредственно инъекция в теле SOAP запроса.

	<soapenv:Envelope xmlns:soapenv=”http://schemas.xmlsoap.org/soap/envelope/” xmlns:web=”web:”>
	<soapenv:Header>
	</soapenv:Header>
<soapenv:Body>
		<web1:Login xmlns:web1=”http://ws.example.com/”> 
				<fname>Ivan</fname>
				<lname>Ivanov</lname>
				<password>lmao1337</password>
		</web1:Login>
	</soapenv:Body>
</soapenv:Envelope>

Это классический запрос авторизации, и если он пройдет успешно, мы получим ответ ОК. Но теперь уберем тэг <lname></lname> из запроса. В ответ от сервера получим, что-то вроде:

Error at line 66: lname == null | loginid
loginid cannot be null

Вообще данный ответ содержит в себе кусок кода, и говорит нам о том, что если lname тэг отсутствует, то должен использоваться loginid вместо него. Получается, если мы создадим запрос, в котором укажем loginid без строки <lname>:

<fname>Ivan</fname>
<password>lmao1337</password>
<loginid>1</loginid>

То мы сможем успешно авторизоваться и отправлять запросы на уровне администратора.

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

SOAP Action Spoofing — сам SOAP допускает использование дополнительного заголовка HTTP – SOAPAction. Данный заголовок содержит в себе имя выполняемой операции и служит для оптимизации анализа SOAP целевым приложением. Приложение, основываясь на заголовке, может не производить анализ целого пересылаемого XML.

Допустим, у нас есть приложение, уязвимое к SOAPAction — спуфингу по двум операциям: “createUser” и “deleteAllUsers”.  При этом, перед приложением стоит шлюз, который блокирует все запросы на удаление всех пользователей, если они пришли извне (deleteAllUsers), т.е. только прямое подключение к приложению позволяет авторизованному пользователю выполнить удаление.

Пример запроса пользователя на создание нового пользователя:

POST /service HTTP/1.1
Host: myHost
SOAPAction: "createUser"

<Envelope>
  <Header />
  <Body>
    <createUser>
      <login>IVANPOPOLAM</login>
      <pwd>secret</pwd>
    </createUser>
  </Body>
</Envelope>

Теперь, если злоумышленник добавит в запрос заголовок SOAPAction:

POST /service HTTP/1.1
Host: myHost
SOAPAction: "deleteAllUsers"

<Envelope>
  <Header />
  <Body>
    <createUser>
      <login>IVANPOPOLAM</login>
      <pwd>secret</pwd>
    </createUser>
  </Body>
</Envelope>

Шлюз, стоящий перед приложением пропустит такой запрос, т.к. он смотрит только в тело SOAP и в следствии приложение прочитав заголовок SOAPAction удалит всех пользователей.

XXE — классическая уязвимость, подробнее о ней — https://habr.com/ru/company/vds/blog/454614/ тут. На самом деле XXE эксплуатируется похожим образом, как и XSS, выполняя вредоносный код на стороне сервера, при разведке данных на приложении и т.п.

Чем защищаться будем?

Описанные ранее уязвимости в основном находятся на уровне логики работы парсеров и обработчиков запросов. Защита достигается путем взаимной работы отдела разработчиков и ИБ-отдела. И если со стороны разработчиков все понятно — не использовать уязвимые библиотеки и вовремя обновляться, то ИБ-отдел может предложить использовать средства защиты веб-приложений — WAF (Web Application Firewall) с функциональностью API Protect. В таком случае WAF обычно выступает дополнительной точкой отказа.

Статью я начал писать до февральских событий, и вообще хотел рассказать о Nginx App Protect и о его возможностях относительно уязвимостей. Поэтому я все равно расскажу, и в конце добавлю о российских решениях на рынке СЗИ.

Чем может похвастаться Nginx App Protect

Во-первых, в отличии от классического WAF, он достаточно гибко разворачивается в DevOps инфраструктуру. Является модулем для подписки NGINX Plus.

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

Функционал:

  1. Сигнатурный анализ. Автоматически или принудительно можно указать используемые технологии веб-приложения, и соответственно не «громоздить» сам nginx лишними проверками сигнатур. В общем для API обязательный функционал. Т.к. даже если злоумышленник не будет целиться непосредственно на библиотеки API, с помощью API вызовов вполне можно реализовать сценарий атаки на смежные технологии веб-приложения, передав злоумышленный пейлоад в API.

  2. Подписка Threat Campaigns — это одна из ключевых фишек F5 и Nginx – тяжеловесные скореллированные сигнатуры с низким процентом ложных срабатываний, распространяются только по доп. подписке.

  3. HTTP Compliance — не совсем относится к API, тем не менее ограничивающие политики для запросов всегда нужны и важны.

  4. Data Guard — маскирование критических данных в запросах. Например, если в API передаются серия и номер паспорта, есть возможность маскировать эту информацию.

  5. Parameter parsing — автоматический парсинг параметров из запроса для создания отдельных логических объектов. Далее созданные объекты могут быть индивидуально настроены для применения тех или иных ограничений.

  6. JSON Content — в системе есть возможность создать логический профиль для описания разрешений при использовании JSON. Скажем, можно определить разрешенную длину полезной нагрузки JSON и длину массива, проверять возможные атаки на парсеры JSON.

  7. XML Content — в системе реализован функционал защиты XML именно по сигнатурному анализу. Также, как и в случае с JSON, создается логический профиль для описания разрешенных условий передачи XML: максимально разрешенная глубина вложений, количество параметров, размер.

  8. gRPC Content — в системе создается профиль содержимого gRPC. Nginx обнаруживает сигнатуры атак и запрещенные метасимволы. Кроме того, есть возможность запрещать использование неизвестных полей. Для этого необходимо будет указать файл определения языка (IDL).

Как и говорил ранее, немного о существующих решениях на российском рынке:

PTAF — разработка компании «Positive Technologies», не имеет каких-то автоматизированных протекторов API. Тем не менее у PTAF очень гибкий движок по написанию собственных правил, а также встроенные функции проверки потенциально нелегитимных JSON и XML файлов. 

Wallarm API Security — продукт компании «Wallarm». Функционал направлен точечно на защиту API. Из коробки защищает по OWASP API TOP-10, имеет собственные API парсеры и протекторы JSON/XML.

InfoWatch Attack Killer — под капотом ядро «Wallarm», его API парсеры и механизмы защиты.

Фундаментально это все. Ограничения на точке отказа в любом случае не панацея, необходимо всегда анализировать уязвимые места парсеров и создавать виртуальные заплатки. Для этого во многих WAF реализован функционал создания своих сигнатур. Т.е., помимо того, чтобы просто внедрить WAF в свою инфраструктуру, необходимо постоянно его администрировать совместно с разработчиками веб-приложения.

Tags:
Hubs:
Total votes 11: ↑11 and ↓0+11
Comments14

Articles

Information

Website
www.angarasecurity.ru
Registered
Founded
Employees
201–500 employees
Location
Россия