Получаем доступ к облаку XenServer через доступ к одной виртуальной машине

Автор: vik_kr Дата: . Категория: Статьи

овсем скоро, 11 марта, стартует online-этап ежегодного соревнования по кибербезопасности NeoQUEST-2016! В преддверии этого публикуем разбор одного из заданий «очной ставки» NeoQUEST-2015. Это задание под названием «Истина где-то рядом» было направлено на получение доступа ко всему облаку XenServer, имея доступ только лишь к одной виртуалке! Такой хак осуществим с помощью специального апплета, ранее используемого XenServer, позволяющего получить доступ по VNC к виртуальной машине.

Под катом опишем исходные данные для задания и расскажем, как можно было пройти это задание двумя способами:

  • используя XenAPI
  • используя Web



 

Исходные данные


Участники в описании задания получили IP-адрес, по которому находился сайт с большой кнопкой «Get Key». При её нажатии появлялась надпись, сообщающая, что были попытки подключения к двум серверам и попытки поиска ключа в базах данных этих серверов. Однако, как информировала та же надпись, подключиться удалось только к первому серверу, и ключ там не нашёлся…



Как видно, к серверу №1 удалось подсоединиться, и даже есть ссылка (слово «OK»). При переходе по ссылке должен запуститься апплет, но, поскольку современные браузеры плохо работают с апплетами, скорее всего, ничего не запустится.



Однако первая же ссылка в гугле говорит: «надо добавить сайт в разрешённый в настройках Java и перезапустить браузер»! Делаем…



После перезапуска браузера появляется окно «Secure Warning», в котором в поле «Publisher» написано Citrix System.



Запустив апплет, участник получал доступ к виртуальной машине. И здесь он должен был понять, что ему дают доступ к виртуальной машине, которая работает на базе продукта Citrix. Загуглив, какие бывают продукты у Citrix, можно предположить, что это XenServer. А чтобы быть до конца в этом уверенным, можно посмотреть на иконку сайта и там увидеть логотип XenServer.



На рабочем столе есть ярлык браузера Chrome, запустив который и открыв историю, можно найти обращение к «localhost/phpmyadmin». Перейдя по этому адресу, можно увидеть базу данных neoquest, в которой есть таблица key, но нет записей…



Виртуалка была одна на всех, и участники активно сражались за нее, отнимая друг у друга управление курсором мыши и мешая своим соперникам просматривать записи в базе данных!

Дальнейшие поиски ключа на этой виртуальной машине бесполезны, попытки найти ещё одну виртуальную машину в сети тоже не дадут результата (у второй виртуальной машины нет сетевого адаптера).

Посмотрев исходный код страницы с апплетом, находим код, отвечающий за его запуск:
 

<applet archive='/q.jar' id=vncapp code='com/xensource/ui/vnc/Initialize.class' width='950' height='720'>
    <PARAM NAME='SESSION' VALUE = 'OpaqueRef:427a76b3-2d50-89bb-28e6-eb9e51c66971'/>
    <PARAM NAME='URL' VALUE ='https://10.0.20.61/console?uuid=b1c1a188-26bf-e5c8-a5ed-7545f17f492b'/>
    <PARAM NAME='USEURL' VALUE ='true'/>
</applet>



В запуске апплета для участника интересны два параметра: SESSION и URL. Из URL видно, что есть ещё один IP-адрес – 10.0.20.61. Заходим на этот IP в браузере и видим: «Citrix Systems, Inc. XenServer 6.2.0», что окончательно убеждает нас, что виртуалка работает на XenServer!

Теперь начинаем искать вторую виртуальную машину. Логично исходить из предположения, что доступ к ней осуществляется также через апплет, через параметр URL, а именно, через значение UUID. Поэтому для дальнейших экспериментов необходимо запустить апплет у себя. Самый простой способ для этого — сохранить html-страницу с апплетом (апплет надо скачать отдельно) и запустить у себя на веб-сервере.

Есть два способа получить значение UUID: через XenAPI или выполнить запрос к серверу через браузер. Рассмотрим оба эти способа по порядку.
 

Способ №1: используем XenAPI


Это было запланированное решение задания. Код будем писать на Python, для этого качаем SDK для XenServer и оттуда берём XenApi.py. 
Нам необходимо получить список всех виртуальных машин, находящихся на сервере, а для них — список их консолей.

Загуглив, как получить список виртуальных машин, можно найти следующий код:
 

session = XenAPI.Session(xen_url)   
session.xenapi.login_with_password(xen_user, xen_pass)
vms = session.xenapi.VM.get_all()
print vms



Где xen_url — адрес сервера, в нашем случае «https://10.0.20.61», xen_user и xen_pass для нас недоступны, но у нас уже имеется значение установленной сессии. Можно попробовать вместо session.xenapi.VM.get_all() передать значение установленной сессии напрямую в метод в следующем виде: session.VM.get_all(ses). Тогда скрипт получения списка виртуальных машин будет иметь следующий вид:
 

import XenAPI
xen_url = "https://10.0.20.61"
session = XenAPI.Session(xen_url)
ses = "OpaqueRef:427a76b3-2d50-89bb-28e6-eb9e51c66971"
vms = session.VM.get_all(ses)
print vms


 

Результат выполнения этого скрипта будет выглядеть так:



Результат получился достаточно большим, и это не список виртуальных машин, а ссылки на них, поэтому логичнее продолжить написание скрипта, так, чтобы получить консоли. Для этого используем стандартную функцию API VM.get_consoles, в итоге получившийся скрипт имеет вид:
 

import XenAPI
xen_url = "https://10.0.20.61"
session = XenAPI.Session(xen_url)
ses = "OpaqueRef:427a76b3-2d50-89bb-28e6-eb9e51c66971"
vms = session.VM.get_all(ses)
for vm in vms['Value']:
    console = session.VM.get_consoles(ses,vm)
    print console


 

Результат выполнения скрипта:



Результат опять достаточно большой, но большинство значений пустые, и, как в прошлый раз, это не сами консоли, а ссылки для них. Также есть виртуальные машины, где две ссылки для консоли. Для преобразования ссылки в значение, пригодное для апплета, используется функция console.get_location. Тогда скрипт имеет вид:
 

import XenAPI
xen_url = "https://10.0.20.61"
ses = "OpaqueRef:427a76b3-2d50-89bb-28e6-eb9e51c66971"
session = XenAPI.Session(xen_url)
vms = session.VM.get_all(ses)
for vm in vms['Value']:
    console = session.VM.get_consoles(ses,vm)
    for con in console['Value']:
        url = session.console.get_location(ses,con)
        print url



Результатом работы скрипта будет:
 

{'Status': 'Success', 'Value': 'https://10.0.20.61/console?uuid=9b7965ed-002b-5d52-4bd6-380556aa2219'}
{'Status': 'Success', 'Value': 'https://10.0.20.61/console?uuid=1a9df134-6e10-22a5-6f99-2d1df8f2fc58'}
{'Status': 'Success', 'Value': 'https://10.0.20.61/console?uuid=68d03d5d-d9cd-0b91-c61f-213f3a572582'}
{'Status': 'Success', 'Value': 'https://10.0.20.61/console?uuid=b1c1a188-26bf-e5c8-a5ed-7545f17f492b'}



Последние значение — такое же, как в поле URL, что подсказывает, что мы на правильном пути! Осталось проверить только 3 решения.
 

Способ №2: через Web


Второе решение гораздо проще и целиком основано на веб. Если загуглить «Xenserver OpaqueRef», то можно наткнуться на описание получения метрик производительности для Xenserver через RRD. Для получение части этих метрик необходимо знать только IP-адрес сервера и OpaqueRef. Так для получения всех метрик виртуальной машины надо знать UUID виртуальной машины «http:///vm_rrd?session_id=OpaqueRef:&uuid=», но для получения обновлений для всех виртуальных машин достаточно знать только OpaqueRef. Его мы получаем запросом «http:///rrd_updates?session_id=OpaqueRef:&start=10258122541». В нашем случае запрос будет иметь вид: «http://10.0.20.61/rrd_updates?session_id=OpaqueRef:427a76b3-2d50-89bb-28e6-eb9e51c66971&start=10258122541».

В результате в браузере отобразится следующая xml:



Из этой xml можно получить 3 UUID: 4ac6b5b5-fb19-4874-b87a-c0da37f807cf, 11c607ae-c779-c9dd-6b5e-17fd4461defe, 362f5638-b9af-56e8-52dd-92f79267f6ef.
Хоть UUID и не совпадают с теми, что есть в задании, но они также подходят!
 

Конец задания


Дальше перебираем имеющиеся UUID или ссылки на имеющейся локальной копии сайта с апплетом. В случае с ссылкой, полученной через API, правильный результат будет — 10.0.20.61/console?uuid=9b7965ed-002b-5d52-4bd6-380556aa2219, а в случае с UUID — 11c607ae-c779-c9dd-6b5e-17fd4461defe. Мы попадаем на клон первой виртуальной машины, но в браузере почищена история. Однако мы помним, что там был phpmyadmin! Заходим на localhost/phpmyadmin, там такая же база – neoquest, с такой же таблицей – key, в которой и лежит ключ:



Таким образом, используя этот апплет, злоумышленник может «угнать» ваше облако XenServer!
 

А регистрация на NeoQUEST-2016 продолжается!


На NeoQUEST-2016 участников ждет множество интересных и разнообразных заданий, как сложных, так и довольно простых, пройти которые под силу даже новичкам в информационной безопасности. Выбирай свою сторону ирегистрируйся!