Так я подумал, и был какое-то время спокоен.
А еще я использовал расширение HTTP Headers, которое помогало мне просматривать заголовки ответов сервера в удобном виде. В один прекрасный день, я увидел на своих ресурсах рекламу, которой там никогда не было. Немного просмотрев код и поэкспериментировав, я понял, что именно это расширение добавляло рекламу на все сайты, которые я посещаю. Код расширения, к сожалению, я не скопировал вовремя, и на данный момент оно уже удалено из магазина расширений с пометкой “ содержит вредоносное ПО”. С этого и начну свой рассказ.
Мне стало очень интересно, как так, ведь у меня есть четкие правила для браузера о политике загрузки скриптов и отправки данных с моей страницы, а тут я вижу, что настройки безопасности ну очень слабо повышают безопасность пользователей, если они пользуются расширениями для браузера (в данном случае конкретно Google Chrome). Поэтому я решил воссоздать такое расширение, которое смогло бы загружать скрипты с удаленного сервера в обход CSP.
Писать расширения для браузера не очень сложно, об этом было много статей, в частности и от Google , поэтому я не буду останавливаться более подробно на самом написании расширения.
В качестве примера, был выбран сайт Яндекс музыка по нескольким причинам:
- У них есть CSP
- У них достаточно мощные сервера чтобы выдержать всех “кому интересно посмотреть”;
- У них не до конца настроен CSP (на момент написания статьи у них стоит content security policy report only, поэтому я смогу увидеть все сообщения об ошибках о некорректном контенте, но самой блокировки происходить не будет)
Собираем зловредное расширение (готовую версию вы можете посмотреть на GitHub):
1. Файл manifest.json
{
"manifest_version": 2,
"name": "CSP vulnerability",
"description": "This is just an example, please do not use it.",
"version": "1.0",
"browser_action": {
"default_icon": "evil.png",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": [ "https://music.yandex.ua/*" ],
"js": [ "evil.js" ],
"run_at": "document_end"
}
],
"permissions": [
"activeTab",
"https://music.yandex.ua/*"
]
}
2. Создать сам «зловредный» скрипт
Внимательно просмотрев, откуда яндекс разрешает загрузить скрипты
"script-src 'self' 'unsafe-eval' vk.com cdn.pushwoosh.com yandex.ua yandex.st yandex.net yastatic.net yandexadexchange.net *.yandex.ru *.yandex.ua *.yandex.net *.yastatic.net *.yandexadexchange.net *.yandex-team.ru .
Я решил что в этом списке явно не хватает гугл-аналитики, поэтому в качестве “зловредного” подгружаемого скрипта, я выбираю https://google-analytics.com/analytics.js, тем более что многие называют Google — “корпорацией добра”. Такой выбор обусловлен следующими критериями:
- Подключаемый скрипт никому не навредит.
- Он точно работает.
- Он будет пытаться сделать ajax запросы.
- Его смогут подключить все, кто захочет
В этом есть еще один бонус, т.к. я смогу подгруженным скриптом симулировать запросы без поднятия своего сервера и дополнительного кода (разумеется, гугл аналитика не даст посмотреть собранную информацию если я не владелец сайта, но я и не преследовал цель собрать какую то информацию, только демонстрация обхода блокировок).
Скрипт беру стандартный, из мануала, только номер счетчика придумываю из головы:
(function (i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r;
i[r] = i[r] || function () {
(i[r].q = i[r].q || []).push(arguments)
}, i[r].l = 1 * new Date();
a = s.createElement(o),
m = s.getElementsByTagName(o)[0];
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m)
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
ga('create', 'UA-00000000-0', 'auto');
ga('send', 'pageview');
Для начала, пробую выполнить этот скрипт из консоли, чтобы проверить, а работает ли вообще CSP на этом сайте, и вижу следующее:
VM636:10 [Report Only] Refused to load the script 'https://www.google-analytics.com/analytics.js' because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-eval' vk.com cdn.pushwoosh.com yandex.ua yandex.st yandex.net yastatic.net yandexadexchange.net *.yandex.ru *.yandex.ua *.yandex.net *.yastatic.net *.yandexadexchange.net *.yandex-team.ru 'nonce-dWVmJGgsauDNxkDyep5LEg=='".
Теперь попробую добавить все то же самое в расширение, и вот, все работает. Скрипт успешно добавлен на страницу, не сгенерировав ни единой ошибки.
Выводы
Да, многие скажут что выбор расширений это личное дело каждого, да и гугл более или менее оперативно заблокировал расширение (в течении недели с того момента как я сам понял, что оно спамит меня рекламой).
С другой стороны, непонятно сколько оно было вредоносным. Я поясню почему именно вредоносное: добавлялась реклама сомнительных товаров, со ссылками на еще более сомнительные сайты, к тому же, мне к сожалению неизвестно, собирало ли расширение какие-то данные о посещенных мною страницах, и если собирало, то какие, ведь с тем же успехом они могли собирать информацию из форм или просто из посещаемых мною страниц.
Мое мнение таково, что если ресурс сообщает браузеру политику поведения с полученной страницей, то эта политика должна быть абсолютной, и распространяться на всё, в том числе и расширения, а как вы считаете?
Комментарии (25)
alexey-m-ukolov
18.11.2016 18:13+12Мое мнение таково, что если ресурс сообщает браузеру политику поведения с полученной страницей, то эта политика должна быть абсолютной, и распространяться на всё, в том числе и расширения, а как вы считаете?
Я не согласен — если я поставил расширение, которое что-то делает со страницей, я не хочу, чтобы эта страница говорила мне что я могу делать, а что нет. Это мой браузер, я в нём царь и бог и никакие CSP мне не указ.
Вопрос с чистоплотностью создателей расширений, разумеется, остаётся открытым.
MikeKosulin
18.11.2016 20:37Я поясню почему именно вредоносное: добавлялась реклама сомнительных товаров, со ссылками на еще более сомнительные сайты, к тому же, мне к сожалению неизвестно, собирало ли расширение какие-то данные о посещенных мною страницах, и если собирало, то какие, ведь с тем же успехом они могли собирать информацию из форм или просто из посещаемых мною страниц.
так написано, будто речь про Яндекс.Советник
plartem
18.11.2016 20:37+1Сейчас на руках нету примера кода, но вообще расширения хрома могут не только просматривать хедеры, но так же редактировать их любым образом(т.е. CSP хедер можно просто удалить)
Nidhognit
18.11.2016 20:39Интересная информация, нужно будет попробовать
plartem
19.11.2016 01:52https://developer.chrome.com/extensions/webRequest — документация по входящим/исходящим хедерам
Пример удаления csp:
chrome.webRequest.onHeadersReceived.addListener(function(details) { for (var i = 0; i < details.responseHeaders.length; i++) { if ('content-security-policy' === details.responseHeaders[i].name.toLowerCase()) { details.responseHeaders[i].value = ''; } } return { responseHeaders: details.responseHeaders }; }, { urls: ["*://*/*"], types: ["main_frame", "sub_frame"]}, ["blocking", "responseHeaders"]);
yarkov
19.11.2016 18:32Если память не изменяет, то можно модифицировать хэдеры запроса браузера, но не ответа от сервера.
Тот же AdBlock, вроде как, перехватывает запрос и если срабатывает фильтр, то блокирует его.
Хотя могу ошибаться, ибо глубоко не копал.
darth_dolphi
19.11.2016 18:33Или подменить, например для нашего аппа это необходимо что бы заблочить весь js-код и отменить загрузку js- файлов, кроме тех что мы сами добавим, но у нас не расширение а app. Страница на которой подменяются хэдеры лежит в webview и от аппа изолирована.
vadim_kudr
18.11.2016 20:37яндекс советник обходит csp для показа своих предложений. вставляет div c ссылкой. если политики лояльные, то к диву js добавляется. еще не все его запросы в network отображаются.
vikarti
19.11.2016 08:31>Мое мнение таково, что если ресурс сообщает браузеру политику поведения с полученной страницей, то эта политика должна быть абсолютной, и распространяться на всё, в том числе и расширения, а как вы считаете?
И как тогда должен работать например Evernote WebClipper? Он же правит DOM (для выделения, для показа своих меню) (запускается правда только по команде пользователя)
Или например — разнообразные расширения для скачивания видео? (или это прикроем под видом того что если бы владелец сайта хотел — он бы разрешил? )
Браузер у нас собственно на чьем железе и в интересах кого работает? Пользователя. И если пользователь поставил расширение которое нарушает CSP… ну значит так надо.
Вот предупреждение при установке что расширение может делать и это (так же как в Хроме расширения пишут например что нужен доступ к сайту X или вообще ко всем сайтам) может быть и имеет смысл.
И разумеется ситуации когда расширение ставится без ведома и желания пользователя надо давить. (то что пользователь не заметил замаскированной галочки — это не согласие).Nidhognit
19.11.2016 18:34Соглашусь. Было бы не плохо видеть все доступы расширений, как, допустим, при установке приложений на телефоне. + если приложение меняет свои права, не обновлять его по умолчанию, а отключать, и ждать ответа пользователя.
Aingis
19.11.2016 12:24+2Надо сказать, что расширения очень удобны для проверки работы того же CSP. Например, есть расширение CSP Tester https://oxdef.info/csp-tester-announcement/ авторства безопасника Яндекса.* Опять же CSP может мешать функциональности расширения. CSP — это главным образом защита от случайного XSS. А те же вредоносы могут перехватывать передачу данных и на уровне сетевого соединения.
* Пользуюсь случаем, передаю привет ТМ, которые считают, что читатели Хабра — люди второго сорта, которые должны страдать от некликабельных ссылок.Lure_of_Chaos
19.11.2016 14:20* Пользуюсь случаем, передаю привет ТМ, которые считают, что читатели Хабра — люди второго сорта, которые должны страдать от некликабельных ссылок.
так «оберегаются» пользователи от потенциальных троллей.ColdPhoenix
19.11.2016 17:11я ссылка
разметка для кого существует?(промазал уровнем)Aingis
19.11.2016 19:46+1Разметка существует не для читателей, у которых карма долгое время только уменьшалась.
P.S. Интересно, что суть комментария Lure_of_Chaos существенно изменилась после моего комментария ниже. Привет от НЛО, у которого нет денег на модерацию, судя по всему.
Aingis
19.11.2016 16:00+1Lure_of_Chaos, У вас карма больше нуля. Можете кликнуть по ссылке? То-то и оно. (Промахнулся веткой.)
Lure_of_Chaos
20.11.2016 16:04Логика ТМ в другом — если карма ниже нуля, то чел нехороший и скорее всего, даст нехорошую ссылку, по которой кликать лучше не надо даже случайно, а если очень надо — то можно выделить и вставить ручками.
Но, как правило, отрицательная карма не у троллей, а просто у тех многих, чье мнение не совпадает с мнением «избранных», причем достаточно одного необдуманного комментария, чтобы карма улетело в неподъемный минус. Следовательно, хорошо бы ТМ пересмотреть еще раз вопросы кармы и возможностей форматирования при ее «задолженности».
Nyxem
19.11.2016 18:36На самом деле, все довольно очевидно. Эта самая политика, если не ошибаюсь, нужна только для того, чтобы ограничивать поведение подключаемых скриптов. Допустим, если вы подключите какую-то библиотеку, то при правильной настройке CSP вам можно будет не беспокоиться, что эта библиотека будет творить какие-нибудь гадости, например, засыпать HTTP-запросами сайт человека, которого невзлюбил автор библиотеки.
Расширения для браузеров стоят уровнем выше. Дело в том, что когда вы устанавливаете расширение, вам говорят, что оно может читать и модифицировать контент страницы https://music.yandex.ua/*. Это правило абсолютно, оно позволяет даже обходить CORS. Соглашаясь с этим, вы должны осознавать последствия, которые могут быть, если разработчик расширения внезапно лишится совести.
Rampages
19.11.2016 21:45Например всякие savefrom net, который до сих пор можно установить (но не из каталога расширений, а с сайта разработчика), на сайтах магазинов и всяких яндекс.маркетов наверху страницы вставляет блок с таргетированной рекламой и предложением купить этот же товар на eBay или еще где, по более низкой цене.
Да и в каталоге расширений, если поискать то можно найти много расширений, которые что-то непонятное делают с браузером, особенно это касается расширений с играми (всякие моды для браузерных игр).
Mihail57
Мне кажется, или при внедрении такой политики безопасности, уйдут в историю некоторые блокираторы рекламы? Так же что делать с локальными файлами, подключаемыми расширениями?
bnytiki
Блокираторы рекламы работают прежде всего для той рекламы, которую ставят владельцы сайтов.
Сами владельцы сайтов…
Nidhognit
Я не против если на странице что то блокируется, но вот добавлять новое без ведома владельца, или тем более передавать с нее данные, если владелец на прямую запрещает, уже немного нарушает безопасность. Разумеется по моему мнению.
Fenex
Сомневаюсь, что можно придумать какую-нибудь реализацию политики работы расширений, с помощью которой можно было бы только удалять информацию со страницы сайта, но не добавлять. Что-то вроде такой ситуации: appendChild не доступен, зато removeChild — пожалуйста. Да и вообще, попахивает бредом немножко: вся суть расширений сведётся на нет :)
И потом, у расширений есть страница background, которая вообще не имеет никакого отношения к открытым страницам в браузере. Зато эта фоновая страница имеет доступ к скриптам content_script (и наоборот). Через фоновую страницу можно сделать любой ajax-запрос, а потом переслать информацию в content_script, который имеет доступ к необходимой странице (в частности, к DOM). В этом случае мы де-факто политику безопасности не нарушаем: с самой страницы никаких запросов не идёт.
Контроль расширений идёт именно при установке: выдача прав (указанных в «permissions») конечным пользователем.
dj_raphael
Если запретят, я перейду на другой браузер. браузер мой и я могу делать со скаченым контентом всё что хочу.