JSONP
JSONP или JSON-P (JSON с дополнением) — это исторический метод JavaScript для запроса данных путем загрузки <script>
элемент, [1] который представляет собой элемент, предназначенный для загрузки обычного JavaScript. Его предложил Боб Ипполито в 2005 году. [2] JSONP позволяет совместно использовать данные в обход политики одного и того же происхождения, которая запрещает запуск кода JavaScript для чтения элементов DOM мультимедиа или данных XMLHttpRequest , полученных за пределами исходного сайта страницы. Исходный сайт обозначается комбинацией схемы URI , имени хоста и номера порта .
JSONP уязвим из-за того, что источник данных заменяет безобидный вызов функции вредоносным кодом, поэтому он был заменен механизмом совместного использования ресурсов между источниками (доступен с 2009 года). [3] ) в современных приложениях.
Функциональность
[ редактировать ]HTML <script>
элементу обычно разрешено выполнять код JavaScript, полученный из сторонних источников. Однако службы, отвечавшие чистыми данными JSON , не могли обмениваться данными из иностранных источников до принятия CORS ( совместное использование ресурсов между источниками ).
Например, запрос в зарубежную службу http://server.example.com/Users/1234
может вернуть запись о человеке по имени Клем в формате JSON. Синтаксис JSON соответствует синтаксису объектов JavaScript.
{
"Name": "Clem",
"Id": 1234,
"Rank": 7
}
Без поддержки CORS попытка использовать данные в разных доменах приводит к ошибке JavaScript.
<script type="application/javascript"
src="http://server.example.com/Users/1234">
</script>
Браузер загрузит <script>
файл, оценить его содержимое, ошибочно интерпретировать необработанные данные JSON как блок и вызвать синтаксическую ошибку. Даже если данные интерпретировались как литерал объекта JavaScript, к ним не мог бы получить доступ JavaScript, запущенный в браузере, поскольку без присвоения переменной литералы объекта недоступны.
В шаблоне использования JSONP URL-запрос, на который указывает src
атрибут в <script>
Элемент возвращает данные JSON с кодом JavaScript (обычно вызовом функции), заключенным вокруг него. Эта «обернутая полезная нагрузка» затем интерпретируется браузером. Таким образом, функция, которая уже определена в среде JavaScript, может манипулировать данными JSON. Типичный запрос и ответ JSONP показаны ниже.
Вызов функции parseResponse() — это буква «P» в JSONP — «заполнение» или «префикс» вокруг чистого JSON. [4] Чтобы JSONP работал, сервер должен ответить ответом, включающим функцию JSONP. JSONP не работает с результатами в формате JSON. Вызов функции JSONP, который отправляется обратно, и полезные данные, которые получает функция, должны быть согласованы между клиентом и сервером. По соглашению, сервер, предоставляющий данные JSON, предлагает запрашивающему веб-сайту назвать функцию JSONP, обычно используя имя jsonp или обратный вызов в качестве именованного параметра строки запроса, в своем запросе к серверу: <script src="http://server.example.com/Users/1234?callback=parseResponse"></script>
.
В этом примере полученная полезная нагрузка будет такой:
parseResponse({"Name": "Clem", "Id": 1234, "Rank": 7});
Внедрение элемента сценария
[ редактировать ]JSONP имеет смысл только при использовании с элементом сценария. Для каждого нового запроса JSONP браузер должен добавить новый <script>
элемент или повторно использовать существующий. Первый вариант — добавление нового элемента сценария — осуществляется посредством динамической манипуляции с DOM и известен как внедрение элемента сценария . <script>
элемент вводится в HTML DOM с URL-адресом желаемой конечной точки JSONP, установленным как атрибут «src». Такое динамическое внедрение элемента сценария обычно выполняется с помощью вспомогательной библиотеки JavaScript. jQuery и другие платформы имеют вспомогательные функции JSONP; есть и самостоятельные варианты.
Пример использования jQuery для динамического внедрения элемента сценария для вызова JSONP выглядит следующим образом:
$.getScript("http://server.example.com/Users/192.168.73.96?callback=parseResponse");
После внедрения элемента браузер оценивает его и выполняет HTTP GET для URL-адреса источника, получая содержимое. Затем браузер оценивает возвращаемую полезную нагрузку как JavaScript. Обычно это вызов функции. Таким образом, использование JSONP может позволить страницам браузера работать с политикой одного и того же источника посредством внедрения элемента сценария. [5]
Сценарий выполняется в пределах включаемой страницы и, как таковой, по-прежнему подвергается междоменным ограничениям относительно домена включаемой страницы. Это означает, что веб-страница не может, например, загрузить библиотеку, размещенную на другом сайте, через JSONP, а затем выполнить запросы XMLHttpRequest к этому сайту (если не поддерживается совместное использование ресурсов между источниками (CORS)), хотя такую библиотеку можно использовать для сделать XMLHttpRequests на свой сайт.
Проблемы безопасности
[ редактировать ]Ненадежный сторонний код
[ редактировать ]Включение элементов сценария с удаленных серверов позволяет удаленным серверам вставлять любой на веб-сайт контент. Если на удаленных серверах есть уязвимости, позволяющие внедрение JavaScript, страница, обслуживаемая с исходного сервера, подвергается повышенному риску. Если злоумышленник сможет внедрить любой JavaScript в исходную веб-страницу, то этот код сможет получить дополнительный JavaScript из любого домена, минуя политику одного и того же происхождения . [6] HTTP-заголовок политики безопасности контента позволяет веб-сайтам сообщать веб-браузерам, из каких доменных сценариев можно включать.
Примерно в 2011 году была предпринята попытка определить более безопасное строгое определение подмножества для JSONP. [1] что браузеры смогут принудительно выполнять запросы сценариев с определенным типом MIME, например «application/json-p». Если ответ не был проанализирован как строгий JSONP, браузер мог бы выдать ошибку или просто проигнорировать весь ответ. Однако от этого подхода отказались в пользу CORS , а правильный тип MIME для JSONP остался. application/javascript
. [7]
Различия в пробелах
[ редактировать ]JSONP имел те же проблемы, что и разрешение JSON с помощью eval()
: оба интерпретируют текст JSON как JavaScript, что означает различия в обработке U+2028 ( разделитель строк ) и U+2029 ( разделитель абзацев ) из собственно JSON. Это сделало некоторые строки JSON незаконными в JSONP; серверы, обслуживающие JSONP, должны были экранировать эти символы перед передачей. [8] Эта проблема теперь исправлена в ES2019. [9]
Манипулирование именами обратного вызова и отраженная атака с загрузкой файла
[ редактировать ]Несанкционированные имена обратного вызова могут использоваться для передачи вредоносных данных клиентам в обход ограничений, связанных с application/json
тип контента, как показано в атаке с отраженной загрузкой файлов (RFD) в 2014 году. [10]
Небезопасные конечные точки JSONP также могут быть заражены вредоносными данными. [11]
Подделка межсайтового запроса
[ редактировать ]Простое развертывание JSONP подвержено атакам с подделкой межсайтовых запросов (CSRF или XSRF). [12] Поскольку HTML <script>
элемент не соблюдает политику одного и того же происхождения в реализациях веб-браузера, вредоносная страница может запрашивать и получать данные JSON, принадлежащие другому сайту. Это позволит оценивать данные в формате JSON в контексте вредоносной страницы, возможно, разглашая пароли или другие конфиденциальные данные, если пользователь в настоящее время вошел в систему на другом сайте.
Розетта Флэш
[ редактировать ]Rosetta Flash — это метод эксплуатации, который позволяет злоумышленнику использовать серверы с уязвимой конечной точкой JSONP, заставляя Adobe Flash Player полагать, что указанный злоумышленником Flash-апплет создан на уязвимом сервере. Flash Player реализует политику одного и того же источника, позволяющую отправлять запросы (с помощью файлов cookie) и получать ответы от хостинг-сайта. Затем апплет может отправить полученные данные обратно злоумышленнику. Это эксплойт для разных источников, эффект которого аналогичен внедрению произвольного Flash-апплета в уязвимый домен. Эксплойт использует полезную нагрузку ActionScript, скомпилированную в SWF-файл, состоящий полностью из буквенно-цифровых символов, путем создания потока zlib с определенным заголовком и блоков DEFLATE со специальным кодированием Хаффмана . Полученный в результате SWF-файл, содержащий только буквы и цифры, затем используется в качестве параметра обратного вызова вызова JSONP. До июля 2014 года уязвимыми были такие известные сайты, как Google, YouTube, Twitter, Yahoo!, Яндекс, LinkedIn, eBay, GitHub, Instagram и Tumblr. [13] Эту уязвимость первоначально обнаружили Эрлинг и Алок Менграджани во время публичной презентации на конференции по безопасности. Эксплуатация уязвимости была впоследствии улучшена Габором Молнаром. инженер по безопасности Google Мишель Спаньоло. Этот термин придумал [14] и имеет CVE - 2014-4671 [15] и CVE- 2014-5333 . [16] Версия Adobe Flash Player 14.0.0.145, выпущенная 8 июля 2014 г., ввела более строгую проверку файлов Flash, [17] а в версии 14.0.0.176, выпущенной 12 августа 2014 г., исправлено окончательное решение: [18] предотвращение работы этого эксплойта.
До исправления Adobe веб-сайты могли защитить себя, добавляя пустой комментарий JavaScript (/**/) или даже просто новую строку в качестве первых байтов ответа JSONP.
История
[ редактировать ]В июле 2005 года Джордж Джемпти предложил добавить к JSON необязательное присвоение переменной. [19] [20] Первоначальное предложение для JSONP, где дополнение является функцией обратного вызова, по-видимому, было сделано Бобом Ипполито в декабре 2005 года. [21] и в настоящее время используется многими приложениями Web 2.0, такими как Dojo Toolkit и Google Web Toolkit .
См. также
[ редактировать ]Ссылки
[ редактировать ]- ^ Перейти обратно: а б «Более безопасный междоменный Ajax с JSON-P/JSONP» . JSON-P.org . Архивировано из оригинала 4 марта 2016 года . Проверено 30 октября 2011 г.
- ^ Ипполито, Боб (5 декабря 2005 г.). «Удаленный JSON — JSONP» . Боб Ипполито о Haskell, Python, Erlang, JavaScript и т . д . Архивировано из оригинала 8 июня 2012 года . Проверено 10 февраля 2017 г. .
- ^ «Обмен ресурсами между источниками» . Могу ли я использовать ... Проверено 4 мая 2020 г.
- ^ «Экспериментальный набор результатов RDF в переводчик JSON» . Архивировано из оригинала 15 ноября 2014 года . Проверено 20 февраля 2012 г.
- ^ «Так как же на самом деле работает JSONP? Несколько простых примеров» . Джейсон Шок . 5 февраля 2013 года . Проверено 26 декабря 2021 г.
- ^ Бен Хаяк (17 октября 2014 г.). «Выполнение метода того же происхождения» (PDF) . Проверено 22 октября 2014 г.
- ^ Грей, Илай (27 июня 2010 г.). «Безопасно ли это для предоставления JSONP?» . stackoverflow.com . Проверено 7 сентября 2012 г.
- ^ «JSON: подмножество JavaScript, которого нет» . Магнус Холм. Архивировано из оригинала 13 мая 2012 года . Проверено 16 мая 2011 г.
- ^ «Включить JSON (он же JSON ⊂ ECMAScript)» . Гитхаб . 24 октября 2022 г. Проверено 24 октября 2022 г.
- ^ Орен Хафиф (2014). «Отраженная загрузка файла — новый вектор веб-атаки» . ТрастВейв . Проверено 25 марта 2015 г.
- ^ «Практическое внедрение JSONP» . 18 января 2017 г.
- ^ Гроссман, Иеремия (27 января 2006 г.). «Продвинутые методы веб-атак с использованием GMail» . Проверено 3 июля 2009 г.
- ^ Микеле, Спаньоло. «Злоупотребление JSONP с Rosetta Flash» . Архивировано из оригинала 21 июля 2014 года . Проверено 20 июля 2014 г.
- ^ «Google — список уязвимостей программного обеспечения, обнаруженных или исправленных сотрудниками Google» . Проверено 29 июля 2014 г.
- ^ «MITRE: CVE-2014-4671» . Проверено 29 июля 2014 г.
- ^ «MITRE: CVE-2014-5333» . Проверено 21 августа 2014 г.
- ^ «Бюллетень по безопасности Adobe APSB14-17» . Проверено 29 июля 2014 г.
- ^ «Бюллетень по безопасности Adobe APSB14-18» . Проверено 21 августа 2014 г.
- ^ «оценка JSON» . 19 июля 2005 г. Архивировано из оригинала 12 февраля 2006 г.
- ^ «json: Сообщение: Re: Комментарии» . 17 августа 2005 г. Архивировано из оригинала 22 июля 2012 г.
- ^ «Удаленный JSON — JSONP» . из __future__ import * . Bob.pythonmac.org. 5 декабря 2005 г. Архивировано из оригинала 4 декабря 2009 г. Проверено 8 сентября 2008 г.
Внешние ссылки
[ редактировать ]- серверный фильтр оборачивает любой ответ в обратный вызов jsonp – делается с помощью исходного кода jsonp-java
- Потенциальные проблемы безопасности, связанные с JSON.
- Источник данных JSONP для удаленных доменов