Pull to refresh

Безопасность. Модификация кода ядра платформы подгружаемыми апплетами

Reading time 4 min
Views 660
Все что описано ниже касается только клиентской части реализованной на JavaScript. Приветствуется критика технического характера (например, пути обхода), но не критка в стиле «нафига это нужно».

При разработке модуля подключения апплетов к некой платформе (назовем ее Hyper) появилась задача обеспечения безопасности, так как подключаемый апплет кроме пассивного блока данных (content) содержит и активный (code). А в активном блоке невнимательный разработчик (злоумышленник) может обратиться к глобальному объекту window и получить доступ к переменным или важным методам ядра и сделать подмену, что в лучшем случае просто приведет к краху платформы (в пределах браузера конечно), а в худшем установка различных хуков не влияющих на работу системы, но перехватывающих персональные данные пользователя. В дальнейшем ничего не подозревающий пользователь будет пользоваться гаджетом «Часы от Боба», который по тихому собирает о нем информацию, или рассылает спам по адресам из контакт листа.

Уже была рассмотрена проблема коллизий глобальных переменных и предложено решение об изоляции подгружаемого кода от кода ядра платформы. Всем известно что при создании переменной в глобальном пространстве имен она становится свойством объекта window. Например var a = 10; одно и тоже что window.a = 10;

Наша задача изолировать код ядра чтобы сторонние скрипты не смогли получить к нему доступ. Изоляция базируется на создании анонимной функции и моментального вызова этой функции для инициализации локальных переменных и объектов.
Пример: (function () { a = 10; })(); Функция анонимна и не будет видна через объект window.

Заведем простенькое ядро:

var Core = {};
Core.sName = «MyCore»;
Core.MyMethod = function(sMyValue) { alert(sMyValue); };
* This source code was highlighted with Source Code Highlighter.

Изолируем ядро:

(function () {
 var Core = {};
 Core.sName = «MyCore»;
 Core.MyMethod = function(sMyValue) { alert(sMyValue); };
})();
* This source code was highlighted with Source Code Highlighter.


Теперь создадим функцию загрузки апплета:

Applet.Link = function(sCode, oContext) { (new Function(sCode)).call(oContext); }, где

sCode — исполняемый код апплета, oContext — важный параметр. Если взглянуть шире то это понятие контекста из мира desktop программного обеспечения. Кто писал на ассемблере под protected mode поймут о чем речь. Вкратце контекст содержит информацию о состоянии системы. В desktop приложениях там сохраняется информация о регистрах, т.е. само приложение может их менять и при этом не нарушая работу всей системы. В нашем случае контекст содержит переменные и объекты платформы необходимые для работы апплета. Наша задача при запуске апплета на исполнение сформировать контекст. Для этого нам необходимо знать какие переменные и методы платформы нужны коду апплета. Будем рассматривать уже созданные объекты. Допустим апплету нужен метод MyMethod из пространства имен Core.
Создание контекста будем делать вручную (в Hyper это все автоматизировано, есть описатель апплета в xml формате и понятие ImportBlock, где перечисляются импортируемые переменные и объекты). В статье для усвоения материала все упрощено. Итак получаем контекст: var oContext = { MyMethod: Core.MyMethod) }. Обьединим это все в коде:

(function() {

 // Core module.
 var Core = {};
 Core.sName = «MyCore»;
 Core.MyClass = function() {};
 Core.MyClass.prototype.MyMethod = function(sMyValue) { alert(sMyValue); };

 // Applet module.
 Applet = {};
 Applet.Link = function(sCode, oContext) { (new Function(sCode)).call(oContext); }

 // Load applet module.
 var sCode = «this.MyMethod('Hello world');»;
 var oContext = { MyMethod: Core.MyMethod };
 Applet.Link(sCode, oContext);

})();
* This source code was highlighted with Source Code Highlighter.

Что происходит в полученном коде? Cоздается апплет с кодом: this.MyMethod('Hello world'); Так как функция с данным кодом запускалась в контексте объекта oContext содержащего свойство MyMethod, это свойство становится доступным в теле этой функции через this. Работа апплета выведет алерт с текстом Hello world. Вернемся к злоумышленникам или просто невнимательным разработчикам.
Был создан апплет #1 с кодом и запущен на исполнение:

this.MyMethod = function() { alert(«Hack!!!») };
this.MyMethod('Hello world!!!');
* This source code was highlighted with Source Code Highlighter.

В результате этот апплет покажет алерт с текстом Hack. Апплет пытается заменить метод из пространства имен Core, но на самом деле он поменяет метод только в своем контексте. И поэтому другой апплет использующий тот же метод отработает нормально.

Создан апплет #2 с кодом и запущен на исполение:

Core.MyMethod = function() { alert('Hack!!!'); };

Здесь злоумышленник в наглую попытался изменить Core.MyMethod, но его апплет отработает с ошибкой, потому что Core неопределен и мы знаем почему.
И теперь весь код:

(function() {

 // Core module.
 var Core = {};
 Core.sName = «MyCore»;
 Core.MyMethod = function(sMyValue) { alert(sMyValue); };

 // Applet module.
 Applet = {};
 Applet.Link = function(sCode, oContext) { (new Function(sCode)).call(oContext); };

 // Load applet module from hacker #1.
 var sCode = «this.MyMethod = function() { alert('Hack!!!'); }; this.MyMethod('Hello world');»;
 var oContext = { MyMethod: Core.MyMethod };
 Applet.Link(sCode, oContext);

 // Load applet module from hacker #2.
 var sCode = «Core.MyMethod = function() { alert('Hack!!!'); };»;
 var oContext = { MyMethod: Core.MyMethod };
 Applet.Link(sCode, oContext);

 // Load applet module from right developer.
 var sCode = «this.MyMethod('Hello world');»;
 var oContext = { MyMethod: Core.MyMethod };
 Applet.Link(sCode, oContext);

})();
* This source code was highlighted with Source Code Highlighter.

ВАЖНО!!! При формировании контекста необходимо следить чтобы туда не попала ссылка на объект, иначе вредоносный апплет сможет подменить весь объект с методами и уже вся платформа будет работать с вредоносным кодом. Проблема решается написанием функции для формирования контекста, которая учитывает все что импортируется и производит копирование по иерархии объекта.

Вывод: Была рассмотрена вторая проблема безопасности платформы имеющей возможность разработки апплетов под нее. Первая, напомю, это коллизии имен переменных в глобальном пространстве имен. Есть еще третья проблема это доступ к глобальным свойствам браузера (window, document и т.д.), но эта тема для другой статьи.
Tags:
Hubs:
+14
Comments 53
Comments Comments 53

Articles