Add XSS implementation (supports both internal and yellows fork)
This commit is contained in:
parent
517ae3c2e8
commit
d5bd23d5db
5 changed files with 53 additions and 13 deletions
4
dist/index.html
vendored
4
dist/index.html
vendored
|
@ -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
4
dist/style.css
vendored
|
@ -78,3 +78,7 @@
|
||||||
#qemuMonitorOutput {
|
#qemuMonitorOutput {
|
||||||
height: 180px;
|
height: 180px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#xssCheckboxContainer {
|
||||||
|
display: none;
|
||||||
|
}
|
|
@ -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,
|
||||||
}
|
}
|
43
src/index.js
43
src/index.js
|
@ -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 = "";
|
chatinput.value = "";
|
||||||
}
|
}
|
||||||
});
|
|
||||||
buttons.sendChat.addEventListener('click', () => {
|
|
||||||
vm.chat(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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
Loading…
Reference in a new issue