Hallo,
heute möchte ich eine Kleinigkeit vorstellen die mir doch ein wenig Spaß erbracht hatte
Im Prinzip hatte ich vor einen TeamSpeak Telnet komplett zu emulieren und potentiellen Query abfragen komplett absurde Ergebnisse zu liefern,
da das jedoch ein enormer Aufwand geworden wäre um die ganzen Commands mit deren dazugehörigen Parametern zu parsen
habe ich mir einen richtigen TeamSpeak Server hergenommen um ledeglich einige Response Parameter auszutauschen.
Die NodeJS App Funktioniert im Prinzip so:
Ein Telnet Client baut die Verbindung zum NodeJS Server auf
Der NodeJS Server baut daraufhin eine Verbindung zum TeamSpeak Server via Query auf
Jede Request welche der NodeJS Server entgegen nimmt wird ohne weiteres zur TeamSpeak Query weitergeleitet
Jede Response welche von der TeamSpeak Query empfangen wird läuft durch eine String Replacer Function und wird dann zum Telnet Client gesendet
klingt doch relativ harmlos?
Durch das dass ich zuerst bei der Slot Anzahl dann 10 Millionen belegte Slots zurück gesendet habe hatte es zuerst bei TSViewer/TS3Index deren Graphen ein wenig zerschossen (war ziemlich Lustig mit anzusehen)
Natürlich kamen durch die manipulation durch den Graphen auch Ideen eines nicht so fremden Native Network Forum Nutzers
Spoiler anzeigen
jedoch ist mir das aus Zeitlichen gründen dann nicht ausgegangen
XSS (https://en.wikipedia.org/wiki/Cross-site_scripting)
Ein anderer meinte dann zu mir ich solle versuchen JavaScript Code in deren Seite einzufügen
Da über Server Name / Server Welcome Text das sicher escaped wird habe ich es zuerst über den Betriebssystem Namen versucht auszugeben (ohne Erfolg)
danach über die Versions Nummer (ERFOLG!), es wurde beim Laden der Server Seite ein einfaches alert getriggert welches auf der Seite ein harmloses "Hi!" anzeigte
Natürlich habe ich sofort einen TS3Index Supporter angeschrieben,
scheinbar ein wenig inkompetent weil er nicht wusste wie Schwerwiegend eine derartige Lücke sein kann wenn man diese richtig ausnutzen würde weil eh nur ~70 Zeichen in das Server Versions Feld reinpassen würden
und hat aber nicht gewusst dass du da auch externe Scripts einbetten könntest und von einem externen Script so wesentlich mehr Code ausführen könntest.
Nichts desto trotz wurde die Lücke dann zügig innerhalb von ~4 Stunden geschlossen
Hier noch ein Bild von veränderten Daten welche von TS3Index ausgegeben wurden (Versions Nummer und Betriebssystem)
Spoiler anzeigen
Und von TS3Viewer.com habe ich noch ein Bild der falschen Slotzahlen
Spoiler anzeigen
Nun ein wenig zum eigentlichen Script welches ich gebaut hatte um dies zu ermöglichen,
teils gibts noch Probleme mit dem richtigen schließen einer Verbindung (TSViewer hat die Request zwar verarbeitet aber Fehler gebracht dass die Abfrage nicht in Ordnung war)
Ich habe hierbei die NodeJS Version v6.4.0 genutzt
/*--------------------------------------------------------------------------
"THE BEER-WARE LICENSE" (Revision 42):
<[email protected]> wrote this thing. As long as you retain this notice you
can do whatever you want with this stuff. If we meet some day, and you think
this stuff is worth it, you can buy me a beer in return - David K.
--------------------------------------------------------------------------*/
var net = require("net");
const CONFIG = {
listenport: 10011, //External Port on which this Scripts listen to
ts3: ["10.10.12.102", 10011] //TeamSpeak Connection Data IP + Query Port
}
var repl = {
virtualserver_name:"Hi",
virtualserver_platform:"NodeJS",
virtualserver_version:"1.3.3.7\\s[Build:\\s1234567890]",
virtualserver_maxclients:"1",
virtualserver_clientsonline:"2048",
virtualserver_uptime:"98921412412",
virtualserver_total_ping:"1.0000"
}
var replacer = (str) => {
for (var k in repl) {
var regex = new RegExp(k+"=[\\S]{1,}", "g")
str = str.replace(regex, k+"="+repl[k]);
}
return str;
}
net.createServer((socket) => {
console.log("Query Connected! ("+socket.remoteAddress+")")
var remote = net.connect(CONFIG.ts3[1], CONFIG.ts3[0]);
socket.on('data', (stream) => {
remote.write(stream);
})
remote.on('data', (stream) => {
socket.write(replacer(String(stream)));
})
socket.on('end', () => {
remote.end();
console.log("Query Disconnected! ("+socket.remoteAddress+")")
});
remote.on('end', () => {
socket.end();
});
remote.on('error', () => {});
socket.on('error', () => {});
}).listen(CONFIG.listenport);
Alles anzeigen
const CONFIG = {
listenport: 10011, //External Port on which this Scripts listen to
ts3: ["10.10.12.102", 10011] //TeamSpeak Connection Data IP + Query Port
}
Ist eigentlich selbst erklärend^
Es sollte ebenfalls ein TeamSpeak Whitelist Eintrag aktiv sein damit der NodeJS Server nicht gebannt wird
var repl = {
virtualserver_name:"Hi",
virtualserver_platform:"NodeJS",
virtualserver_version:"1.3.3.7\\s[Build:\\s1234567890]",
virtualserver_maxclients:"1",
virtualserver_clientsonline:"2048",
virtualserver_uptime:"98921412412",
virtualserver_total_ping:"1.0000"
}
var replacer = (str) => {
for (var k in repl) {
var regex = new RegExp(k+"=[\\S]{1,}", "g")
str = str.replace(regex, k+"="+repl[k]);
}
return str;
}
Alles anzeigen
Hier ist der eigentliche Teil welcher die ganzen Responses filtert und ggf abändert und dann in der Funktion ausgegeben wird
In der Variable "repl" werden die keywords angegeben mit der Variable die ersetzt werden soll (die Liste kann also nach belieben angepasst werden)
Bei TeamSpeak müssen "Leertasten" bzw Whitespaces mit "\s" escaped werden, durch das dass NodeJS ein einfaches "\" selber noch im String verarbeitet muss das Backslash ebenfalls mit einem weiteren Backslash escaped werden
> "\\s" um ein Leerzeichen anzeigen zu lassen
net.createServer((socket) => {
console.log("Query Connected! ("+socket.remoteAddress+")")
var remote = net.connect(CONFIG.ts3[1], CONFIG.ts3[0]);
socket.on('data', (stream) => {
remote.write(stream);
})
remote.on('data', (stream) => {
socket.write(replacer(String(stream)));
})
socket.on('end', () => {
remote.end();
console.log("Query Disconnected! ("+socket.remoteAddress+")")
});
remote.on('end', () => {
socket.end();
});
remote.on('error', () => {});
socket.on('error', () => {});
}).listen(CONFIG.listenport);
Alles anzeigen
Hier werden die einzelnen Requests von TeamSpeak Server und dem Telnet Client abgefertigt
in der Variable "remote" ist die Verbindung zum TeamSpeak Server "abgespeichert"
danach registriere ich events um die Daten zu bekommen
beim socket.on empfange ich die Daten vom Telnet Client und sende diese weiter an die TeamSpeak Query
bei remote.on empfange ich Daten von der TeamSpeak Query, parse die Response und schicke sie zurück an den Telnet Client
baut nicht zu viel Scheisse
happy Slot Faking