-
Notifications
You must be signed in to change notification settings - Fork 84
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes done for security vulnerabilities (#50)
* [Rohit|Tazeen] Allows pdf, image, doc type file uploads. Restricts other file types and double extensions * [Rohit] Removes multiple error messages for invalid login, kept only one * [Rohit|Tazeen] Strips stored xss from imput fields * [Rohit|Tazeen] Adds server side validation to restricts file uploads * Update README.md --------- Co-authored-by: rohit-yawalkar <[email protected]> Co-authored-by: SanoferSameera <[email protected]>
- Loading branch information
1 parent
4ba28d5
commit 9515a14
Showing
7 changed files
with
98 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 59 additions & 33 deletions
92
openelis/src/us/mn/state/health/lims/common/util/SafeRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,83 @@ | ||
package us.mn.state.health.lims.common.util; | ||
|
||
|
||
import java.util.regex.Pattern; | ||
import org.apache.logging.log4j.Logger; | ||
import org.apache.logging.log4j.LogManager; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletRequestWrapper; | ||
import java.util.Arrays; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class SafeRequest extends HttpServletRequestWrapper { | ||
|
||
private final Logger logger = LogManager.getLogger(SafeRequest.class); | ||
private List<String> ignoreEncodingForParams = Arrays.asList("sampleXML"); | ||
|
||
public SafeRequest(HttpServletRequest request) { | ||
super(request); | ||
private static Pattern[] patterns = new Pattern[]{ | ||
// Script fragments | ||
Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE), | ||
// src='...' | ||
Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), | ||
Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), | ||
// lonely script tags | ||
Pattern.compile("</script>", Pattern.CASE_INSENSITIVE), | ||
Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), | ||
// eval(...) | ||
Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), | ||
// expression(...) | ||
Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL), | ||
// javascript:... | ||
Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE), | ||
// vbscript:... | ||
Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE), | ||
// onload(...)=... | ||
Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL) | ||
}; | ||
|
||
public SafeRequest(HttpServletRequest servletRequest) { | ||
super(servletRequest); | ||
} | ||
|
||
@Override | ||
public String getParameter(String name) { | ||
HttpServletRequest request = (HttpServletRequest) this.getRequest(); | ||
String encodedValue = getEncodedParamValue(name, request.getParameter(name)); | ||
logger.debug(String.format("Intercepted action request: %s, name: %s, value= %s", request.getServletPath(), name, encodedValue)); | ||
return encodedValue; | ||
} | ||
public String[] getParameterValues(String parameter) { | ||
String[] values = super.getParameterValues(parameter); | ||
|
||
private String getEncodedParamValue(String name, String value) { | ||
if (ignoreEncodingForParams.contains(name)) { | ||
return value; | ||
if (values == null) { | ||
return null; | ||
} | ||
return StringUtil.encode(value); | ||
|
||
int count = values.length; | ||
String[] encodedValues = new String[count]; | ||
for (int i = 0; i < count; i++) { | ||
encodedValues[i] = stripXSS(values[i]); | ||
} | ||
|
||
return encodedValues; | ||
} | ||
|
||
@Override | ||
public Map<String, String[]> getParameterMap() { | ||
logger.debug("getParameterMap"); | ||
Map<String, String[]> newParameterMap = new HashMap<>(); | ||
Map<String, String[]> existingParameterMap = super.getParameterMap(); | ||
for (String key : existingParameterMap.keySet()) { | ||
newParameterMap.put(key, getParameterValues(key)); | ||
} | ||
return newParameterMap; | ||
public String getParameter(String parameter) { | ||
String value = super.getParameter(parameter); | ||
|
||
return stripXSS(value); | ||
} | ||
|
||
@Override | ||
public String[] getParameterValues(String name) { | ||
logger.debug("getParameterValues"); | ||
String[] existingValues = super.getParameterValues(name); | ||
String[] newValues = new String[existingValues.length]; | ||
for (int i = 0; i < existingValues.length; i++) { | ||
newValues[i] = getEncodedParamValue(name, existingValues[i]); | ||
logger.debug(String.format("Encoded param name: %s, value= %s", name, name, newValues[i])); | ||
public String getHeader(String name) { | ||
String value = super.getHeader(name); | ||
return stripXSS(value); | ||
} | ||
|
||
private String stripXSS(String value) { | ||
if (value != null) { | ||
|
||
// Avoid null characters | ||
value = value.replaceAll("\0", ""); | ||
|
||
// Remove all sections that match a pattern | ||
for (Pattern scriptPattern : patterns){ | ||
value = scriptPattern.matcher(value).replaceAll(""); | ||
} | ||
} | ||
return newValues; | ||
return value; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters