Как стать автором
Обновить

Комментарии 45

Интересно.
Возможно, стоит поподробнее рассказать про то, каким же именно образом используется __defineSetter__?

Я плохо владею терминологией, но если вкратце, то злоумышленник определяет анонимную функцию, которая является setter'ом (установщиком?) свойства объекта. В примере — свойства Id. Таким образом, когда данные будут получены, то вызовется эта функция и в ней злоумышленник может как угодно распорядиться с этими данными.

Object.prototype.__defineSetter__('Id', function(obj){
  alert(obj);
});

Ну чтобы совсем подробно преподробно — метод __defineSetter__ поддерживают текущие версии FF & Chrome и планируется ввести в IE8, про предыдущие IE — неизвестно, что примечательно, раньше с помощью __defineSetter__ можно было уронить Mozilla Firefox < 3.0.7, Thunderbird < 2.0.0.21, and SeaMonkey < 1.1.15

Проверить уязвимость можно зарегистрировавшись на haacked.com и авторизовавшись перейти на страницу: haacked.com/demos/JsonAttack.html

а как же Опера, или Оперу уже за браузер не считают?
в мире — нет, не считают, очень небольшие проценты.
В мире — нет, в СНГ — да, и рас уж мы в рунете — было бы интересно узнать, как дела обстоят с ней.
*раз
Короче, уязвимость только в Fx и в Chrom'е…
Ну ладно. Моя на них не сидить. А прием интересный.
Проверял? Если нет надо будет в IETester проверить…
А если используется JSONP, то всё ещё проще, переопределяем callback-функцию и voilà.
Что если json result будет также банально переопределять Object.prototype.__defineSetter__ на безопасную заглушку, то это решает проблему, так?
Как ты собираешься это банально переопределить в json result?
хотя это лишнее. достаточно добавить соли к урлу
Решает проблему — не отдавать JSON на GET запросы, а только на POST или же проверять наличие в запросе заголовка «X-Requested-With: XMLHttpRequest» или отдавать с заголовком «Content-Type: application/json»
в чем трудность поменять заголовок у запроса?
Угон основан на так называемом «scriptTagProxy». Скажи как ты собираешься сделать так чтобы клиентский браузер наткнувшийся на <script src=«example.com/...»/> отправил заголовок «X-Requested-With: XMLHttpRequest»?
хммм, каюсь, поспешил
Сходил на сайт vulnerable.example.com
Ничего интересного.
You have reached this web page by typing "example.com", "example.net", or "example.org" into your web browser. These domain names are reserved for use in documentation and are not available for registration. See RFC 2606, Section 3.
Я, наверное, чего-то не понимаю, но раз уж мы авторизованы на vulnerable.example.com, то что мешает в файле JsonAttack.html сделать ajax-запрос к vulnerable.example.com/Json, получить нужные данные и отправить их потом на любой url? Причем тогда мы будем вольны выбирать GET, POST или что-нибудь еще.
А как ты передашь авторизационную куку?
А разве браузер не передаст ее самомстоятельно при использовании XhrIframeProxy?
Хотя, конечно, соглашусь, что это уже будет не столь элегантное решение.
Мешает тот забавный факт, что AJAX-запросы (я имею в виду XMLHttpRequest) запрещены к сторонним доменам согласно политикам безопасности браузеров. И сделано это как раз для того, чтобы кто попало не мог через AJAX пользоваться куками пользователя без спроса :)

Что касается scriptTagProxy — он позволяет делать только GET-запросы. Отсюда вывод: правильная защита от атаки — высылка конфиденциальных данных только в ответ на POST-запросы.
пфф, +1 =)
Прежде чем голословно отвергать возможность кросс-доменных ajax-запросов советую погуглить на тему XhrIframeProxy
Если бы вы читали мой пост внимательно, то вы могли бы заметить, что я специально подчеркнул, что речь идет о XMLHttpRequest.

Что касается XhrIframeProxy — с ним не сделаешь POST-запроса.
ага, по вашему мнению я могу сделать страницу и через яваскрипт управлять пользовательским браузером от его имени (типа, «открой-ка страницу mail.google.com и покажи inbox»)? В таком случае даже плевать на json было бы — хоть че качай и парсь.

