Атака на API

Атака на API

Oleg

Установка

Существуют версии клиента Postman для Linux, Mac и Windows. Для ясности будем использовать клиента для Linux на нашей атакующей машине. В Windows и Mac установка довольно проста, но в Linux может понадобиться пара зависимостей для начала работы.

Клиент Postman – это приложение, созданное с использованием фреймворка Electron. Оно довольно переносимое, но для него требуется зависимость libgconf, доступная в репозиториях Kali. Ее можно установить, используя команду apt-get install из терминала.

root@kali:~/tools# apt-get install libgconf-2-4
Reading package lists... Done
Building dependency tree
[...]

Чтобы получить последнюю скомпилированную сборку Postman, загрузим архив с расширением .gzip из его репозитория, доступного на сайте https://dl.pstmn.io/download/latest/linux64, с помощью команды wget. Команда wget сохранит файл в postman.tar.gz в локальном каталоге.

root@kali:~/tools# wget https://dl.pstmn.io/download/latest/linux64
-O postman.tar.gz
[...]
HTTP request sent, awaiting response... 200 OK
Length: 78707727 (75M) [application/gzip]
Saving to: 'postman.tar.gz'
[...]

Извлечем содержимое на диск в нашем каталоге tools с помощью команды tar zxvf, как показано ниже.

root@kali:~/tools# tar zxvf postman.tar.gz
Postman/
Postman/snapshot_blob.bin
[...]

После установки зависимостей можно запустить Postman, вызвав предварительно скомпилированный двоичный файл Postman . Как и ожидалось, он находится в каталоге Postman/, который мы только что извлекли из архива.

Запуск клиента Postman для Linux

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

Пользовательский интерфейс по большей части не требует пояснений. Мы можем ввести URL-адрес API, изменить HTTP-метод, передать пользовательские заголовки и даже создать действительную авторизацию с помощью пары кликов.

В качестве теста выполним тот же запрос, который создали ранее с помощью команды curl. Ответ появится на вкладке Body, изображенной на скриншоте (рис.), с возможностью форматировать содержимое. Postman может автоматически парсить и форматировать ответ в виде XML, HTML, JSON или обычного текста. Эта функция полезна, когда ответ представляет собой большой блок данных.

Одна из сильных сторон Postman заключается в его способности записывать все запросы, которые мы сделали в панели History (История) слева. Это позволяет нам, разработчикам API или QA-аналитикам, сохранять запросы и ответы в коллекциях.

Пример запроса Postman к API

Коллекции могут быть экспортированы разработчиками и импортированы нами во время выполнения задания. Это экономит массу времени при создании собственных запросов, и мы можем сразу же приступить к поиску уязвимостей.

Вышестоящий прокси-сервер

Postman также поддерживает маршрутизацию запросов через системный прокси-сервер или пользовательский сервер. Использование Burp или OWASP ZAP в данном случае – мудрый выбор. Как только мы импортируем и запускаем коллекцию, каждый запрос будет перехватываться и будет готов к проверке и повторному воспроизведению.

В разделе File (Файл) и далее в Settings (Настройки) есть вкладка Proxy (Прокси-сервер), которая должна позволить нам указать локальный проксисервер Burp, 127.0.0.1 на порту 8080 по умолчанию (см. рис.).

Все наши последующие запросы в Postman будут также отображаться на вкладке HTTP history прокси-сервера Burp (см. рис.).

Конфигурация вышележащего прокси-сервера Postman
Burp показывает запросы, сгенерированные Postman

Среда выполнения

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

Создание новой среды в Postman

Во всплывающем окне введите внятное имя и нажмите кнопку Add (Добавить), чтобы создать новую пустую среду выполнения.

Добавление новой среды выполнения в Postman

Запросы теперь могут быть связаны со средой выполнения нашего ECorp API. Коллекции также можно запускать в определенных средах выполнения, что позволяет создавать и передавать переменные между запросами.

На рисунке показан простой GET-запрос, поставленный в очередь для запуска в среде ECorp API.

Указание среды выполнения для запроса

Коллекции

Как уже было сказано, коллекция – это просто список API-запросов в определенной последовательности. Их можно экспортировать в JSON и импортировать в любой клиент Postman, что делает их действительно переносимыми.

