From 7662c7200fb83e475af3506a9b583b2fd2d6b270 Mon Sep 17 00:00:00 2001 From: dkayiwa Date: Thu, 14 Nov 2024 02:38:08 +0300 Subject: [PATCH] Filtering at the backend --- .../java/org/openmrs/web/xss/XSSFilter.java | 51 +++++++++++++ .../web/xss/XSSMultipartRequestWrapper.java | 72 ++++++++++++++++++ .../openmrs/web/xss/XSSRequestWrapper.java | 73 +++++++++++++++++++ omod/src/main/resources/config.xml | 9 +++ 4 files changed, 205 insertions(+) create mode 100644 omod/src/main/java/org/openmrs/web/xss/XSSFilter.java create mode 100644 omod/src/main/java/org/openmrs/web/xss/XSSMultipartRequestWrapper.java create mode 100644 omod/src/main/java/org/openmrs/web/xss/XSSRequestWrapper.java diff --git a/omod/src/main/java/org/openmrs/web/xss/XSSFilter.java b/omod/src/main/java/org/openmrs/web/xss/XSSFilter.java new file mode 100644 index 00000000..c3857ffa --- /dev/null +++ b/omod/src/main/java/org/openmrs/web/xss/XSSFilter.java @@ -0,0 +1,51 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under + * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. + * + * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS + * graphic logo is a trademark of OpenMRS Inc. + */ +package org.openmrs.web.xss; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest; + +public class XSSFilter implements Filter { + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, + ServletException { + + if (!"GET".equalsIgnoreCase(((HttpServletRequest) request).getMethod())) { + if (ServletFileUpload.isMultipartContent((HttpServletRequest) request)) { + request = new XSSMultipartRequestWrapper((DefaultMultipartHttpServletRequest) request); + } else { + request = new XSSRequestWrapper((HttpServletRequest) request); + } + } + + chain.doFilter(request, response); + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void destroy() { + + } +} diff --git a/omod/src/main/java/org/openmrs/web/xss/XSSMultipartRequestWrapper.java b/omod/src/main/java/org/openmrs/web/xss/XSSMultipartRequestWrapper.java new file mode 100644 index 00000000..db0b9752 --- /dev/null +++ b/omod/src/main/java/org/openmrs/web/xss/XSSMultipartRequestWrapper.java @@ -0,0 +1,72 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under + * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. + * + * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS + * graphic logo is a trademark of OpenMRS Inc. + */ +package org.openmrs.web.xss; + +import java.util.Enumeration; + +import org.owasp.encoder.Encode; +import org.springframework.util.MultiValueMap; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest; + +public class XSSMultipartRequestWrapper extends DefaultMultipartHttpServletRequest { + + public XSSMultipartRequestWrapper(DefaultMultipartHttpServletRequest request) { + super(request); + } + + @Override + public String getParameter(String name) { + + String value = getRequest().getParameter(name); + if (value == null) { + return null; + } + + return Encode.forHtml(value); + } + + @Override + public String[] getParameterValues(String name) { + + String[] values = getRequest().getParameterValues(name); + if (values == null) { + return null; + } + + int count = values.length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++) { + encodedValues[i] = Encode.forHtml(values[i]); + } + + return encodedValues; + } + + @Override + public DefaultMultipartHttpServletRequest getRequest() { + return (DefaultMultipartHttpServletRequest) super.getRequest(); + } + + @Override + public MultipartFile getFile(String name) { + return getRequest().getFile(name); + } + + @Override + public MultiValueMap getMultiFileMap() { + return getRequest().getMultiFileMap(); + } + + @Override + public Enumeration getParameterNames() { + return getRequest().getParameterNames(); + } +} diff --git a/omod/src/main/java/org/openmrs/web/xss/XSSRequestWrapper.java b/omod/src/main/java/org/openmrs/web/xss/XSSRequestWrapper.java new file mode 100644 index 00000000..844bd55c --- /dev/null +++ b/omod/src/main/java/org/openmrs/web/xss/XSSRequestWrapper.java @@ -0,0 +1,73 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under + * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. + * + * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS + * graphic logo is a trademark of OpenMRS Inc. + */ +package org.openmrs.web.xss; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +import org.apache.commons.io.IOUtils; +import org.owasp.encoder.Encode; + +public class XSSRequestWrapper extends HttpServletRequestWrapper { + + public XSSRequestWrapper(HttpServletRequest request) { + super(request); + } + + @Override + public String[] getParameterValues(String parameter) { + + String[] values = super.getParameterValues(parameter); + if (values == null) { + return null; + } + + int count = values.length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++) { + encodedValues[i] = Encode.forHtml(values[i]); + } + + return encodedValues; + } + + @Override + public String getParameter(String name) { + + String value = super.getParameter(name); + if (value == null) { + return null; + } + + return Encode.forHtml(value); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + + String requestBody = IOUtils.toString(super.getInputStream(), StandardCharsets.UTF_8.name()); + String sanitizedBody = Encode.forHtmlContent(requestBody); + + return new ServletInputStream() { + + private final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(sanitizedBody.getBytes()); + + @Override + public int read() throws IOException { + return byteArrayInputStream.read(); + } + }; + } +} diff --git a/omod/src/main/resources/config.xml b/omod/src/main/resources/config.xml index 4e78b785..b4009f68 100644 --- a/omod/src/main/resources/config.xml +++ b/omod/src/main/resources/config.xml @@ -351,6 +351,15 @@ dwrFilter /ms/call/plaincall/* + + + XSSFilter + org.openmrs.web.xss.XSSFilter + + + XSSFilter + /* +