diff options
author | 2019-06-05 16:24:35 +0200 | |
---|---|---|
committer | 2019-06-05 16:24:40 +0200 | |
commit | 3b4d9e772bc96effe948abf4f8e34737a1030148 (patch) | |
tree | df4591b147faefcbe896b1ef5d277c5e8d9d6f87 | |
parent | 3ee6a1ab82fcc13dd28ab825d1c77ee6067ab467 (diff) |
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 <d.mizyn@samsung.com>
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<CommonWidgetMeta> getWidgetData(HttpServletRequest request, @RequestParam String resourceType) { - return new PortalRestResponse<CommonWidgetMeta>(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<String> 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<String>(PortalRestStatusEnum.ERROR, "ERROR", "Category cannot be null or empty"); + }else { + if(!dataValidator.isValid(commonWidgetMeta)) + return new PortalRestResponse<String>(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<String> saveWidgetData(@RequestBody CommonWidget commonWidget) { logger.debug(EELFLoggerDelegate.debugLogger, "saveWidgetData: argument is {}", commonWidget); - if (commonWidget.getCategory() == null || commonWidget.getCategory().trim().equals("")) - return new PortalRestResponse<String>(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<String>(PortalRestStatusEnum.ERROR, err, null); - return new PortalRestResponse<String>(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<String> deleteWidgetData(@RequestBody CommonWidget commonWidget) { logger.debug(EELFLoggerDelegate.debugLogger, "deleteWidgetData: argument is {}", commonWidget); - return new PortalRestResponse<String>(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<Map<String, List<SearchResultItem>>> 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<String, List<SearchResultItem>>()); + new HashMap<>()); } else if (searchString == null || searchString.trim().length() == 0) { return new PortalRestResponse<>(PortalRestStatusEnum.ERROR, "searchPortal: String string is null", - new HashMap<String, List<SearchResultItem>>()); + 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<String, List<SearchResultItem>>()); + 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 @@ -99,6 +99,18 @@ public class DashboardSearchResultControllerTest { } @Test + public void getWidgetDataXSSTest() { + String resourceType = "\"<IMG SRC=\\\"jav\\tascript:alert('XSS');\\\">\""; + 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<String> ecpectedPortalRestResponse = new PortalRestResponse<String>(); ecpectedPortalRestResponse.setMessage("ERROR"); @@ -152,6 +164,82 @@ public class DashboardSearchResultControllerTest { } @Test + public void saveWidgetDataBulkXSSTest() { + PortalRestResponse<String> ecpectedPortalRestResponse = new PortalRestResponse<>(); + ecpectedPortalRestResponse.setMessage("ERROR"); + ecpectedPortalRestResponse.setResponse("Category is not valid"); + ecpectedPortalRestResponse.setStatus(PortalRestStatusEnum.ERROR); + + CommonWidgetMeta commonWidgetMeta = new CommonWidgetMeta(); + commonWidgetMeta.setCategory("test"); + + List<CommonWidget> commonWidgetList = new ArrayList<>(); + CommonWidget commonWidget = new CommonWidget(); + commonWidget.setId((long) 1); + commonWidget.setCategory("test"); + commonWidget.setHref("\"<IMG SRC=\\\"jav\\tascript:alert('XSS');\\\">\""); + 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<String> actualPortalRestResponse = dashboardSearchResultController + .saveWidgetDataBulk(commonWidgetMeta); + assertEquals(ecpectedPortalRestResponse, actualPortalRestResponse); + } + + @Test + public void saveWidgetDataXSSTest() { + PortalRestResponse<String> 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("\"<IMG SRC=\"jav\\tascript:alert('XSS');\">\""); + commonWidget.setTitle("test_title"); + commonWidget.setContent("test_content"); + commonWidget.setEventDate(null); + commonWidget.setSortOrder(1); + + Mockito.when(searchService.saveWidgetData(commonWidget)).thenReturn(null); + + PortalRestResponse<String> actualPortalRestResponse = dashboardSearchResultController + .saveWidgetData(commonWidget); + assertEquals(expectedPortalRestResponse, actualPortalRestResponse); + + } + + @Test + public void deleteWidgetDataXSSTest() { + PortalRestResponse<String> 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("\"<IMG SRC=\"jav\\tascript:alert('XSS');\">\""); + commonWidget.setContent("test_content"); + commonWidget.setEventDate(null); + commonWidget.setSortOrder(1); + Mockito.when(searchService.deleteWidgetData(commonWidget)).thenReturn(null); + + PortalRestResponse<String> actualPortalRestResponse = dashboardSearchResultController + .deleteWidgetData(commonWidget); + + assertEquals(expectedPortalRestResponse, actualPortalRestResponse); + } + + @Test public void saveWidgetDataIfCatagoryNullTest() { PortalRestResponse<String> ecpectedPortalRestResponse = new PortalRestResponse<String>(); ecpectedPortalRestResponse.setMessage("ERROR"); @@ -340,6 +428,22 @@ public class DashboardSearchResultControllerTest { } @Test + public void searchPortalXSS() { + EPUser user = mockUser.mockEPUser(); + Mockito.when(EPUserUtils.getUserSession(mockedRequest)).thenReturn(user); + String searchString = "<script>alert(“XSS”)</script> "; + + PortalRestResponse<Map<String, List<SearchResultItem>>> expectedResult = new PortalRestResponse<Map<String, List<SearchResultItem>>>(); + expectedResult.setMessage("searchPortal: User object is invalid"); + expectedResult.setStatus(PortalRestStatusEnum.ERROR); + + PortalRestResponse<Map<String, List<SearchResultItem>>> actualResult = dashboardSearchResultController + .searchPortal(mockedRequest, searchString); + assertEquals(actualResult, expectedResult); + + } + + @Test public void searchPortalIfSearchExcptionTest() { EPUser user = mockUser.mockEPUser(); ; |