Чтобы продемонстрировать всю мощь коллекций Postman, создадим коллекцию для экземпляра нашего уязвимого API, api.ecorp.local, работающего на порту 8081.

Если посмотрим документацию по уязвимому API от Мэтта Вальдеса (Matt Valdes), то заметим, что для большинства взаимодействий требуется токен авторизации, передаваемый через пользовательский HTTP-заголовок X-Auth-Token. Хотя большинство RESTful API пытается использовать заголовок Authorization для токенов, пользовательские заголовки не так уж редки. Такие инструменты, как Burp и Postman, идеально подходят для тестирования безопасности, поскольку бóльшую часть работы можно автоматизировать, даже когда сталкиваемся с отклонениями от нормы.

Документацию можно найти в файле README.md на странице https://github.com/mattvaldes/vulnerable-api.

В документации говорится, что можно получить новый токен, если отпра вить POST-запрос в /tokens, тело которого содержит данные аутентификации в формате JSON. Учетные данные по умолчанию: user1 и pass1. Тело нашего запроса на аутентификацию должно выглядеть так:

{
"auth": {
"passwordCredentials": {
"username": "user1",
"password": "pass1"
}
}
}

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

{
"access": {
"token": {
"expires": "[Expiration Date]",
"id": "[Token]"
},
"user": {
"id": 1,
"name": "user1"
}
}
}

Затем можем передать значение id в конечную точку /user/1 через заголовок X-Auth-Token , и запрос должен быть выполнен успешно.

Успешный аутентифицированный запрос к уязвимому API

Теперь, когда у нас есть последовательность запросов, нам нужно создать коллекцию и частично автоматизировать это тестирование.

И снова с помощью кнопки Create New в левом верхнем углу выберите Collection (Коллекция):

Создание новой коллекции

Во всплывающем окне можно ввести имя и описание, если необходимо, преж­де чем нажать кнопку Create (Создать).

Создание новой коллекции

Все сделанные нами запросы записываются на вкладке История в рабочей области.

Мы можем выделить те, которые нам нужны для коллекции, и нажать кнопку Save (Сохранить) рядом с кнопкой Send (Отправить) в правом верхнем углу.

Сохранение запросов в коллекцию

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

Выбор нужной коллекции

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

Аутентифицированный запрос Postman

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

Для этого нам нужно использовать функцию Postman под названием Tests (Тесты). Каждый запрос настроим на выполнение тестов и выполнение какого-то действия. Как правило, они могут использоваться для того, чтобы проверить, был ли запрос. Разработчики могут использовать тесты, чтобы убедиться, что код, который они только что добавили, ничего не испортил.

Тесты пишутся на JavaScript, поэтому необходимо некоторое количество знаний в области программирования. К счастью, существуют уже готовые тесты, которые мы можем использовать.

Для нашего запроса Get Auth Token в коллекции ECorp API тест должен проверить ответ, проанализировать его как JSON и извлечь идентификатор токена. Чтобы передать его другому запросу, можно использовать среду ECorp API и сохранить данные в переменной, которую мы называем auth_token.

Код для достижения этой цели довольно прост, хотя и выглядит немного странно, если вы не знакомы с JavaScript. Каждая запись pm.test является отдельным тестом, который должен быть выполнен в указанном порядке. Если какой-либо из тестов не будет пройден, мы увидим предупреждение.

pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
pm.test("Save Auth Token", function () {
var data = pm.response.json();
pm.environment.set("auth_token", data['access']['token']['id']);
});

Первый тест просто проверяет наличие ответа 200 от API. Все остальное вызовет ошибку во время запуска коллекции.

Второй тест выполнит парсинг текста ответа с помощью метода json() и сохранит его в локальной переменной data. Если вы помните иерархию ответа /tokens, нам нужно получить доступ к значению id в поле access.token, используя нотацию массива JavaScript: data['access']['token']['id'].

Используя функцию pm.environment.set, сохраняем значение id в переменной среды auth_token, делая его доступным для других запросов.

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

Изучение среды Postman

Наш второй запрос к /user/1 требует, чтобы мы передали это значение через заголовок X-Auth-Token. Добавляем новый пользовательский заголовок и для этого значения извлекаем список существующих переменных, набирая {{ в поле Value (Значение). Postman автоматически заполнит имеющиеся переменные за нас.

Использование переменных среды в запросах

Нажав кнопку Send (Отправить), убеждаемся, что запрос прошел проверку подлинности.

Аутентифицированный запрос успешно выполнен

Запуск коллекции

Коллекции можно экспортировать и импортировать, используя знакомый формат JSON. Импорт – это простая операция перетаскивания. Разработчики и QA-аналитики могут создавать коллекции так же, как мы делали ранее, экспортировать их и в качестве части задания отправлять файл нам. Это значительно упрощает нашу работу по тестированию API, потому что трудоемкая работа уже выполнена.

После импорта коллекцию можно запустить, нажав на кнопку Runner рядом с кнопкой New в меню.

Открытие компонента Runner

Откроется новое окно Collection Runner, содержащее все импортированные коллекции. Выберите коллекцию ECorp API, среду ECorp API и нажмите кнопку Run ECorp API (Запустить API ECorp).

Запуск коллекции ECorp

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

Успешный запуск коллекции

Что еще более важно, все запросы в коллекции переданы на наш проксисервер Burp.

Запуск коллекции, перехваченный Burp

Теперь можем запустить модули Scanner, Intruder и Sequencer или повторно воспроизвести любой запрос, чтобы манипулировать данными и искать уязвимости, как мы обычно делаем, когда работаем с традиционными приложениями.

Факторы атаки

Атаки на API на базе HTTP на самом деле ничем не отличаются от атак на традиционные веб-приложения. Мы должны следовать той же основной процедуре:

Определить точки внедрения;

Отправить непредвиденный ввод и наблюдать за поведением API;

Искать обычных подозреваемых: SQL-инъекции, XXE, XSS, внедрение команд, локальное и удаленное включение файлов.

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

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

В случае с веб-сервисами ответ обычно не отображается, в основном из-за заголовка Content-Type, устанавливаемого в ответе. Обычно это формат JSON или XML, которые большинство браузеров не будет отображать как HTML. Я говорю «большинство», потому что, к сожалению, некоторые старые браузеры по-прежнему отображают контент, игнорируя заголовок Content-Type, указанный сервером, и делая догадки на основе данных в ответе.

В URL-адресе api.ecorp.local/user/1 была обнаружена следующая отраженная проблема ввода:

GET /user/1<svg%2fonload=alert(1)> HTTP/1.1
Content-Type: application/json
X-Auth-Token: 3284bb036101252db23d4b119e60f7cc
cache-control: no-cache
Postman-Token: d5fba055-6935-4150-96fb-05c829c62779
User-Agent: PostmanRuntime/7.1.1
Accept: */*
Host: api.ecorp.local:8081
Connection: close

Передаем полезную нагрузку JavaScript и видим, что API отражает ее обратно клиенту без экранирования.

HTTP/1.0 200 OK
Date: Tue, 24 Apr 2018 17:14:03 GMT
Server: WSGIServer/0.1 Python/2.7.11
Content-Length: 80
Content-Type: application/json
{"response": {"error": {"message": "user id 1<svg/onload=alert(1)>
not
found»}}}

Обычно этого достаточно, чтобы доказать, что уязвимость существует и можно атаковать пользователей с помощью методов социальной инженерии. Однако если приглядеться, то можно заметить, что в значении Content-Type стоит application/json, а это означает, что современные браузеры не будут отображать ответ в виде HTML-кода, что делает нашу полезную нагрузку бесполезной.

API по-прежнему дают какую-то надежду. К веб-сервисам обычно нет прямого доступа в разъединенной среде. Возможно, этот конкретный API используется веб-приложением. Сообщение об ошибке может в конечном итоге попасть в браузер, что может отобразить нашу полезную нагрузку. Что делать, если все ошибки регистрируются в веб-сервисе, а затем аккуратно отображаются в панели состояния, которая видна только внутри? Тогда мы выполним код, написанный на JavaScript, для аналитика, проверяющего состояние API.

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

Report Page