Дело в том что порсто так XMLHttpRequest куда попало не сделать. Именно поэтому и появился, кстати, JSONP. А вот <script src=""> отфигачит любой сайт, но при этом он должен явно вернуть что то js-совместимое (будь то json или js код).
Дело в том что порсто так XMLHttpRequest куда попало не сделать. Именно поэтому и появился, кстати, JSONP

Я не очень уловил почему именно появился JSONP…
такс. допустим надо получить с сайта Х что то «публичное». Например, набор интересных фоток «на сегодня» с фликра. Ну или что угодно другое, авторы чего готовы предоставить контент через jsonp (т.е. понимают что это вообще нифига не безопасно).

XMLHttpRequest не прокатит — ибо запрос на другой домен не пройдёт.
<script src=""> впринципе прокатит, но при этом нет возможности выполнить колбек. Хотя авторы «фликра» или любого доругого сервиса могут сказать, мол, «мы вам на это вернём flickr_callback(data), а у вас в коде на стороне клиента просто определете нужный колбек с таким названием». Но это уже не так удобно, ибо никто бы толком не договорился какой колбек (название) считать самым важным. Вот тут и появился jsonp.

на запрос ext_server/get_jsonp сервак должен посмотреть какой callback хочется (а мы вызываем это через ext_server/get_jsonp?callback=my_callback). И вернуть данные в виде my_callback([… json data… ]).

JSONP работает только через <script src=""> и только с GET запросами. Зато позволяет на любом сайте получить список фоток фликра =). Фликр тут в пример, только потому что там действительно есть jsonp для этого.

Тем кто предоставляет jsonp надо помнить, что он позволяет любому сайту получить доступ от имени пользователя jsonp-дающего-сайта. А значит — можно использовать только для публичных данных и никак иначе.
«именно поэтому и появился jsonp» — потому что XMLHttpRequest куда попало не сделать, а это и является смыслом jsonp. Я ответил на ваш вопрос? )
Великолепно ответили!
Я узнал, что такое JSONP!
Потому как XMLHttpRequest можно делать только к тому же домену, что и текущая страница. То есть если у вас на сайте страничка со скриптом, то через XMLHttpRequest вы можете запрашивать только свой сайт.
А если в страничку вставить фрейм с адресом другого сайта, то из этого фрейма можно будет делать ajax-запросы к этому сайты, а потом прокидывать данные в основной документ.
каким образом вы вставите свой код во фрейм со страницей чужого сайта?
Вы правы. Приношу извинения за свою невнимательность.
Детальное описание уязвимости, информацию об уязвимых фреймворках и о методах борьбы можно почитать в pdf-ке по первой ссылке в гугле javascript hijacking
Из-за причины данной уязвимости mozilla зачесалась и в частности предложили игнорировать setters в инициализации объектов и массивов (детали по ссылке). Вроде как в Firefox 3.5 (к сожалению проверить нет возможности) данная атака уже не пройдет.
Отличная статья по ссылке. Плюс в комментарии указано, кто же виноват :)
Меня там улыбнуло вот это:
PS. Your blog is hosted on an https server, but the comment form submits to an http server. I had to tweak your page source to submit my comments.
В некотором роде схожая фишка (в том плане, что тоже использует доверие сайта к пользователю): Cross-site request forgery
прочитал статью и коменты и понял что лучше всего использовать xss post для работы асинхронных приложений… :)
Обожаю Javascript! :) Спасибо автору, я узнал про setter'ы, думал их пока нет в JS. Теперь можно будет поиграться.
Про подобные способы можно прочитать на сайте code.google.com/p/doctype/ В частности, для борьбы с такой эксплуатацией JSON-запросов, необходимо в ответ с сервера помещать код, вызывающий ошибку обработки явакрипта. Ну и не забыть отдельное спасибо сказать разработчикам браузеров, которые фактически позволяют выполнять код с разных доменов в одном окне.
Интересно на Head запросы сработает?
Спасибо! Познавательно
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории