Server-side parameter pollution

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

  • Переопределять уже заданные параметры.

  • Менять поведение приложения.

  • Получать доступ к данным без надлежащих прав.

Проверять на загрязнение параметров можно любой пользовательский ввод. К примеру, уязвимыми могут оказаться query-параметры, поля форм, заголовки и параметры в пути URL.

Note

Эту уязвимость иногда называют HTTP parameter pollution. Однако этим же термином обозначают и технику обхода WAF. Чтобы избежать путаницы, в этой теме будем говорить только о загрязнении параметров на стороне сервера.

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

Проверка загрязнения параметров в строке запроса

Чтобы проверить загрязнение параметров на стороне сервера в строке запроса, подставьте в ввод специальные символы синтаксиса запроса — например #, & и = — и посмотрите, как на это реагирует приложение.

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

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

Усечение query string

Можно попытаться усечь серверный запрос, используя URL-кодированный символ #. Чтобы проще было трактовать результат, после # можно добавить любую строку.

Например, так:

Фронтенд попытается обратиться к следующему URL:

Note

Крайне важно кодировать # в URL. Иначе фронтенд воспримет его как идентификатор фрагмента и не передаст во внутренний API.

Изучите ответ и попробуйте понять, было ли усечение. Например, если в ответе вернулся пользователь peter, это может означать, что серверный запрос был усечён. Если же приложение возвращает ошибку Invalid name, возможно, оно сочло foo частью имени пользователя — и это, в свою очередь, намекает, что усечения не произошло.

Если удаётся усечь серверный запрос, исчезает необходимость в том, чтобы поле publicProfile было установлено в true. Иногда это можно использовать, чтобы получать непубличные профили пользователей.

Внедрение некорректных параметров

Можно попробовать добавить второй параметр в серверный запрос, используя URL-кодированный символ &.

Например:

Это приведёт к следующему серверному запросу к внутреннему API:

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

Чтобы сложить более полную картину, потребуется дальнейшее тестирование.

Внедрение корректных параметров

Если удаётся менять query string, затем можно попробовать добавить во внутренний запрос второй, но уже корректный параметр.

Связанные страницы

О том, как находить параметры, которые можно внедрять в строку запроса, см. раздел Поиск скрытых параметров API.

Например, если удалось обнаружить параметр email, его можно добавить так:

В результате внутренний API получит запрос:

Изучите ответ, чтобы понять, как приложение разбирает дополнительный параметр.

Переопределение существующих параметров

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

Например:

Это приведёт к следующему запросу во внутренний API:

Внутренний API видит два параметра name. Последствия зависят от того, как конкретная технология обрабатывает повторяющийся параметр — и это поведение различается. Например:

  • PHP учитывает только последний параметр. В итоге поиск будет по carlos.

  • ASP.NET объединяет оба параметра. В итоге поиск будет по peter,carlos, что может привести к ошибке Invalid username.

  • Node.js / express учитывает только первый параметр. В итоге поиск будет по peter, и результат не изменится.

Если удаётся переопределить исходный параметр, это может дать возможность для эксплуатации. Например, можно добавить name=administrator — и это иногда позволяет войти в систему как пользователь administrator.

Проверка загрязнения параметров в REST-путях

В RESTful API имена и значения параметров могут размещаться не в строке запроса, а прямо в пути URL. Например, путь:

Можно разложить так:

  • /api — корневой API-эндпоинт.

  • /users — ресурс, в данном случае пользователи.

  • /123 — параметр, здесь идентификатор конкретного пользователя.

Представим приложение, которое позволяет редактировать профили пользователей по их имени. Запросы отправляются на такой эндпоинт:

Это приводит к следующему запросу на стороне сервера:

Злоумышленник может попытаться манипулировать параметрами в пути URL на стороне сервера, чтобы эксплуатировать API. Для проверки добавьте последовательности path traversal, изменяющие параметры, и наблюдайте за реакцией приложения.

Можно отправить URL-кодированное peter/../admin в качестве значения параметра name:

Это может привести к следующему запросу на стороне сервера:

Если серверный клиент или бэкендовый API нормализует путь, он может разрешиться в /api/private/users/admin.

Проверка загрязнения параметров в структурированных форматах данных

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

Представим приложение, в котором пользователь редактирует профиль, а изменения применяются запросом к серверному API. Когда вы меняете имя, браузер делает запрос:

Это приводит к следующему запросу на стороне сервера:

Можно попробовать добавить параметр access_level следующим образом:

Если пользовательский ввод вставляется в серверный JSON без достаточной валидации или очистки, это приводит к такому серверному запросу:

В результате пользователь peter может получить права администратора.

Связанные материалы

О том, как находить параметры, которые можно внедрять в строку запроса, см. раздел Поиск скрытых параметров API.

Рассмотрим похожий пример, но теперь пользовательский ввод на стороне клиента находится в JSON-данных. Когда вы меняете имя, браузер отправляет:

Это приводит к следующему запросу на стороне сервера:

Можно попытаться добавить параметр access_level так:

Если ввод декодируется, а затем добавляется в серверный JSON без корректного экранирования, получится такой серверный запрос:

И снова это может привести к тому, что пользователь peter получит права администратора.

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

Note

Хотя пример выше — в JSON, загрязнение параметров на стороне сервера может встречаться в любом структурированном формате данных. Пример для XML см. в разделе XInclude attacks

Проверка автоматизированными средствами

Burp включает автоматизированные инструменты, которые помогают выявлять уязвимости класса server-side parameter pollution.

Burp Scanner автоматически обнаруживает подозрительные преобразования ввода при выполнении аудита. Это ситуации, когда приложение получает пользовательский ввод, как-то его преобразует, а затем продолжает обработку уже преобразованного результата. Такое поведение само по себе не обязательно является уязвимостью, поэтому потребуется дополнительная проверка вручную, описанными выше методами. Подробнее см. описание проблемы Suspicious input transformation.

Также можно использовать расширение Backslash Powered Scanner для поиска серверных инъекций. Сканер классифицирует ввод как boring, interesting или vulnerable. Интересные находки нужно разбирать вручную, применяя методы, описанные выше. Подробнее см. Backslash Powered Scanning: hunting unknown vulnerability classes.

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

Чтобы предотвратить server-side parameter pollution, используйте список разрешенных символов, которые не требуют кодирования, и убедитесь, что весь прочий пользовательский ввод кодируется до включения в серверный запрос. Также важно следить, чтобы весь ввод соответствовал ожидаемому формату и структуре.

Last updated