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 --- 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 ++-- 5 files changed, 117 insertions(+), 50 deletions(-) (limited to 'ecomp-sdk/epsdk-app-os') diff --git a/ecomp-sdk/epsdk-app-os/README.md b/ecomp-sdk/epsdk-app-os/README.md index d9d7fb68..daf03237 100644 --- a/ecomp-sdk/epsdk-app-os/README.md +++ b/ecomp-sdk/epsdk-app-os/README.md @@ -19,9 +19,11 @@ Version 1.4.0, 2017 - PORTAL-72 Address Sonar Scan code issues - PORTAL-79 remove unwanted SDK left menu under Report-sample dashboard - PORTAL-90 Use approved ONAP license text -- Portal-86 Remove application specific usages from tests and other files (rework) -- Portal-104 Replaced the sql connector to maria db -- Portal-127 Remove GreenSock license code from b2b library +- PORTAL-86 Remove application specific usages from tests and other files (rework) +- PORTAL-104 Replaced the sql connector to maria db +- PORTAL-127 Remove GreenSock license code from b2b library +- PORTAL-118 Missing Error page in Portal-SDK app when there is an exception happen in the backend. + * Put new entries here * Version 1.3.0, 28 August 2017 diff --git a/ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkDMLMySql_2_1_OS.sql b/ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkDMLMySql_2_1_OS.sql index cb4a3085..91402fb0 100644 --- a/ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkDMLMySql_2_1_OS.sql +++ b/ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkDMLMySql_2_1_OS.sql @@ -36,4 +36,16 @@ Insert into fn_app (APP_ID,APP_NAME,APP_IMAGE_URL,APP_DESCRIPTION,APP_NOTES,APP_ -- fn_user_role Insert into fn_user_role (USER_ID,ROLE_ID,PRIORITY,APP_ID) values (1,1,null,1); +-- fn_restricted_url +insert into fn_restricted_url values('admin','menu_admin'); +insert into fn_restricted_url values('get_role','menu_admin'); +insert into fn_restricted_url values('get_role_functions','menu_admin'); +insert into fn_restricted_url values('role_list/*','menu_admin'); +insert into fn_restricted_url values('role_function_list/*','menu_admin'); +insert into fn_restricted_url values('addRole','menu_admin'); +insert into fn_restricted_url values('addRoleFunction','menu_admin'); +insert into fn_restricted_url values('removeRole','menu_admin'); +insert into fn_restricted_url values('removeRoleFunction','menu_admin'); +insert into fn_restricted_url values('profile/*','menu_admin'); + commit; diff --git a/ecomp-sdk/epsdk-app-os/src/main/java/org/onap/portalapp/filter/SecurityXssFilter.java b/ecomp-sdk/epsdk-app-os/src/main/java/org/onap/portalapp/filter/SecurityXssFilter.java index 71ab7359..aad01286 100644 --- a/ecomp-sdk/epsdk-app-os/src/main/java/org/onap/portalapp/filter/SecurityXssFilter.java +++ b/ecomp-sdk/epsdk-app-os/src/main/java/org/onap/portalapp/filter/SecurityXssFilter.java @@ -38,71 +38,119 @@ */ package org.onap.portalapp.filter; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import javax.servlet.FilterChain; +import javax.servlet.ReadListener; import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; +import org.apache.http.HttpStatus; import org.onap.portalapp.util.SecurityXssValidator; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.springframework.web.filter.OncePerRequestFilter; -import org.springframework.web.util.ContentCachingRequestWrapper; -import org.springframework.web.util.ContentCachingResponseWrapper; -import org.springframework.web.util.WebUtils; public class SecurityXssFilter extends OncePerRequestFilter { - private static final String BAD_REQUEST = "BAD_REQUEST"; + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SecurityXssFilter.class); + + private static final String APPLICATION_JSON = "application/json"; + + private static final String ERROR_BAD_REQUEST = "{\"error\":\"BAD_REQUEST\"}"; private SecurityXssValidator validator = SecurityXssValidator.getInstance(); - private static String getRequestData(final HttpServletRequest request) throws UnsupportedEncodingException { - String payload = null; - ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class); - if (wrapper != null) { - byte[] buf = wrapper.getContentAsByteArray(); - if (buf.length > 0) { - payload = new String(buf, 0, buf.length, wrapper.getCharacterEncoding()); - } + public class RequestWrapper extends HttpServletRequestWrapper { + + private ByteArrayOutputStream cachedBytes; + + public RequestWrapper(HttpServletRequest request) { + super(request); } - return payload; - } - private static String getResponseData(final HttpServletResponse response) throws IOException { - String payload = null; - ContentCachingResponseWrapper wrapper = WebUtils.getNativeResponse(response, - ContentCachingResponseWrapper.class); - if (wrapper != null) { - byte[] buf = wrapper.getContentAsByteArray(); - if (buf.length > 0) { - payload = new String(buf, 0, buf.length, wrapper.getCharacterEncoding()); - wrapper.copyBodyToResponse(); + @Override + public ServletInputStream getInputStream() throws IOException { + if (cachedBytes == null) + cacheInputStream(); + + return new CachedServletInputStream(); + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + private void cacheInputStream() throws IOException { + cachedBytes = new ByteArrayOutputStream(); + IOUtils.copy(super.getInputStream(), cachedBytes); + } + + public class CachedServletInputStream extends ServletInputStream { + private ByteArrayInputStream input; + + public CachedServletInputStream() { + input = new ByteArrayInputStream(cachedBytes.toByteArray()); } + + @Override + public int read() throws IOException { + return input.read(); + } + + public boolean isFinished() { + return false; + } + + public boolean isReady() { + return false; + } + + public void setReadListener(ReadListener readListener) { + + } + } - return payload; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - - if (request.getMethod().equalsIgnoreCase("POST") || request.getMethod().equalsIgnoreCase("PUT")) { - - HttpServletRequest requestToCache = new ContentCachingRequestWrapper(request); - HttpServletResponse responseToCache = new ContentCachingResponseWrapper(response); - filterChain.doFilter(requestToCache, responseToCache); - String requestData = getRequestData(requestToCache); - String responseData = getResponseData(responseToCache); - if (StringUtils.isNotBlank(requestData) && validator.denyXSS(requestData)) { - throw new SecurityException(BAD_REQUEST); + if (validateRequestType(request)) { + request = new RequestWrapper(request); + String requestData = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8.toString()); + try { + if (StringUtils.isNotBlank(requestData) && validator.denyXSS(requestData)) { + response.setContentType(APPLICATION_JSON); + response.setStatus(HttpStatus.SC_BAD_REQUEST); + response.getWriter().write(ERROR_BAD_REQUEST); + throw new SecurityException(ERROR_BAD_REQUEST); + } + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "doFilterInternal() failed due to BAD_REQUEST", e); + response.getWriter().close(); + return; } + filterChain.doFilter(request, response); } else { filterChain.doFilter(request, response); } } -} + + private boolean validateRequestType(HttpServletRequest request) { + return (request.getMethod().equalsIgnoreCase("POST") || request.getMethod().equalsIgnoreCase("PUT") + || request.getMethod().equalsIgnoreCase("DELETE")); + } +} \ No newline at end of file diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/conf/system.properties b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/conf/system.properties index de056a3d..0dc81301 100644 --- a/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/conf/system.properties +++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/conf/system.properties @@ -69,4 +69,6 @@ instance_uuid=8da691c9-987d-43ed-a358-00ac2f35685d # app_base_url = https://www.openecomp.org/app_context/ #authenticate user server -authenticate_user_server=http://todo_enter_auth_server_hostname:8383/openid-connect-server-webapp/allUsers \ No newline at end of file +authenticate_user_server=http://todo_enter_auth_server_hostname:8383/openid-connect-server-webapp/allUsers +#cookie domain +cookie_domain = onap.org \ No newline at end of file diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/web.xml b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/web.xml index f5039df4..76a372be 100644 --- a/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/web.xml +++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/web.xml @@ -1,8 +1,7 @@ + xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee" xmlns:web="http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" + version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"> ecomp-sdk-app-os @@ -14,12 +13,16 @@ COOKIE - SecurityXssFilter - org.onap.portalapp.filter.SecurityXssFilter - - - SecurityXssFilter - /* - + SecurityXssFilter + org.onap.portalapp.filter.SecurityXssFilter + + + + SecurityXssFilter + /* + + + /WEB-INF/jsp/error.jsp + \ No newline at end of file -- cgit 1.2.3-korg