From 69062c0ec148ccadaced3ef1d6eff63ba422c055 Mon Sep 17 00:00:00 2001 From: st782s Date: Wed, 3 Jan 2018 14:30:16 -0500 Subject: Harden code Issue-ID: PORTAL-145,PORTAL-119,PORTAL-118 Harden code to address SQL injecton, XSS vulnerabilities; Separate docker images for portal, sdk app and DMaaPBC ui; Missing error page Change-Id: I1818fbf86c601dd41b274729038e731fb2ec8f7d Signed-off-by: st782s --- .../portalsdk/analytics/model/SearchHandler.java | 2 +- ecomp-sdk/epsdk-app-common/README.md | 4 +- .../controller/core/FnMenuController.java | 13 +-- .../controller/core/ProfileController.java | 6 +- .../portalapp/controller/core/RoleController.java | 8 +- .../controller/core/RoleListController.java | 4 +- .../controller/core/SingleSignOnController.java | 18 +++- .../controller/sample/BroadcastController.java | 11 +- .../controller/sample/BroadcastListController.java | 4 +- .../onap/portalapp/util/SecurityXssValidator.java | 34 +++--- ecomp-sdk/epsdk-app-os/README.md | 8 +- .../db-scripts/EcompSdkDMLMySql_2_1_OS.sql | 12 +++ .../onap/portalapp/filter/SecurityXssFilter.java | 120 ++++++++++++++------- .../src/main/webapp/WEB-INF/conf/system.properties | 4 +- .../epsdk-app-os/src/main/webapp/WEB-INF/web.xml | 23 ++-- .../src/main/resources/ESAPI.properties | 2 +- .../src/main/webapp/WEB-INF/jsp/error.jsp | 38 ++++++- .../ds2-admin/modals/role-function-add.html | 17 ++- .../DS2-view-models/ds2-admin/role_list.html | 2 +- .../src/main/webapp/app/fusion/styles/ecomp.css | 11 ++ ecomp-sdk/epsdk-core/README.md | 3 +- .../interceptor/SessionTimeoutInterceptor.java | 19 +++- .../core/logging/format/AlarmSeverityEnum.java | 16 ++- .../onap/portalsdk/core/service/UrlAccessImpl.java | 82 ++++++++++++-- .../onap/portalsdk/core/util/SystemProperties.java | 2 + .../workflow/controllers/WorkflowController.java | 2 +- 26 files changed, 350 insertions(+), 115 deletions(-) diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/onap/portalsdk/analytics/model/SearchHandler.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/onap/portalsdk/analytics/model/SearchHandler.java index a6043ea7..863f510c 100644 --- a/ecomp-sdk/epsdk-analytics/src/main/java/org/onap/portalsdk/analytics/model/SearchHandler.java +++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/onap/portalsdk/analytics/model/SearchHandler.java @@ -295,7 +295,7 @@ public class SearchHandler extends org.onap.portalsdk.analytics.RaptorObject { } else { rep_name_sql = " AND UPPER(cr.title) LIKE UPPER('%%') "; } - sql = sql.replace("[fReportName]", ESAPI.encoder().encodeForSQL( SecurityCodecUtil.getCodec(),rep_name_sql)); + sql = sql.replace("[fReportName]",rep_name_sql); if (menuId.length() > 0){ /*sql += "AND INSTR('|'||cr.menu_id||'|', '|'||'" + menuId + "'||'|') > 0 " diff --git a/ecomp-sdk/epsdk-app-common/README.md b/ecomp-sdk/epsdk-app-common/README.md index fa3e7bc4..e72d9420 100644 --- a/ecomp-sdk/epsdk-app-common/README.md +++ b/ecomp-sdk/epsdk-app-common/README.md @@ -29,9 +29,9 @@ Version 1.4.0 - PORTAL-42 Use OParent as parent POM - PORTAL-72 Address Sonar Scan code issues - PORTAL-90 Use approved ONAP license text -- Portal-86 Remove application specific usages from tests and other files +- PORTAL-86 Remove application specific usages from tests and other files - PORTAL-78 Fix SingleSignon by force session creation prior to redirection to portal - +- PORTAL-118 Missing Error page in Portal-SDK app when there is an exception happen in the backend. Version 1.3.0, 28 August 2017 - Portal-19 Renaming the Group Id in the POM file to org.onap.portal.sdk diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/FnMenuController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/FnMenuController.java index dfc735b1..c441417b 100644 --- a/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/FnMenuController.java +++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/FnMenuController.java @@ -76,7 +76,7 @@ public class FnMenuController extends RestrictedBaseController { @Autowired FnMenuService service; - + @Autowired FunctionalMenuListService functionalMenuListService; @@ -91,7 +91,7 @@ public class FnMenuController extends RestrictedBaseController { logger.error(EELFLoggerDelegate.errorLogger, "getParentListFailed", e); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); - out.write(e.getMessage()); + out.write("An error occurred in the getParentList () "); } } @@ -104,7 +104,7 @@ public class FnMenuController extends RestrictedBaseController { logger.error(EELFLoggerDelegate.errorLogger, "getFunctionCDList", e); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); - out.write(e.getMessage()); + out.write("An error occurred in the getFunctionCDList ()"); } } @@ -160,7 +160,6 @@ public class FnMenuController extends RestrictedBaseController { mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); JsonNode root = mapper.readTree(request.getReader()); Menu fnMenuItem = mapper.readValue(root.get("availableFnMenuItem").toString(), Menu.class); - service.saveFnMenu(fnMenuItem); request.getSession() .removeAttribute(SystemProperties.getProperty(SystemProperties.APPLICATION_MENU_ATTRIBUTE_NAME)); @@ -183,7 +182,7 @@ public class FnMenuController extends RestrictedBaseController { response.setCharacterEncoding("UTF-8"); request.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); - out.write(e.getMessage()); + out.write("An error occurred in the updateFnMenu () "); } return null; @@ -198,9 +197,7 @@ public class FnMenuController extends RestrictedBaseController { JsonNode root = mapper.readTree(request.getReader()); Menu fnMenuItem = mapper.readValue(root.get("fnMenuItem").toString(), Menu.class); Menu fnMenuItemRow = service.getMenuItemRow(fnMenuItem.getId()); - service.removeMenuItem(fnMenuItemRow); - response.setCharacterEncoding("UTF-8"); response.setContentType("application / json"); request.setCharacterEncoding("UTF-8"); @@ -215,7 +212,7 @@ public class FnMenuController extends RestrictedBaseController { response.setCharacterEncoding("UTF-8"); request.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); - out.write(e.getMessage()); + out.write("An error occurred in the removeFnMenu ()"); } return null; diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/ProfileController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/ProfileController.java index c83e926e..b63d24aa 100644 --- a/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/ProfileController.java +++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/ProfileController.java @@ -229,7 +229,7 @@ public class ProfileController extends RestrictedBaseController { response.setCharacterEncoding("UTF-8"); try { PrintWriter out = response.getWriter(); - out.write(e.getMessage()); + out.write("An error occurred in the saveProfile ()"); } catch (IOException e1) { logger.error(EELFLoggerDelegate.errorLogger, "saveProfile: failed to write", e1); } @@ -279,7 +279,7 @@ public class ProfileController extends RestrictedBaseController { logger.error(EELFLoggerDelegate.errorLogger, "removeRole failed", e); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); - out.write(e.getMessage()); + out.write("An error occurred in the removeRole ()"); return null; } } @@ -322,7 +322,7 @@ public class ProfileController extends RestrictedBaseController { response.setCharacterEncoding("UTF-8"); request.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); - out.write(e.getMessage()); + out.write("An error occurred in the addNewRole ()"); return null; } diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/RoleController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/RoleController.java index 69a25e66..bd1a6ab0 100644 --- a/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/RoleController.java +++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/RoleController.java @@ -232,7 +232,7 @@ public class RoleController extends RestrictedBaseController { logger.error(EELFLoggerDelegate.errorLogger, "removeRole failed", e); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); - out.write(e.getMessage()); + out.write("An error occurred removeRole failed in the removeRoleFunction"); return null; } @@ -269,7 +269,7 @@ public class RoleController extends RestrictedBaseController { logger.error(EELFLoggerDelegate.errorLogger, "removeRoleFunction failed", e); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); - out.write(e.getMessage()); + out.write("An error occurred removeRoleFunction failed in the removeRoleFunction"); return null; } @@ -305,7 +305,7 @@ public class RoleController extends RestrictedBaseController { logger.error(EELFLoggerDelegate.errorLogger, "removeChildRole failed", e); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); - out.write(e.getMessage()); + out.write("An error occurred removeChildRole failed in the removeChildRole()"); return null; } @@ -342,7 +342,7 @@ public class RoleController extends RestrictedBaseController { logger.error(EELFLoggerDelegate.errorLogger, "addChildRole failed", e); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); - out.write(e.getMessage()); + out.write("An error occurred addChildRole failed in the addChildRole()"); return null; } diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/RoleListController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/RoleListController.java index b89cb43c..c7804e5f 100644 --- a/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/RoleListController.java +++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/RoleListController.java @@ -141,7 +141,7 @@ public class RoleListController extends RestrictedBaseController { logger.error(EELFLoggerDelegate.errorLogger, "toggleRole failed", e); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); - out.write(e.getMessage()); + out.write("An error occurred while saving Role in the toggleRole()"); return null; } @@ -180,7 +180,7 @@ public class RoleListController extends RestrictedBaseController { response.setCharacterEncoding("UTF-8"); request.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); - out.write(e.getMessage()); + out.write("An error occurred while removing Role in the toggleRole()"); return null; } diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/SingleSignOnController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/SingleSignOnController.java index fb2e3b80..982a60b8 100644 --- a/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/SingleSignOnController.java +++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/core/SingleSignOnController.java @@ -37,6 +37,8 @@ */ package org.onap.portalapp.controller.core; +import java.net.MalformedURLException; +import java.net.URL; import java.net.URLDecoder; import java.net.URLEncoder; import java.util.HashMap; @@ -47,6 +49,7 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; +import org.apache.commons.lang.StringUtils; import org.onap.portalsdk.core.auth.LoginStrategy; import org.onap.portalsdk.core.command.LoginBean; import org.onap.portalsdk.core.controller.UnRestrictedBaseController; @@ -159,6 +162,7 @@ public class SingleSignOnController extends UnRestrictedBaseController { // both user and session are non-null. logger.info(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: redirecting to the forwardURL {}", forwardURL); + validateDomain(forwardURL); return new ModelAndView("redirect:" + forwardURL); } @@ -180,6 +184,7 @@ public class SingleSignOnController extends UnRestrictedBaseController { // application can publish a base URL in system.properties String appUrl = SystemProperties.getProperty(SystemProperties.APP_BASE_URL); returnToAppUrl = appUrl + (appUrl.endsWith("/") ? "" : "/") + forwardURL; + validateDomain(returnToAppUrl); logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: using app base URL {} and redirectURL {}", appUrl, returnToAppUrl); } else { @@ -190,6 +195,7 @@ public class SingleSignOnController extends UnRestrictedBaseController { // should always find the specified token. returnToAppUrl = request.getRequestURL().toString().replace("single_signon.htm", forwardURL); + validateDomain(returnToAppUrl); logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: computed redirectURL {}", returnToAppUrl); } @@ -202,7 +208,6 @@ public class SingleSignOnController extends UnRestrictedBaseController { final String redirectUrl = portalUrl + "?uebAppKey=" + uebAppKey + "&redirectUrl=" + encodedReturnToAppUrl; logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: portal-bound redirect URL is {}", redirectUrl); - // this line may not be necessary but jsessionid coockie is not getting created in all cases; // so force the cookie creation request.getSession(true); @@ -211,6 +216,17 @@ public class SingleSignOnController extends UnRestrictedBaseController { } } + private void validateDomain(String forwardURL) throws MalformedURLException { + if (StringUtils.isNotBlank(forwardURL)) { + String hostName = new URL(forwardURL).getHost(); + if (StringUtils.isNotBlank(hostName) && !hostName.endsWith(SystemProperties.getProperty(SystemProperties.COOKIE_DOMAIN))) { + logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: accessing Unauthorized url", + hostName); + throw new SecurityException("accessing Unauthorized url : " + hostName); + } + } + } + protected void initateSessionMgtHandler(HttpServletRequest request) { String portalJSessionId = getPortalJSessionId(request); String jSessionId = getJessionId(request); diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/sample/BroadcastController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/sample/BroadcastController.java index 316f35cd..c4f0d430 100644 --- a/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/sample/BroadcastController.java +++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/sample/BroadcastController.java @@ -45,8 +45,10 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.json.JSONObject; +import org.onap.portalapp.util.SecurityXssValidator; import org.onap.portalsdk.core.controller.RestrictedBaseController; import org.onap.portalsdk.core.domain.BroadcastMessage; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.portalsdk.core.service.BroadcastService; import org.onap.portalsdk.core.util.SystemProperties; import org.onap.portalsdk.core.web.support.AppUtils; @@ -65,6 +67,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; @RequestMapping("/") public class BroadcastController extends RestrictedBaseController { + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(BroadcastController.class); + @Autowired private BroadcastService broadcastService; @@ -77,7 +81,7 @@ public class BroadcastController extends RestrictedBaseController { model.put("broadcastMessage", mapper.writeValueAsString(broadcastService.getBroadcastMessage(request))); model.put("broadcastSites", mapper.writeValueAsString(referenceData(request).get("broadcastSites"))); } catch (Exception e) { - e.printStackTrace(); + logger.error(EELFLoggerDelegate.errorLogger, "broadcast() failed", e); } return new ModelAndView(getViewName(), model); } @@ -96,7 +100,7 @@ public class BroadcastController extends RestrictedBaseController { response.getWriter().write(j.toString()); } catch (Exception e) { - e.printStackTrace(); + logger.error(EELFLoggerDelegate.errorLogger, "getBroadcast() failed", e); } } @@ -141,7 +145,8 @@ public class BroadcastController extends RestrictedBaseController { response.setCharacterEncoding("UTF-8"); request.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); - out.write(e.getMessage()); + out.write("An error occurred while saving the BroadcastMessage in the save () mapping-/broadcast/save "); + logger.error(EELFLoggerDelegate.errorLogger, "save() failed", e); return null; } diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/sample/BroadcastListController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/sample/BroadcastListController.java index aeeaca56..2a9af812 100644 --- a/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/sample/BroadcastListController.java +++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/controller/sample/BroadcastListController.java @@ -121,7 +121,7 @@ public class BroadcastListController extends RestrictedBaseController { response.setCharacterEncoding("UTF-8"); request.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); - out.write(e.getMessage()); + out.write("An error occurred while removing the BroadcastMessage in the remove ()"); logger.error(EELFLoggerDelegate.errorLogger, "remove() failed", e); return null; } @@ -156,7 +156,7 @@ public class BroadcastListController extends RestrictedBaseController { response.setCharacterEncoding("UTF-8"); request.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); - out.write(e.getMessage()); + out.write("An error occurred while saving the BroadcastMessage in the toggleActive () "); logger.error(EELFLoggerDelegate.errorLogger, "toggleActive() failed", e); return null; } diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/util/SecurityXssValidator.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/util/SecurityXssValidator.java index b51cb8db..97545508 100644 --- a/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/util/SecurityXssValidator.java +++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/onap/portalapp/util/SecurityXssValidator.java @@ -60,6 +60,7 @@ public class SecurityXssValidator { private static final String MYSQL_DB = "mysql"; private static final String ORACLE_DB = "oracle"; private static final String MARIA_DB = "mariadb"; + private static final int FLAGS = Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL; static SecurityXssValidator validator = null; private static Codec instance; @@ -82,46 +83,39 @@ public class SecurityXssValidator { private SecurityXssValidator() { // Avoid anything between script tags - XSS_INPUT_PATTERNS.add(Pattern.compile("", Pattern.CASE_INSENSITIVE)); + XSS_INPUT_PATTERNS.add(Pattern.compile("", FLAGS)); // avoid iframes - XSS_INPUT_PATTERNS.add(Pattern.compile("(.*?)", Pattern.CASE_INSENSITIVE)); + XSS_INPUT_PATTERNS.add(Pattern.compile("(.*?)", FLAGS)); // Avoid anything in a src='...' type of expression - XSS_INPUT_PATTERNS.add(Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", - Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL)); + XSS_INPUT_PATTERNS.add(Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", FLAGS)); - XSS_INPUT_PATTERNS.add(Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", - Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL)); + XSS_INPUT_PATTERNS.add(Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", FLAGS)); - XSS_INPUT_PATTERNS.add(Pattern.compile("src[\r\n]*=[\r\n]*([^>]+)", - Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL)); + XSS_INPUT_PATTERNS.add(Pattern.compile("src[\r\n]*=[\r\n]*([^>]+)", FLAGS)); // Remove any lonesome tag - XSS_INPUT_PATTERNS.add(Pattern.compile("", Pattern.CASE_INSENSITIVE)); + XSS_INPUT_PATTERNS.add(Pattern.compile("", FLAGS)); - XSS_INPUT_PATTERNS.add(Pattern.compile(".*().*", Pattern.CASE_INSENSITIVE)); + XSS_INPUT_PATTERNS.add(Pattern.compile(".*().*", FLAGS)); - XSS_INPUT_PATTERNS.add(Pattern.compile(".*().*", Pattern.CASE_INSENSITIVE)); + XSS_INPUT_PATTERNS.add(Pattern.compile(".*().*", FLAGS)); // Remove any lonesome