From 7a7f0cdebe14790ebf9dd79dc8d34be96764a6e7 Mon Sep 17 00:00:00 2001 From: Jared Date: Fri, 25 Dec 2020 05:16:22 -0800 Subject: [PATCH] Do some extra sanitization on HTML output.. --- .../wwwroot/src/Main/BrowserHubConnection.ts | 11 +-- .../wwwroot/src/Main/Commands/WebCommands.ts | 80 ++++++++++++------- Server/wwwroot/src/Main/Console.ts | 43 ++++++++-- Server/wwwroot/src/Main/DataGrid.ts | 1 - Server/wwwroot/src/Main/InputEventHandlers.ts | 4 +- 5 files changed, 97 insertions(+), 42 deletions(-) diff --git a/Server/wwwroot/src/Main/BrowserHubConnection.ts b/Server/wwwroot/src/Main/BrowserHubConnection.ts index 4e93f3552..11b6a4fe1 100644 --- a/Server/wwwroot/src/Main/BrowserHubConnection.ts +++ b/Server/wwwroot/src/Main/BrowserHubConnection.ts @@ -6,7 +6,7 @@ import { CommandResult } from "../Shared/Models/CommandResult.js"; import { CreateCommandHarness, AddCommandResultsHarness, AddPSCoreResultsHarness, UpdateResultsCount } from "./ResultsParser.js"; import { UserOptions } from "../Shared/Models/UserOptions.js"; import { MainApp } from "./App.js"; -import { AddConsoleOutput, AddConsoleHTML } from "./Console.js"; +import { AddConsoleOutput, AddConsoleHTML, AddConsoleElement } from "./Console.js"; import { ReceiveChatText } from "./Chat.js"; import { ShowMessage, ShowModal } from "../Shared/UI.js"; import { EncodeForHTML } from "../Shared/Utilities.js"; @@ -55,10 +55,10 @@ export var BrowserHubConnection = new class BrowserHubConnection { hubConnection.on("Chat", (deviceID: string, deviceName: string, message: string, disconnected: boolean) => { var encodedMessage = EncodeForHTML(message); if (disconnected) { - AddConsoleHTML(`${deviceName} disconnected from chat.`); + AddConsoleHTML("span", "text-info font-italic", `${deviceName} disconnected from chat.`); } else if (message) { - AddConsoleHTML(`Chat from ${deviceName}: ${encodedMessage}`); + AddConsoleHTML("span", "text-info font-weight-bold", `Chat from ${deviceName}:`, message); } ReceiveChatText(deviceID, deviceName, encodedMessage, disconnected); @@ -106,9 +106,6 @@ export var BrowserHubConnection = new class BrowserHubConnection { ShowMessage(popupMessage); } }); - hubConnection.on("DisplayConsoleHTML", (message: string) => { - AddConsoleHTML(message); - }); hubConnection.on("DownloadFile", (fileID: string) => { location.assign(`/API/FileSharing/${fileID}`); }); @@ -169,7 +166,7 @@ export var BrowserHubConnection = new class BrowserHubConnection { xhr.send(); }); hubConnection.on("CommandResultCreated", (result: CommandResult) => { - AddConsoleHTML(CreateCommandHarness(result).outerHTML); + AddConsoleElement(CreateCommandHarness(result)); }); hubConnection.on("ServiceID", (deviceId: string, serviceConnectionId: string) => { this.DeviceIdToControlTargetLookup[deviceId].ServiceConnectionId = serviceConnectionId; diff --git a/Server/wwwroot/src/Main/Commands/WebCommands.ts b/Server/wwwroot/src/Main/Commands/WebCommands.ts index c9b5bbe0a..92ff1b138 100644 --- a/Server/wwwroot/src/Main/Commands/WebCommands.ts +++ b/Server/wwwroot/src/Main/Commands/WebCommands.ts @@ -5,7 +5,7 @@ import { BrowserHubConnection } from "../BrowserHubConnection.js"; import { CommandLineParameter } from "../../Shared/Models/CommandLineParameter.js"; import { MainApp } from "../App.js"; import * as DataGrid from "../DataGrid.js"; -import { AddConsoleHTML, AddConsoleOutput, AddTransferHarness } from "../Console.js"; +import { AddConsoleElement, AddConsoleHTML, AddConsoleLineBreak, AddConsoleOutput, AddConsoleTrustedHtml, AddTransferHarness } from "../Console.js"; import { GetSelectedDevices } from "../DataGrid.js"; import { EncodeForHTML } from "../../Shared/Utilities.js"; import { RemoteControlTarget } from "../../Shared/Models/RemoteControlTarget.js"; @@ -110,23 +110,27 @@ var commands: Array = [ AddConsoleOutput("No devices are selected."); return; }; - var output = `
Version Results:
- - - - `; + var title = document.createElement("div"); + title.innerText = "Version Results:"; + var table = document.createElement("table"); + var head = table.createTHead(); + var body = table.createTBody(); + + table.className = "console-device-table table table-responsive"; + head.innerHTML = ""; var deviceList = selectedDevices.map(x => { return ` - - + + ` }); - output += deviceList.join(""); - output += "
Device NameAgent Version
Device NameAgent Version
${x.DeviceName} - ${x.AgentVersion} - ${EncodeForHTML(x.DeviceName)}${EncodeForHTML(x.AgentVersion)}
"; - AddConsoleOutput(output); + body.innerHTML = deviceList.join(); + + + AddConsoleElement(title); + AddConsoleElement(table); + } ), new ConsoleCommand( @@ -193,12 +197,12 @@ var commands: Array = [ "", (parameters) => { if (parameters.length == 0) { - var output = `Command List:
`; + var output = `
Command List:
`; WebCommands.forEach(x => { output += `
${x.Name}
${x.Summary}
`; }) output += "
"; - AddConsoleOutput(output); + AddConsoleTrustedHtml(output); return; } var suppliedCommand = parameters.find(x => x.Name.toLowerCase() == "command") || {} as CommandLineParameter; @@ -209,14 +213,16 @@ var commands: Array = [ AddConsoleOutput("No matching commands found."); } else if (result.length == 1) { - AddConsoleHTML("
" + result[0].FullHelp); + AddConsoleLineBreak(); + AddConsoleTrustedHtml(result[0].FullHelp); } else { - var outputText = "Multiple commands found:

"; + AddConsoleOutput("Multiple commands found:"); + AddConsoleLineBreak(2); for (var i = 0; i < result.length; i++) { - outputText += result[i].Name + "
"; + AddConsoleOutput(result[i].Name); + AddConsoleLineBreak(); } - AddConsoleHTML(outputText); } } ), @@ -233,11 +239,28 @@ var commands: Array = [ AddConsoleOutput("No devices are selected."); return; } - var output = `
Selected Devices:
- - - - `; + + var title = document.createElement("div"); + title.innerText = "Selected Devices:"; + + var table = document.createElement("table"); + table.className = "console-device-table table table-responsive"; + + var head = table.createTHead(); + head.innerHTML = ` + + + + + + + + + + + + + ` var deviceList = selectedDevices.map(x => { return ` @@ -257,9 +280,12 @@ var commands: Array = [ ` }); - output += deviceList.join(""); - output += "
OnlineDevice NameAliasCurrent UserLast OnlinePlatformOS DescriptionFree StorageTotal Storage (GB)Free MemoryTotal Memory (GB)Tags
OnlineDevice NameAliasCurrent UserLast OnlinePlatformOS DescriptionFree StorageTotal Storage(GB)Free MemoryTotal Memory(GB)Tags
${EncodeForHTML(x.Tags || "")}
"; - AddConsoleOutput(output); + + var body = table.createTBody(); + body.innerHTML = deviceList.join(); + + AddConsoleElement(title); + AddConsoleElement(table); } ), new ConsoleCommand("Reinstall", diff --git a/Server/wwwroot/src/Main/Console.ts b/Server/wwwroot/src/Main/Console.ts index e90e00259..5597abfeb 100644 --- a/Server/wwwroot/src/Main/Console.ts +++ b/Server/wwwroot/src/Main/Console.ts @@ -1,5 +1,6 @@ import { UserSettings } from "./UserSettings.js"; import { ConsoleOutputDiv, ConsoleFrame, ConsoleTab, ConsoleAlert, ConsoleTextArea } from "./UI.js"; +import { EncodeForHTML } from "../Shared/Utilities.js"; export function AddConsoleOutput(strOutputMessage: string) { var outputBlock = document.createElement("div"); @@ -7,11 +8,11 @@ export function AddConsoleOutput(strOutputMessage: string) { var prompt = document.createElement("div"); prompt.classList.add("console-prompt"); - prompt.innerHTML = UserSettings.PromptString; + prompt.innerText = UserSettings.PromptString; var output = document.createElement("div"); output.classList.add("console-output"); - output.innerHTML = strOutputMessage; + output.innerText = strOutputMessage; outputBlock.appendChild(prompt); outputBlock.appendChild(output); @@ -22,15 +23,47 @@ export function AddConsoleOutput(strOutputMessage: string) { IncrementMissedMessageCount(); } -export function AddConsoleHTML(html: string) { + +export function AddConsoleHTML(elementTag: string, className: string, content: string, extraContent: string = null) { + var innerEle = document.createElement(elementTag); + innerEle.className = className; + innerEle.innerText = content; + + var contentWrapper = document.createElement("div"); + contentWrapper.appendChild(innerEle); + + if (extraContent) { + var extra = document.createElement("span"); + extra.innerText = extraContent; + contentWrapper.appendChild(extra); + } + + ConsoleOutputDiv.appendChild(contentWrapper); + + ConsoleFrame.scrollTop = ConsoleFrame.scrollHeight; + + IncrementMissedMessageCount(); +} + +export function AddConsoleTrustedHtml(trustedHtml: string) { var contentWrapper = document.createElement("div"); - contentWrapper.innerHTML = html; + contentWrapper.innerHTML = trustedHtml; ConsoleOutputDiv.appendChild(contentWrapper); ConsoleFrame.scrollTop = ConsoleFrame.scrollHeight; IncrementMissedMessageCount(); } +export function AddConsoleLineBreak(count: number = 1) { + for (var i = 0; i < count; i++) { + ConsoleOutputDiv.appendChild(document.createElement("br")); + } +} +export function AddConsoleElement(element: HTMLElement) { + ConsoleOutputDiv.appendChild(element); + ConsoleFrame.scrollTop = ConsoleFrame.scrollHeight; + IncrementMissedMessageCount(); +} export function AddTransferHarness(transferID: string, totalDevices: number) { var transferHarness = document.createElement("div"); transferHarness.id = transferID; @@ -41,7 +74,7 @@ export function AddTransferHarness(transferID: string, totalDevices: number) { Total Devices: ${totalDevices} | Completed: 0
`; - AddConsoleHTML(transferHarness.outerHTML); + AddConsoleElement(transferHarness); } export function AutoSizeTextArea() { ConsoleTextArea.style.height = "1px"; diff --git a/Server/wwwroot/src/Main/DataGrid.ts b/Server/wwwroot/src/Main/DataGrid.ts index a67f2e720..7210a3718 100644 --- a/Server/wwwroot/src/Main/DataGrid.ts +++ b/Server/wwwroot/src/Main/DataGrid.ts @@ -5,7 +5,6 @@ import { BrowserHubConnection } from "./BrowserHubConnection.js" import { ShowModal } from "../Shared/UI.js"; import { Device } from "../Shared/Models/Device.js"; import { EncodeForHTML } from "../Shared/Utilities.js"; -import { RemoteControlTarget } from "../Shared/Models/RemoteControlTarget.js"; export const DataSource: Array = new Array(); export const FilteredDevices: Array = new Array(); diff --git a/Server/wwwroot/src/Main/InputEventHandlers.ts b/Server/wwwroot/src/Main/InputEventHandlers.ts index f577a06cd..f87690099 100644 --- a/Server/wwwroot/src/Main/InputEventHandlers.ts +++ b/Server/wwwroot/src/Main/InputEventHandlers.ts @@ -3,7 +3,7 @@ import * as UI from "./UI.js"; import * as CommandProcessor from "./CommandProcessor.js"; import * as DataGrid from "./DataGrid.js"; import { BrowserHubConnection } from "./BrowserHubConnection.js"; -import { AddConsoleOutput } from "./Console.js"; +import { AddConsoleHTML, AddConsoleOutput } from "./Console.js"; import { ShowModal, ShowMessage } from "../Shared/UI.js"; @@ -201,7 +201,7 @@ function keyDownOnInputTextArea() { } UI.CommandCompletionDiv.classList.add("hidden"); UI.CommandInfoDiv.classList.add("hidden"); - AddConsoleOutput(`${UI.ConsoleTextArea.value}`); + AddConsoleHTML("span", "echo-input", UI.ConsoleTextArea.value); if (!BrowserHubConnection.Connected) { AddConsoleOutput("Not connected. Reconnecting..."); BrowserHubConnection.Connect();