From 3b4d9e772bc96effe948abf4f8e34737a1030148 Mon Sep 17 00:00:00 2001 From: Dominik Mizyn Date: Wed, 5 Jun 2019 16:24:35 +0200 Subject: [PATCH] XSS Vulnerability fix in DashboardSearchResultController Custom Validator is used to secure this endpoints. Issue-ID: OJSI-15 Change-Id: Idf523a53bc5fe9e1df8110526d56336953759c86 Signed-off-by: Dominik Mizyn --- .../DashboardSearchResultController.java | 50 +++++++--- .../DashboardSearchResultControllerTest.java | 104 +++++++++++++++++++++ 2 files changed, 143 insertions(+), 11 deletions(-) diff --git a/ecomp-portal-BE-os/src/main/java/org/onap/portalapp/portal/controller/DashboardSearchResultController.java b/ecomp-portal-BE-os/src/main/java/org/onap/portalapp/portal/controller/DashboardSearchResultController.java index 0be57120..1dff6040 100644 --- a/ecomp-portal-BE-os/src/main/java/org/onap/portalapp/portal/controller/DashboardSearchResultController.java +++ b/ecomp-portal-BE-os/src/main/java/org/onap/portalapp/portal/controller/DashboardSearchResultController.java @@ -48,7 +48,6 @@ import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.onap.portalapp.controller.EPRestrictedBaseController; -import org.onap.portalapp.portal.controller.DashboardSearchResultController; import org.onap.portalapp.portal.domain.EPUser; import org.onap.portalapp.portal.ecomp.model.PortalRestResponse; import org.onap.portalapp.portal.ecomp.model.PortalRestStatusEnum; @@ -57,6 +56,8 @@ import org.onap.portalapp.portal.service.DashboardSearchService; import org.onap.portalapp.portal.transport.CommonWidget; import org.onap.portalapp.portal.transport.CommonWidgetMeta; import org.onap.portalapp.util.EPUserUtils; +import org.onap.portalapp.validation.DataValidator; +import org.onap.portalapp.validation.SecureString; import org.onap.portalsdk.core.domain.support.CollaborateList; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.springframework.beans.factory.annotation.Autowired; @@ -71,6 +72,7 @@ import org.springframework.web.bind.annotation.RestController; public class DashboardSearchResultController extends EPRestrictedBaseController { private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(DashboardSearchResultController.class); + private DataValidator dataValidator = new DataValidator(); @Autowired private DashboardSearchService searchService; @@ -86,7 +88,12 @@ public class DashboardSearchResultController extends EPRestrictedBaseController @RequestMapping(value = "/widgetData", method = RequestMethod.GET, produces = "application/json") public PortalRestResponse getWidgetData(HttpServletRequest request, @RequestParam String resourceType) { - return new PortalRestResponse(PortalRestStatusEnum.OK, "success", + if (resourceType !=null){ + SecureString secureString = new SecureString(resourceType); + if (!dataValidator.isValid(secureString)) + return new PortalRestResponse<>(PortalRestStatusEnum.ERROR, "Provided data is invalid", null); + } + return new PortalRestResponse<>(PortalRestStatusEnum.OK, "success", searchService.getWidgetData(resourceType)); } @@ -100,9 +107,14 @@ public class DashboardSearchResultController extends EPRestrictedBaseController @RequestMapping(value = "/widgetDataBulk", method = RequestMethod.POST, produces = "application/json") public PortalRestResponse saveWidgetDataBulk(@RequestBody CommonWidgetMeta commonWidgetMeta) { logger.debug(EELFLoggerDelegate.debugLogger, "saveWidgetDataBulk: argument is {}", commonWidgetMeta); - if (commonWidgetMeta.getCategory() == null || commonWidgetMeta.getCategory().trim().equals("")) + if (commonWidgetMeta.getCategory() == null || commonWidgetMeta.getCategory().trim().equals("")){ return new PortalRestResponse(PortalRestStatusEnum.ERROR, "ERROR", "Category cannot be null or empty"); + }else { + if(!dataValidator.isValid(commonWidgetMeta)) + return new PortalRestResponse(PortalRestStatusEnum.ERROR, "ERROR", + "Category is not valid"); + } // validate dates for (CommonWidget cw : commonWidgetMeta.getItems()) { String err = validateCommonWidget(cw); @@ -123,13 +135,18 @@ public class DashboardSearchResultController extends EPRestrictedBaseController @RequestMapping(value = "/widgetData", method = RequestMethod.POST, produces = "application/json") public PortalRestResponse saveWidgetData(@RequestBody CommonWidget commonWidget) { logger.debug(EELFLoggerDelegate.debugLogger, "saveWidgetData: argument is {}", commonWidget); - if (commonWidget.getCategory() == null || commonWidget.getCategory().trim().equals("")) - return new PortalRestResponse(PortalRestStatusEnum.ERROR, "ERROR", + if (commonWidget.getCategory() == null || commonWidget.getCategory().trim().equals("")){ + return new PortalRestResponse<>(PortalRestStatusEnum.ERROR, "ERROR", "Cateogry cannot be null or empty"); + }else { + if(!dataValidator.isValid(commonWidget)) + return new PortalRestResponse<>(PortalRestStatusEnum.ERROR, "ERROR", + "Category is not valid"); + } String err = validateCommonWidget(commonWidget); if (err != null) - return new PortalRestResponse(PortalRestStatusEnum.ERROR, err, null); - return new PortalRestResponse(PortalRestStatusEnum.OK, "success", + return new PortalRestResponse<>(PortalRestStatusEnum.ERROR, err, null); + return new PortalRestResponse<>(PortalRestStatusEnum.OK, "success", searchService.saveWidgetData(commonWidget)); } @@ -165,7 +182,10 @@ public class DashboardSearchResultController extends EPRestrictedBaseController @RequestMapping(value = "/deleteData", method = RequestMethod.POST, produces = "application/json") public PortalRestResponse deleteWidgetData(@RequestBody CommonWidget commonWidget) { logger.debug(EELFLoggerDelegate.debugLogger, "deleteWidgetData: argument is {}", commonWidget); - return new PortalRestResponse(PortalRestStatusEnum.OK, "success", + if(!dataValidator.isValid(commonWidget)) + return new PortalRestResponse<>(PortalRestStatusEnum.ERROR, "ERROR", + "Data is not valid"); + return new PortalRestResponse<>(PortalRestStatusEnum.OK, "success", searchService.deleteWidgetData(commonWidget)); } @@ -180,16 +200,24 @@ public class DashboardSearchResultController extends EPRestrictedBaseController @RequestMapping(value = "/allPortal", method = RequestMethod.GET, produces = "application/json") public PortalRestResponse>> searchPortal(HttpServletRequest request, @RequestParam String searchString) { + if(searchString!=null){ + SecureString secureString = new SecureString(searchString); + if(!dataValidator.isValid(secureString)){ + return new PortalRestResponse<>(PortalRestStatusEnum.ERROR, + "searchPortal: User object is invalid", + null); + } + } EPUser user = EPUserUtils.getUserSession(request); try { if (user == null) { return new PortalRestResponse<>(PortalRestStatusEnum.ERROR, "searchPortal: User object is null? - check logs", - new HashMap>()); + new HashMap<>()); } else if (searchString == null || searchString.trim().length() == 0) { return new PortalRestResponse<>(PortalRestStatusEnum.ERROR, "searchPortal: String string is null", - new HashMap>()); + new HashMap<>()); } else { logger.debug(EELFLoggerDelegate.debugLogger, "searchPortal: user {}, search string '{}'", user.getLoginId(), searchString); @@ -200,7 +228,7 @@ public class DashboardSearchResultController extends EPRestrictedBaseController } catch (Exception e) { logger.error(EELFLoggerDelegate.errorLogger, "searchPortal failed", e); return new PortalRestResponse<>(PortalRestStatusEnum.ERROR, e.getMessage() + " - check logs.", - new HashMap>()); + new HashMap<>()); } } diff --git a/ecomp-portal-BE-os/src/test/java/org/onap/portalapp/portal/controller/DashboardSearchResultControllerTest.java b/ecomp-portal-BE-os/src/test/java/org/onap/portalapp/portal/controller/DashboardSearchResultControllerTest.java index 9edf99e7..ff588daa 100644 --- a/ecomp-portal-BE-os/src/test/java/org/onap/portalapp/portal/controller/DashboardSearchResultControllerTest.java +++ b/ecomp-portal-BE-os/src/test/java/org/onap/portalapp/portal/controller/DashboardSearchResultControllerTest.java @@ -98,6 +98,18 @@ public class DashboardSearchResultControllerTest { assertEquals(ecpectedPortalRestResponse.getStatus(), actualPortalRestResponse.getStatus()); } + @Test + public void getWidgetDataXSSTest() { + String resourceType = "\"\""; + PortalRestResponse expectedPortalRestResponse = new PortalRestResponse<>(); + expectedPortalRestResponse.setMessage("Provided data is invalid"); + expectedPortalRestResponse.setStatus(PortalRestStatusEnum.ERROR); + Mockito.when(searchService.getWidgetData(resourceType)).thenReturn(null); + PortalRestResponse acutualPoratlRestResponse = dashboardSearchResultController + .getWidgetData(mockedRequest, resourceType); + assertEquals(acutualPoratlRestResponse, expectedPortalRestResponse); + } + @Test public void saveWidgetDataBulkIfCatrgoryNullTest() { PortalRestResponse ecpectedPortalRestResponse = new PortalRestResponse(); @@ -151,6 +163,82 @@ public class DashboardSearchResultControllerTest { assertEquals(ecpectedPortalRestResponse, actualPortalRestResponse); } + @Test + public void saveWidgetDataBulkXSSTest() { + PortalRestResponse ecpectedPortalRestResponse = new PortalRestResponse<>(); + ecpectedPortalRestResponse.setMessage("ERROR"); + ecpectedPortalRestResponse.setResponse("Category is not valid"); + ecpectedPortalRestResponse.setStatus(PortalRestStatusEnum.ERROR); + + CommonWidgetMeta commonWidgetMeta = new CommonWidgetMeta(); + commonWidgetMeta.setCategory("test"); + + List commonWidgetList = new ArrayList<>(); + CommonWidget commonWidget = new CommonWidget(); + commonWidget.setId((long) 1); + commonWidget.setCategory("test"); + commonWidget.setHref("\"\""); + commonWidget.setTitle("test_title"); + commonWidget.setContent("test_content"); + commonWidget.setEventDate(null); + commonWidget.setSortOrder(1); + + commonWidgetList.add(commonWidget); + + commonWidgetMeta.setItems(commonWidgetList); + + Mockito.when(searchService.saveWidgetDataBulk(commonWidgetMeta)).thenReturn(null); + + PortalRestResponse actualPortalRestResponse = dashboardSearchResultController + .saveWidgetDataBulk(commonWidgetMeta); + assertEquals(ecpectedPortalRestResponse, actualPortalRestResponse); + } + + @Test + public void saveWidgetDataXSSTest() { + PortalRestResponse expectedPortalRestResponse = new PortalRestResponse<>(); + expectedPortalRestResponse.setMessage("ERROR"); + expectedPortalRestResponse.setResponse("Category is not valid"); + expectedPortalRestResponse.setStatus(PortalRestStatusEnum.ERROR); + CommonWidget commonWidget = new CommonWidget(); + commonWidget.setId((long) 1); + commonWidget.setCategory("test"); + commonWidget.setHref("\"\""); + commonWidget.setTitle("test_title"); + commonWidget.setContent("test_content"); + commonWidget.setEventDate(null); + commonWidget.setSortOrder(1); + + Mockito.when(searchService.saveWidgetData(commonWidget)).thenReturn(null); + + PortalRestResponse actualPortalRestResponse = dashboardSearchResultController + .saveWidgetData(commonWidget); + assertEquals(expectedPortalRestResponse, actualPortalRestResponse); + + } + + @Test + public void deleteWidgetDataXSSTest() { + PortalRestResponse expectedPortalRestResponse = new PortalRestResponse<>(); + expectedPortalRestResponse.setMessage("ERROR"); + expectedPortalRestResponse.setResponse("Data is not valid"); + expectedPortalRestResponse.setStatus(PortalRestStatusEnum.ERROR); + CommonWidget commonWidget = new CommonWidget(); + commonWidget.setId((long) 1); + commonWidget.setCategory("test"); + commonWidget.setHref("test_href"); + commonWidget.setTitle("\"\""); + commonWidget.setContent("test_content"); + commonWidget.setEventDate(null); + commonWidget.setSortOrder(1); + Mockito.when(searchService.deleteWidgetData(commonWidget)).thenReturn(null); + + PortalRestResponse actualPortalRestResponse = dashboardSearchResultController + .deleteWidgetData(commonWidget); + + assertEquals(expectedPortalRestResponse, actualPortalRestResponse); + } + @Test public void saveWidgetDataIfCatagoryNullTest() { PortalRestResponse ecpectedPortalRestResponse = new PortalRestResponse(); @@ -339,6 +427,22 @@ public class DashboardSearchResultControllerTest { } + @Test + public void searchPortalXSS() { + EPUser user = mockUser.mockEPUser(); + Mockito.when(EPUserUtils.getUserSession(mockedRequest)).thenReturn(user); + String searchString = " "; + + PortalRestResponse>> expectedResult = new PortalRestResponse>>(); + expectedResult.setMessage("searchPortal: User object is invalid"); + expectedResult.setStatus(PortalRestStatusEnum.ERROR); + + PortalRestResponse>> actualResult = dashboardSearchResultController + .searchPortal(mockedRequest, searchString); + assertEquals(actualResult, expectedResult); + + } + @Test public void searchPortalIfSearchExcptionTest() { EPUser user = mockUser.mockEPUser(); -- 2.16.6