Skip to content
Permalink
Browse files Browse the repository at this point in the history
NMS-13231: Backport Security Issues from Last Month
  • Loading branch information
christianpape committed Apr 20, 2021
1 parent b6a8557 commit eb08b5e
Show file tree
Hide file tree
Showing 31 changed files with 233 additions and 83 deletions.
Expand Up @@ -454,7 +454,7 @@ require('../services/Requisitions');
RequisitionsService.startTiming();
RequisitionsService.saveForeignSourceDefinition($scope.foreignSourceDef).then(
function() { // success
growl.success('The definition for the requisition ' + $scope.foreignSource + ' has been saved.');
growl.success('The definition for the requisition ' + _.escape($scope.foreignSource) + ' has been saved.');
form.$dirty = false;
},
$scope.errorHandler
Expand All @@ -474,7 +474,7 @@ require('../services/Requisitions');
RequisitionsService.startTiming();
RequisitionsService.deleteForeignSourceDefinition($scope.foreignSource).then(
function() { // success
growl.success('The foreign source definition for ' + $scope.foreignSource + 'has been reseted.');
growl.success('The foreign source definition for ' + _.escape($scope.foreignSource) + 'has been reseted.');
$scope.initialize();
},
$scope.errorHandler
Expand Down Expand Up @@ -517,7 +517,7 @@ require('../services/Requisitions');
* @methodOf ForeignSourceController
*/
$scope.initialize = function() {
growl.success('Retrieving definition for requisition ' + $scope.foreignSource + '...');
growl.success('Retrieving definition for requisition ' + _.escape($scope.foreignSource) + '...');
RequisitionsService.getForeignSourceDefinition($scope.foreignSource).then(
function(foreignSourceDef) { // success
$scope.foreignSourceDef = foreignSourceDef;
Expand Down
Expand Up @@ -476,7 +476,7 @@ const RequisitionMetaDataEntry = require('../model/RequisitionMetaDataEntry');
RequisitionsService.startTiming();
RequisitionsService.saveNode($scope.node).then(
function() { // success
growl.success('The node ' + $scope.node.nodeLabel + ' has been saved.');
growl.success('The node ' + _.escape($scope.node.nodeLabel) + ' has been saved.');
$scope.foreignId = $scope.node.foreignId;
form.$dirty = false;
},
Expand All @@ -492,7 +492,7 @@ const RequisitionMetaDataEntry = require('../model/RequisitionMetaDataEntry');
* @methodOf NodeController
*/
$scope.refresh = function() {
growl.success('Retrieving node ' + $scope.foreignId + ' from requisition ' + $scope.foreignSource + '...');
growl.success('Retrieving node ' + _.escape($scope.foreignId) + ' from requisition ' + _.escape($scope.foreignSource) + '...');
RequisitionsService.getNode($scope.foreignSource, $scope.foreignId).then(
function(node) { // success
$scope.node = node;
Expand Down
Expand Up @@ -111,8 +111,8 @@ const QuickNode = require('../model/QuickNode');
*/
$scope.provision = function() {
$scope.isSaving = true;
growl.info($sanitize('The node ' + $scope.node.nodeLabel + ' is being added to requisition ' + $scope.node.foreignSource + '. Please wait...'));
var successMessage = $sanitize('The node ' + $scope.node.nodeLabel + ' has been added to requisition ' + $scope.node.foreignSource);
growl.info('The node ' + _.escape($scope.node.nodeLabel) + ' is being added to requisition ' + _.escape($scope.node.foreignSource) + '. Please wait...');
var successMessage = 'The node ' + _.escape($scope.node.nodeLabel) + ' has been added to requisition ' + _.escape($scope.node.foreignSource);
RequisitionsService.quickAddNode($scope.node).then(
function() { // success
$scope.reset();
Expand Down Expand Up @@ -238,7 +238,7 @@ const QuickNode = require('../model/QuickNode');
function() { // success
RequisitionsService.synchronizeRequisition(foreignSource, false).then(
function() {
growl.success('The requisition ' + foreignSource + ' has been created and synchronized.');
growl.success('The requisition ' + _.escape(foreignSource) + ' has been created and synchronized.');
$scope.foreignSources.push(foreignSource);
},
$scope.errorHandler
Expand Down
Expand Up @@ -200,7 +200,7 @@ require('../services/Synchronize');
* @param {object} The node's object to delete
*/
$scope.deleteNode = function(node) {
bootbox.confirm('Are you sure you want to remove the node ' + node.nodeLabel + '?', function(ok) {
bootbox.confirm('Are you sure you want to remove the node ' + _.escape(node.nodeLabel) + '?', function(ok) {
if (ok) {
RequisitionsService.startTiming();
RequisitionsService.deleteNode(node).then(
Expand All @@ -214,7 +214,7 @@ require('../services/Synchronize');
if (index > -1) {
$scope.filteredNodes.splice(index,1);
}
growl.success('The node ' + node.nodeLabel + ' has been deleted.');
growl.success('The node ' + _.escape(node.nodeLabel) + ' has been deleted.');
},
$scope.errorHandler
);
Expand Down Expand Up @@ -295,7 +295,7 @@ require('../services/Synchronize');
if (value) {
$scope.pageSize = value;
}
growl.success('Retrieving requisition ' + $scope.foreignSource + '...');
growl.success('Retrieving requisition ' + _.escape($scope.foreignSource) + '...');
RequisitionsService.getRequisition($scope.foreignSource).then(
function(requisition) { // success
$scope.requisition = requisition;
Expand Down
Expand Up @@ -172,14 +172,14 @@ require('../services/Synchronize');
}
});
modalInstance.result.then(function(targetForeignSource) {
bootbox.confirm('This action will override the existing foreign source definition for the requisition named ' + targetForeignSource + ', using ' + foreignSource + ' as a template. Are you sure you want to continue ? This cannot be undone.', function(ok) {
bootbox.confirm('This action will override the existing foreign source definition for the requisition named ' + _.escape(targetForeignSource) + ', using ' + _.escape(foreignSource) + ' as a template. Are you sure you want to continue ? This cannot be undone.', function(ok) {
if (!ok) {
return;
}
RequisitionsService.startTiming();
RequisitionsService.cloneForeignSourceDefinition(foreignSource, targetForeignSource).then(
function() { // success
growl.success('The foreign source definition for ' + foreignSource + ' has been cloned to ' + targetForeignSource);
growl.success('The foreign source definition for ' + _.escape(foreignSource) + ' has been cloned to ' + _.escape(targetForeignSource));
},
$scope.errorHandler
);
Expand All @@ -201,18 +201,18 @@ require('../services/Synchronize');
if (foreignSource) {
// Validate Requisition
if (foreignSource.match(/[/\\?:&*'"]/)) {
bootbox.alert('Cannot add the requisition ' + foreignSource + ' because the following characters are invalid:<br/>:, /, \\, ?, &, *, \', "');
bootbox.alert('Cannot add the requisition ' + _.escape(foreignSource) + ' because the following characters are invalid:<br/>:, /, \\, ?, &, *, \', "');
return;
}
var r = $scope.requisitionsData.getRequisition(foreignSource);
if (r) {
bootbox.alert('Cannot add the requisition ' + foreignSource+ ' because there is already a requisition with that name');
bootbox.alert('Cannot add the requisition ' + _.escape(foreignSource) + ' because there is already a requisition with that name');
return;
}
// Create Requisition
RequisitionsService.addRequisition(foreignSource).then(
function(r) { // success
growl.success('The requisition ' + r.foreignSource + ' has been created.');
growl.success('The requisition ' + _.escape(r.foreignSource) + ' has been created.');
},
$scope.errorHandler
);
Expand Down Expand Up @@ -271,7 +271,7 @@ require('../services/Synchronize');
RequisitionsService.startTiming();
RequisitionsService.updateDeployedStatsForRequisition(requisition).then(
function() { // success
growl.success('The deployed statistics for ' + requisition.foreignSource + ' has been updated.');
growl.success('The deployed statistics for ' + _.escape(requisition.foreignSource) + ' has been updated.');
},
$scope.errorHandler
);
Expand All @@ -286,12 +286,12 @@ require('../services/Synchronize');
* @param {string} foreignSource The name of the requisition
*/
$scope.removeAllNodes = function(foreignSource) {
bootbox.confirm('Are you sure you want to remove all the nodes from ' + foreignSource + '?', function(ok) {
bootbox.confirm('Are you sure you want to remove all the nodes from ' + _.escape(foreignSource) + '?', function(ok) {
if (ok) {
RequisitionsService.startTiming();
RequisitionsService.removeAllNodesFromRequisition(foreignSource).then(
function() { // success
growl.success('All the nodes from ' + foreignSource + ' have been removed, and the requisition has been synchronized.');
growl.success('All the nodes from ' + _.escape(foreignSource) + ' have been removed, and the requisition has been synchronized.');
var req = $scope.requisitionsData.getRequisition(foreignSource);
req.reset();
},
Expand All @@ -310,12 +310,12 @@ require('../services/Synchronize');
* @param {string} foreignSource The name of the requisition
*/
$scope.delete = function(foreignSource) {
bootbox.confirm('Are you sure you want to remove the requisition ' + foreignSource + '?', function(ok) {
bootbox.confirm('Are you sure you want to remove the requisition ' + _.escape(foreignSource) + '?', function(ok) {
if (ok) {
RequisitionsService.startTiming();
RequisitionsService.deleteRequisition(foreignSource).then(
function() { // success
growl.success('The requisition ' + foreignSource + ' has been deleted.');
growl.success('The requisition ' + _.escape(foreignSource) + ' has been deleted.');
},
$scope.errorHandler
);
Expand Down
Expand Up @@ -46,7 +46,7 @@ require('./Requisitions');
RequisitionsService.startTiming();
RequisitionsService.synchronizeRequisition(requisition.foreignSource, rescanExisting).then(
function() { // success
growl.success('The import operation has been started for ' + requisition.foreignSource + ' (rescanExisting? ' + rescanExisting + ')<br/>Use <b>refresh</b> to update the deployed statistics');
growl.success('The import operation has been started for ' + _.escape(requisition.foreignSource) + ' (rescanExisting? ' + rescanExisting + ')<br/>Use <b>refresh</b> to update the deployed statistics');
requisition.setDeployed(true);
},
errorHandler
Expand All @@ -58,7 +58,7 @@ require('./Requisitions');
'Choose <b>no</b> to synchronize only the new and deleted nodes with the database executing the scan phase only for new nodes.<br/>' +
'Choose <b>dbonly</b> to synchronize all the nodes with the database skipping the scan phase.<br/>' +
'Choose <b>cancel</b> to abort the request.',
title: 'Synchronize Requisition ' + requisition.foreignSource,
title: 'Synchronize Requisition ' + _.escape(requisition.foreignSource),
buttons: {
fullSync: {
label: 'Yes',
Expand Down
Expand Up @@ -6,6 +6,7 @@
'use strict';

const angular = require('angular-js');
const _ = require('underscore-js');
require('angular-mocks');
require('../../../../../src/main/assets/js/apps/onms-requisitions/requisitions');

Expand Down
Expand Up @@ -8,6 +8,7 @@
'use strict';

const angular = require('angular-js');
const _ = require('underscore-js');
require('angular-mocks');
require('../../../../../src/main/assets/js/apps/onms-requisitions/requisitions');

Expand Down
Expand Up @@ -8,6 +8,7 @@
'use strict';

const angular = require('angular-js');
const _ = require('underscore-js');
require('angular-mocks');
require('../../../../../src/main/assets/js/apps/onms-requisitions/requisitions');

Expand Down
Expand Up @@ -8,6 +8,7 @@
'use strict';

const angular = require('angular-js');
const _ = require('underscore-js');
require('angular-mocks');
require('../../../../../src/main/assets/js/apps/onms-requisitions/requisitions');

Expand Down
Expand Up @@ -69,6 +69,11 @@ public void doPost(HttpServletRequest request, HttpServletResponse response) thr
UserManager userFactory = UserFactory.getInstance();

String userID = request.getParameter("userID");

if (userID != null && userID.matches(".*[&<>\"`']+.*")) {
throw new ServletException("User ID must not contain any HTML markup.");
}

String password = request.getParameter("pass1");

boolean hasUser = false;
Expand Down
Expand Up @@ -60,6 +60,10 @@ public void doPost(HttpServletRequest request, HttpServletResponse response) thr
String userID = request.getParameter("userID");
String newID = request.getParameter("newID");

if (newID != null && newID.matches(".*[&<>\"`']+.*")) {
throw new ServletException("User ID must not contain any HTML markup.");
}

// now save to the xml file
try {
UserManager userFactory = UserFactory.getInstance();
Expand Down
Expand Up @@ -151,7 +151,11 @@ private ModelAndView renameGroup(HttpServletRequest request, HttpServletResponse

String oldName = request.getParameter("groupName");
String newName = request.getParameter("newName");


if (newName != null && newName.matches(".*[&<>\"`']+.*")) {
throw new ServletException("Group ID must not contain any HTML markup.");
}

if (StringUtils.hasText(oldName) && StringUtils.hasText(newName)) {
m_groupRepository.renameGroup(oldName, newName);
}
Expand Down Expand Up @@ -312,6 +316,14 @@ private ModelAndView addGroup(HttpServletRequest request, HttpServletResponse re
groupComment = "";
}

if (groupName != null && groupName.matches(".*[&<>\"`']+.*")) {
throw new ServletException("Group ID must not contain any HTML markup.");
}

if (groupComment != null && groupComment.matches(".*[&<>\"`']+.*")) {
throw new ServletException("Group comment must not contain any HTML markup.");
}

boolean hasGroup = false;
try {
hasGroup = m_groupRepository.groupExists(groupName);
Expand Down
Expand Up @@ -36,6 +36,7 @@
%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<%@ taglib uri="https://www.owasp.org/index.php/OWASP_Java_Encoder_Project" prefix="e"%>

<jsp:include page="/includes/bootstrap.jsp" flush="false" >
<jsp:param name="title" value="Event Notifications" />
Expand Down Expand Up @@ -109,31 +110,31 @@
<c:forEach items="${notifications}" var="notification">
<tr>
<td>
<input type="button" class="btn btn-secondary" value="Edit" onclick="javascript:editNotice('${notification.escapedName}')"/>
<input type="button" class="btn btn-secondary" value="Edit" onclick="javascript:editNotice('${e:forJavaScript(notification.escapedName)}')"/>
</td>
<td>
<input type="button" class="btn btn-secondary" value="Delete" onclick="javascript:deleteNotice('${notification.escapedName}')"/>
<input type="button" class="btn btn-secondary" value="Delete" onclick="javascript:deleteNotice('${e:forJavaScript(notification.escapedName)}')"/>
</td>
<td>
<c:choose>
<c:when test="${notification.isOn}">
<input type="radio" value="Off" onclick="javascript:setStatus('${notification.escapedName}','off')"/>Off
<input type="radio" value="On" CHECKED onclick="javascript:setStatus('${notification.escapedName}','on')"/>On
<input type="radio" value="Off" onclick="javascript:setStatus('${e:forJavaScript(notification.escapedName)}','off')"/>Off
<input type="radio" value="On" CHECKED onclick="javascript:setStatus('${e:forJavaScript(notification.escapedName)}','on')"/>On
</c:when>
<c:otherwise>
<input type="radio" value="Off" CHECKED onclick="javascript:setStatus('${notification.escapedName}','off')"/>Off
<input type="radio" value="On" onclick="javascript:setStatus('${notification.escapedName}','on')"/>On
<input type="radio" value="Off" CHECKED onclick="javascript:setStatus('${e:forJavaScript(notification.escapedName)}','off')"/>Off
<input type="radio" value="On" onclick="javascript:setStatus('${e:forJavaScript(notification.escapedName)}','on')"/>On
</c:otherwise>
</c:choose>
</td>
<td>
${notification.name}
${fn:escapeXml(notification.name)}
</td>
<td>
${notification.eventLabel}
${fn:escapeXml(notification.eventLabel)}
</td>
<td>
${notification.displayUei}
${fn:escapeXml(notification.displayUei)}
</td>
</tr>
</c:forEach>
Expand Down
Expand Up @@ -40,6 +40,7 @@
%>

<%@page import="org.opennms.web.group.WebGroup"%>
<%@ page import="org.opennms.core.utils.WebSecurityUtils" %>

<%
WebGroup group = (WebGroup)request.getAttribute("group");
Expand All @@ -60,13 +61,13 @@
<div class="col-md-6">
<div class="card">
<div class="card-header">
<span>Details for Group: <%=group.getName()%></span>
<span>Details for Group: <%=WebSecurityUtils.sanitizeString(group.getName())%></span>
</div>
<table class="table table-sm">
<tr>
<th>Comments:</th>
<td width="75%">
<%=group.getComments()%>
<%=WebSecurityUtils.sanitizeString(group.getComments())%>
</td>
</tr>
<tr>
Expand All @@ -79,7 +80,7 @@
<% } else { %>
<ul class="list-unstyled">
<% for (String user : users) { %>
<li> <%=user%> </li>
<li> <%=WebSecurityUtils.sanitizeString(user)%> </li>
<% } %>
</ul>
<% } %>
Expand Down

0 comments on commit eb08b5e

Please sign in to comment.