Add XSS implementation (supports both internal and yellows fork)

This commit is contained in:
elijahr2411 2023-01-29 17:58:44 -05:00
parent 517ae3c2e8
commit d5bd23d5db
5 changed files with 53 additions and 13 deletions

4
dist/index.html vendored
View file

@ -114,6 +114,10 @@
<div class="input-group"> <div class="input-group">
<span class="input-group-text bg-dark text-light" id="username">Username</span> <span class="input-group-text bg-dark text-light" id="username">Username</span>
<input type="text" class="form-control bg-dark text-light" id="chat-input"/> <input type="text" class="form-control bg-dark text-light" id="chat-input"/>
<div class="input-group-text bg-dark text-light" id="xssCheckboxContainer">
<input class="form-check-input" type="checkbox" value="" id="xssCheckbox"/>
<label class="form-check-label" for="xssCheckbox">XSS</label>
</div>
<button class="btn btn-primary text-light" type="button" id="sendChatBtn"><i class="fa-solid fa-paper-plane"></i></button> <button class="btn btn-primary text-light" type="button" id="sendChatBtn"><i class="fa-solid fa-paper-plane"></i></button>
</div> </div>
</div> </div>

4
dist/style.css vendored
View file

@ -78,3 +78,7 @@
#qemuMonitorOutput { #qemuMonitorOutput {
height: 180px; height: 180px;
} }
#xssCheckboxContainer {
display: none;
}

View file

@ -10,5 +10,10 @@ export const config = {
"wss://computernewb.com/collab-vm/vm7", "wss://computernewb.com/collab-vm/vm7",
"wss://computernewb.com/collab-vm/vm8", "wss://computernewb.com/collab-vm/vm8",
], ],
chatSound: "https://computernewb.com/collab-vm/notify.ogg" chatSound: "https://computernewb.com/collab-vm/notify.ogg",
// What XSS implementation the server uses
// 0: No XSS (If you're using upstream it will be this)
// 1: Internal fork style (main vms only, global opcode 21)
// 2: yellows111/collab-vm-server style (per-user opcode 21)
xssImplementation: 1,
} }

View file

