diff --git a/agents/meshcore.js b/agents/meshcore.js index fcf246df..f9d8dfd7 100644 --- a/agents/meshcore.js +++ b/agents/meshcore.js @@ -3067,7 +3067,7 @@ function createMeshCore(agent) { if (args['_'].length < 1) { response = 'Proper usage: eval "JavaScript code"'; // Display correct command usage } else { - response = JSON.stringify(mesh.eval(args['_'][0])); + response = JSON.stringify(mesh.eval(args['_'][0])); // This can only be run by trusted administrator. } break; } diff --git a/agents/modules_meshcore/amt-manage.js b/agents/modules_meshcore/amt-manage.js index e64eccfe..c8ed799a 100644 --- a/agents/modules_meshcore/amt-manage.js +++ b/agents/modules_meshcore/amt-manage.js @@ -560,14 +560,15 @@ function AmtManager(agent, db, isdebug) { // Activate Intel AMT to CCM // - function makePass(length) { - var text = "", possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - for (var i = 0; i < length; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); } + obj.makePass = function(length) { + var buf = Buffer.alloc(length), text = "", possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + buf.randomFill(); // Fills buffer with secure random from OpenSSL. + for (var i = 0; i < length; i++) { text += possible.charAt(buf[i] % possible.length); } return text; } obj.activeToCCM = function (adminpass) { - if ((adminpass == null) || (adminpass == '')) { adminpass = 'P@0s' + makePass(23); } + if ((adminpass == null) || (adminpass == '')) { adminpass = 'P@0s' + obj.makePass(23); } intelAmtAdminPass = adminpass; if (osamtstack != null) { osamtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], activeToCCMEx2, adminpass); diff --git a/amt/amt-wsman-comm.js b/amt/amt-wsman-comm.js index 8e1c3042..7d1bb155 100644 --- a/amt/amt-wsman-comm.js +++ b/amt/amt-wsman-comm.js @@ -17,12 +17,6 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, parent, obj.noncecounter = 1; obj.authcounter = 0; - obj.Address = '/wsman'; - obj.challengeParams = null; - obj.noncecounter = 1; - obj.authcounter = 0; - obj.cnonce = Math.random().toString(36).substring(7); // Generate a random client nonce - obj.net = require('net'); obj.tls = require('tls'); obj.crypto = require('crypto'); @@ -32,6 +26,12 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, parent, obj.kerberosDone = 0; obj.amtVersion = null; + obj.Address = '/wsman'; + obj.challengeParams = null; + obj.noncecounter = 1; + obj.authcounter = 0; + obj.cnonce = obj.crypto.randomBytes(16).toString('hex'); // Generate a random client nonce + obj.host = host; obj.port = port; obj.user = user; diff --git a/certoperations.js b/certoperations.js index 5cac4922..6a0e920e 100644 --- a/certoperations.js +++ b/certoperations.js @@ -307,7 +307,7 @@ module.exports.CertificateOperations = function (parent) { var keys = obj.pki.rsa.generateKeyPair({ bits: (strong == true) ? 3072 : 2048, e: 0x10001 }); var cert = obj.pki.createCertificate(); cert.publicKey = keys.publicKey; - cert.serialNumber = String(Math.floor((Math.random() * 100000) + 1)); + cert.serialNumber = require('crypto').randomInt(1, 100000); cert.validity.notBefore = new Date(2018, 0, 1); cert.validity.notAfter = new Date(2049, 11, 31); if (addThumbPrintToName === true) { commonName += '-' + obj.pki.getPublicKeyFingerprint(cert.publicKey, { encoding: 'hex' }).substring(0, 6); } @@ -329,7 +329,7 @@ module.exports.CertificateOperations = function (parent) { var keys = obj.pki.rsa.generateKeyPair({ bits: (strong == true) ? 3072 : 2048, e: 0x10001 }); var cert = obj.pki.createCertificate(); cert.publicKey = keys.publicKey; - cert.serialNumber = String(Math.floor((Math.random() * 100000) + 1)); + cert.serialNumber = require('crypto').randomInt(1, 100000); cert.validity.notBefore = new Date(2018, 0, 1); cert.validity.notAfter = new Date(2049, 11, 31); if (addThumbPrintToName === true) { commonName += "-" + obj.pki.getPublicKeyFingerprint(cert.publicKey, { encoding: 'hex' }).substring(0, 6); } diff --git a/common.js b/common.js index b925c9c4..376be61a 100644 --- a/common.js +++ b/common.js @@ -96,7 +96,7 @@ module.exports.data2blob = function (data) { }; // Generate random numbers -module.exports.random = function (max) { return Math.floor(Math.random() * max); }; +module.exports.random = function (max) { require('crypto').randomInt(0, max); }; // Split a comma seperated string, ignoring commas in quotes. module.exports.quoteSplit = function (str) { @@ -187,13 +187,6 @@ module.exports.checkPasswordRequirements = function(password, requirements) { // Limits the number of tasks running to a fixed limit placing the rest in a pending queue. // This is useful to limit the number of agents upgrading at the same time, to not swamp // the network with traffic. - -// taskLimiterQueue.launch(somethingToDo, argument, priority); -// -// function somethingToDo(argument, taskid, taskLimiterQueue) { -// setTimeout(function () { taskLimiterQueue.completed(taskid); }, Math.random() * 2000); -// } - module.exports.createTaskLimiterQueue = function (maxTasks, maxTaskTime, cleaningInterval) { var obj = { maxTasks: maxTasks, maxTaskTime: (maxTaskTime * 1000), nextTaskId: 0, currentCount: 0, current: {}, pending: [[], [], []], timer: null }; diff --git a/multiserver.js b/multiserver.js index 80ad6b5a..1857ece6 100644 --- a/multiserver.js +++ b/multiserver.js @@ -172,7 +172,7 @@ module.exports.CreateMultiServer = function (parent, args) { // Get the next retry time in milliseconds function getConnectRetryTime() { - if (obj.retryBackoff < 30000) { obj.retryBackoff += Math.floor((Math.random() * 3000) + 1000); } + if (obj.retryBackoff < 30000) { obj.retryBackoff += require('crypto').randomInt(1000, 4000); } return obj.retryBackoff; } diff --git a/views/default.handlebars b/views/default.handlebars index 971ad1dd..268a312d 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -2301,27 +2301,23 @@ if (message.trustedCert == true) { // Trusted certificate, use HTTPS port. var rdpurl = window.location.origin + domainUrl + 'clickonce/minirouter/MeshMiniRouter.application?WS=wss%3A%2F%2F' + window.location.hostname + '%2Fmeshrelay.ashx%3Fauth=' + message.cookie + '&CH={{{webcerthash}}}&AP=' + message.protocol + ((debugmode == 1) ? '' : '&HOL=1'); - var newWindow = window.open(rdpurl, '_blank'); - newWindow.opener = null; + safeNewWindow(rdpurl, '_blank'); } else { // Not a trusted certificate, use HTTP port. var basicPort = ('{{{serverRedirPort}}}'.toLowerCase() == '') ? '{{{serverPublicPort}}}' : '{{{serverRedirPort}}}'; var rdpurl = 'http://' + window.location.hostname + ':' + basicPort + domainUrl + 'clickonce/minirouter/MeshMiniRouter.application?WS=wss%3A%2F%2F' + window.location.hostname + '%2Fmeshrelay.ashx%3Fauth=' + message.cookie + '&CH={{{webcerthash}}}&AP=' + message.protocol + ((debugmode == 1) ? '' : '&HOL=1'); - var newWindow = window.open(rdpurl, '_blank'); - newWindow.opener = null; + safeNewWindow(rdpurl, '_blank'); } } else if (message.tag == 'novnc') { var vncurl = window.location.origin + domainUrl + 'novnc/vnc.html?ws=wss%3A%2F%2F' + window.location.host + encodeURIComponentEx(domainUrl) + 'meshrelay.ashx%3Fauth%3D' + message.cookie + '&show_dot=1' + (urlargs.key?('&key=' + urlargs.key):'') + '&l={{{lang}}}'; var node = getNodeFromId(message.nodeid); if (node != null) { vncurl += '&name=' + encodeURIComponentEx(node.name); } - var newWindow = window.open(vncurl, 'mcnovnc/' + message.nodeid); - newWindow.opener = null; + safeNewWindow(vncurl, 'mcnovnc/' + message.nodeid); } else if (message.tag == 'mstsc') { var rdpurl = window.location.origin + domainUrl + 'mstsc.html?ws=' + message.cookie + (urlargs.key?('&key=' + urlargs.key):''); var node = getNodeFromId(message.nodeid); if (node != null) { rdpurl += '&name=' + encodeURIComponentEx(node.name); } - var newWindow = window.open(rdpurl, 'mcmstsc/' + message.nodeid); - newWindow.opener = null; + safeNewWindow(rdpurl, 'mcmstsc/' + message.nodeid); } break; } @@ -3014,7 +3010,7 @@ if (message.consent & 64) { y.push("Privacy bar"); } if (y.length == 0) { y.push("None"); } x += addHtmlValue("User Consent", y.join(', ')); - x += '
' + "Remote Desktop Link" + '
'; + x += '
' + "Remote Desktop Link" + '
'; setDialogMode(2, "Share Device", 1, null, x); break; } @@ -4133,7 +4129,7 @@ x += '
' + format("Invite someone to install the mesh agent by sharing an invitation link. This link points the user to installation instructions for the \"{0}\" device group. The link is public and no account for this server is needed.", EscapeHtml(mesh.name)) + '

'; x += addHtmlValue("Link Expiration", ''); x += addHtmlValue("Installation Type", ''); - x += '
'; + x += ''; setDialogMode(2, "Invite", 3, performAgentInvite, x, meshid); if (features & 64) { Q('d2InviteType').focus(); d2ChangedInviteType(); } else { Q('d2inviteExpire').focus(); validateAgentInvite(); } d2RequestInvitationLink(); @@ -4710,7 +4706,7 @@ var panel = [0, 10, 12, 11, 13, 16, 17, 15, 19][action]; // (invalid), General, Desktop, Terminal, Files, Events, Console, Plugin if (event && (event.shiftKey == true)) { // Open the device in a different tab - window.open(window.location.origin + '?node=' + nodeid.split('/')[2] + '&viewmode=' + panel + '&hide=16', 'meshcentral:' + nodeid); + safeNewWindow(window.location.origin + '?node=' + nodeid.split('/')[2] + '&viewmode=' + panel + '&hide=16', 'meshcentral:' + nodeid); } else { // Go to the right panel gotoDevice(nodeid, panel); @@ -4810,7 +4806,7 @@ function cmdeskplayeraction(action) { if (xxdialogMode) return; - window.open(window.location.origin + '{{{domainurl}}}player.htm', 'meshcentral-deskplayer'); + safeNewWindow(window.location.origin + '{{{domainurl}}}player.htm', 'meshcentral-deskplayer'); } function p13deletefileCm(b, file) { @@ -5471,7 +5467,7 @@ if (event && (event.shiftKey == true)) { // Open the device in a different tab - window.open(window.location.origin + '?node=' + nodeid.split('/')[2] + '&viewmode=10&hide=16', 'meshcentral:' + nodeid); + safeNewWindow(window.location.origin + '?node=' + nodeid.split('/')[2] + '&viewmode=10&hide=16', 'meshcentral:' + nodeid); return; } @@ -5972,9 +5968,9 @@ var url = '/messenger?id=meshmessenger/' + encodeURIComponentEx(currentNode._id) + '/' + encodeURIComponentEx(userinfo._id) + '&title=' + currentNode.name; if ((authCookie != null) && (authCookie != '')) { url += '&auth=' + authCookie; } if (e && (e.shiftKey == true)) { - window.open(url, 'meshmessenger:' + currentNode._id); + safeNewWindow(url, 'meshmessenger:' + currentNode._id); } else { - window.open(url, 'meshmessenger:' + currentNode._id, 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,width=400,height=560'); + safeNewWindow(url, 'meshmessenger:' + currentNode._id, 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,width=400,height=560'); } meshserver.send({ action: 'meshmessenger', nodeid: decodeURIComponent(currentNode._id) }); } @@ -6386,7 +6382,7 @@ var node = getNodeFromId(nodeid); if (node == null) return; if ([1, 2, 3, 4, 21, 22].indexOf(node.agent.id) >= 0) { url += '&os=win'; } else { url += '&os=linux'; } - window.open(url, 'xterm:' + nodeid); + safeNewWindow(url, 'xterm:' + nodeid); return false; } @@ -10060,7 +10056,7 @@ if (meshrights & 1) { // We can edit the mesh invite codes var x = "When enabled, invitation codes can be used by anyone to join devices to this device group using the following public link:" + '

'; - x += '
' + url + '

'; + x += '
' + url + '

'; x += '
'; x += addHtmlValue("Invite Codes", ''); x += addHtmlValue("Installation Type", ''); @@ -10074,7 +10070,7 @@ } else { // View codes only var x = "Invitation codes can be used by anyone to join devices to this device group using the following public link:" + '

'; - x += '
' + url + '

'; + x += '
' + url + '

'; x += addHtmlValue("Invite Codes", currentMesh.invite.codes.join(', ')); x += addHtmlValue("Installation Type", ["Background and interactive", "Background only", "Interactive only"][currentMesh.invite.flags & 3]); setDialogMode(2, "Invite Codes", 1, null, x); @@ -11057,7 +11053,7 @@ haltEvent(e); var url = '/messenger?id=meshmessenger/' + userid + '/' + encodeURIComponentEx(userinfo._id) + '&title=' + name; if ((authCookie != null) && (authCookie != '')) { url += '&auth=' + authCookie; } - window.open(url, 'meshmessenger:' + userid); + safeNewWindow(url, 'meshmessenger:' + userid); meshserver.send({ action: 'meshmessenger', userid: decodeURIComponent(userid) }); return false; } @@ -12408,7 +12404,7 @@ } function refreshRecodings() { meshserver.send({ action: 'recordings', limit: 1000 }); } - function openRecodringPlayer() { if (!xxdialogMode) window.open(window.location.origin + '{{{domainurl}}}player.htm', 'meshcentral-deskplayer'); } + function openRecodringPlayer() { if (!xxdialogMode) safeNewWindow(window.location.origin + '{{{domainurl}}}player.htm', 'meshcentral-deskplayer'); } function p52updateInfo() { var elements = document.getElementsByClassName('RecordingCheckbox'), checkcount = 0; for (var i=0;i= 10) && (x <= 19)) { - if (currentNode) { window.open(window.location.origin + '{{{domainurl}}}' + '?gotonode=' + currentNode._id.split('/')[2] + '&viewmode=' + x + '&hide=16', 'meshcentral:' + currentNode._id); } + if (currentNode) { safeNewWindow(window.location.origin + '{{{domainurl}}}' + '?gotonode=' + currentNode._id.split('/')[2] + '&viewmode=' + x + '&hide=16', 'meshcentral:' + currentNode._id); } } else if ((x >= 20) && (x <= 29)) { - if (currentMesh) { window.open(window.location.origin + '{{{domainurl}}}' + '?gotomesh=' + currentMesh._id.split('/')[2] + '&viewmode=' + x + '&hide=16', 'meshcentral:' + currentMesh._id); } + if (currentMesh) { safeNewWindow(window.location.origin + '{{{domainurl}}}' + '?gotomesh=' + currentMesh._id.split('/')[2] + '&viewmode=' + x + '&hide=16', 'meshcentral:' + currentMesh._id); } } else if ((x >= 30) && (x <= 39)) { - if (currentUser) { window.open(window.location.origin + '{{{domainurl}}}' + '?gotouser=' + ((serverinfo.crossDomain)?currentUser._id:currentUser._id.split('/')[2]) + '&viewmode=' + x + '&hide=16', 'meshcentral:' + currentUser._id); } + if (currentUser) { safeNewWindow(window.location.origin + '{{{domainurl}}}' + '?gotouser=' + ((serverinfo.crossDomain)?currentUser._id:currentUser._id.split('/')[2]) + '&viewmode=' + x + '&hide=16', 'meshcentral:' + currentUser._id); } } else if ((x >= 50) && (x <= 59)) { - if (currentUserGroup) { window.open(window.location.origin + '{{{domainurl}}}' + '?gotougrp=' + ((serverinfo.crossDomain)?currentUserGroup._id:currentUserGroup._id.split('/')[2]) + '&viewmode=' + x + '&hide=16', 'meshcentral:' + currentUserGroup._id); } + if (currentUserGroup) { safeNewWindow(window.location.origin + '{{{domainurl}}}' + '?gotougrp=' + ((serverinfo.crossDomain)?currentUserGroup._id:currentUserGroup._id.split('/')[2]) + '&viewmode=' + x + '&hide=16', 'meshcentral:' + currentUserGroup._id); } } else { // if (x < 10)) - window.open(window.location.origin + '{{{domainurl}}}' + '?viewmode=' + x + '&hide=0', 'meshcentral:' + x); + safeNewWindow(window.location.origin + '{{{domainurl}}}' + '?viewmode=' + x + '&hide=0', 'meshcentral:' + x); } return; } @@ -13542,6 +13538,8 @@ function encodeURIComponentEx(txt) { return encodeURIComponent(txt).replace(/'/g,'%27'); }; function getUserName(userid) { if (users && users[userid] != null) return users[userid].name; return userid.split('/')[2]; } function round(value, precision) { var multiplier = Math.pow(10, precision || 0); return Math.round(value * multiplier) / multiplier; } + function safeNewWindow(url, target) { var newWindow = window.open(url, target, 'noopener,noreferrer'); if (newWindow) { newWindow.opener = null; } } +