@ -7,7 +7,7 @@ import { makeperms } from "./permissions";
// Has turn = 0 // Has turn = 0
// In queue = <queue position> // In queue = <queue position>
var turn = -1; var turn = -1;
var perms = makeperms(0); var perms = makeperms(0, config);
var rank = 0; var rank = 0;
var connected = false; var connected = false;
const vms = []; const vms = [];
@ -53,6 +53,8 @@ const votetime = document.getElementById("votetime");
const staffbtns = document.getElementById("staffbtns"); const staffbtns = document.getElementById("staffbtns");
const qemuMonitorInput = document.getElementById("qemuMonitorInput"); const qemuMonitorInput = document.getElementById("qemuMonitorInput");
const qemuMonitorOutput = document.getElementById("qemuMonitorOutput"); const qemuMonitorOutput = document.getElementById("qemuMonitorOutput");
const xssCheckbox = document.getElementById("xssCheckbox");
const xssCheckboxContainer = document.getElementById("xssCheckboxContainer");
// needed to scroll to bottom // needed to scroll to bottom
const chatListDiv = document.querySelector(".chat-table"); const chatListDiv = document.querySelector(".chat-table");
@ -319,12 +321,12 @@ class CollabVMClient {
return; return;
break; break;
case "1": case "1":
perms = makeperms(65535); perms = makeperms(65535, config);
rank = 2; rank = 2;
break; break;
case "3": case "3":
rank = 3; rank = 3;
perms = makeperms(parseInt(msgArr[3])) perms = makeperms(parseInt(msgArr[3]), config)
} }
this.eventemitter.emit('login', {perms: perms, rank: rank}); this.eventemitter.emit('login', {perms: perms, rank: rank});
usernameSpan.classList.remove("text-light"); usernameSpan.classList.remove("text-light");
@ -347,6 +349,9 @@ class CollabVMClient {
buttons.endTurn.style.display = "inline-block"; buttons.endTurn.style.display = "inline-block";
} }
if (rank === 2) buttons.qemuMonitor.style.display = "inline-block"; if (rank === 2) buttons.qemuMonitor.style.display = "inline-block";
if ((config.xssImplementation === 2 && perms.xss) || (rank === 2 && config.xssImplementation === 1)) {
xssCheckboxContainer.style.display = "inline-block";
}
users.forEach((u) => userModOptions(u.username, u.element, u.element.children[0])); users.forEach((u) => userModOptions(u.username, u.element, u.element.children[0]));
break; break;
case "19": case "19":
@ -516,6 +521,20 @@ class CollabVMClient {
}); });
}, },
qemuMonitor: (cmd) => this.socket.send(guacutils.encode(["admin", "5", this.node, cmd])), qemuMonitor: (cmd) => this.socket.send(guacutils.encode(["admin", "5", this.node, cmd])),
globalXss: (msg) => {
switch (config.xssImplementation) {
case 1:
this.socket.send(guacutils.encode(["admin", "21", msg]));
break;
case 2:
users.forEach((u) => this.socket.send(guacutils.encode(["admin", "21", u.username, msg])));
break;
}
},
userXss: (user, msg) => {
if (config.xssImplementation !== 2 || !users.find(u => u.username === user)) return;
this.socket.send(guacutils.encode(["admin", "21", user, msg]));
}
} }
} }
function multicollab(url) { function multicollab(url) {
@ -614,6 +633,11 @@ function userModOptions(user, tr, td) {
var ip = await vm.admin.getip(user); var ip = await vm.admin.getip(user);
alert(ip); alert(ip);
}); });
if (config.xssImplementation === 2 && perms.xss) addUserDropdownItem(ul, "Direct Message (XSS)", () => {
var msg = window.prompt("Enter message to send");
if (!msg) return;
vm.admin.userXss(user, msg);
});
tr.appendChild(ul); tr.appendChild(ul);
} }
function addUserDropdownItem(ul, text, func) { function addUserDropdownItem(ul, text, func) {
@ -680,15 +704,16 @@ buttons.screenshot.addEventListener('click', async () => {
window.open(url, "_blank"); window.open(url, "_blank");
}); });
chatinput.addEventListener("keypress", (e) => { chatinput.addEventListener("keypress", (e) => {
if (e.key == "Enter") { if (e.key == "Enter") sendChat();
});
buttons.sendChat.addEventListener('click', () => sendChat());
function sendChat() {
if (xssCheckbox.checked)
vm.admin.globalXss(chatinput.value);
else
vm.chat(chatinput.value); vm.chat(chatinput.value);
chatinput.value = "";
}
});
buttons.sendChat.addEventListener('click', () => {
vm.chat(chatinput.value);
chatinput.value = ""; chatinput.value = "";
}); }
buttons.changeUsername.addEventListener('click', () => { buttons.changeUsername.addEventListener('click', () => {
var newuser = window.prompt("Enter new username", window.username); var newuser = window.prompt("Enter new username", window.username);
if (newuser == null) return; if (newuser == null) return;

View file

@ -1,4 +1,4 @@
export function makeperms(mask) { export function makeperms(mask, config) {
const perms = { const perms = {
restore: false, restore: false,
reboot: false, reboot: false,
@ -8,7 +8,8 @@ export function makeperms(mask) {
kick: false, kick: false,
bypassturn: false, bypassturn: false,
rename: false, rename: false,
grabip: false grabip: false,
xss: false
}; };
if ((mask & 1) !== 0) perms.restore = true; if ((mask & 1) !== 0) perms.restore = true;
if ((mask & 2) !== 0) perms.reboot = true; if ((mask & 2) !== 0) perms.reboot = true;
@ -19,5 +20,6 @@ export function makeperms(mask) {
if ((mask & 64) !== 0) perms.bypassturn = true; if ((mask & 64) !== 0) perms.bypassturn = true;
if ((mask & 128) !== 0) perms.rename = true; if ((mask & 128) !== 0) perms.rename = true;
if ((mask & 256) !== 0) perms.grabip = true; if ((mask & 256) !== 0) perms.grabip = true;
if (config.xssImplementation === 2 && (mask & 512) !== 0) perms.xss = true;
return perms; return perms;
} }