2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6 * ===================================================================
8 * Unless otherwise specified, all software contained herein is licensed
9 * under the Apache License, Version 2.0 (the "License");
10 * you may not use this software except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
21 * Unless otherwise specified, all documentation contained herein is licensed
22 * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
23 * you may not use this documentation except in compliance with the License.
24 * You may obtain a copy of the License at
26 * https://creativecommons.org/licenses/by/4.0/
28 * Unless required by applicable law or agreed to in writing, documentation
29 * distributed under the License is distributed on an "AS IS" BASIS,
30 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31 * See the License for the specific language governing permissions and
32 * limitations under the License.
34 * ============LICENSE_END============================================
38 package org.onap.portalapp.filter;
40 import java.util.ArrayList;
41 import java.util.List;
42 import java.util.concurrent.locks.Lock;
43 import java.util.concurrent.locks.ReentrantLock;
44 import java.util.regex.Pattern;
46 import org.apache.commons.lang.NotImplementedException;
47 import org.apache.commons.lang.StringUtils;
48 import org.apache.commons.lang3.StringEscapeUtils;
49 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
50 import org.onap.portalsdk.core.util.SystemProperties;
51 import org.owasp.esapi.ESAPI;
52 import org.owasp.esapi.codecs.Codec;
53 import org.owasp.esapi.codecs.MySQLCodec;
54 import org.owasp.esapi.codecs.OracleCodec;
55 import org.owasp.esapi.codecs.MySQLCodec.Mode;
57 public class SecurityXssValidator {
59 private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SecurityXssValidator.class);
61 private static final String MYSQL_DB = "mysql";
62 private static final String ORACLE_DB = "oracle";
63 private static final String MARIA_DB = "mariadb";
64 private static final int FLAGS = Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL;
65 static SecurityXssValidator validator = null;
66 private static Codec instance;
67 private static final Lock lock = new ReentrantLock();
69 public static SecurityXssValidator getInstance() {
71 if (validator == null) {
74 if (validator == null)
75 validator = new SecurityXssValidator();
84 private SecurityXssValidator() {
85 // Avoid anything between script tags
86 XSS_INPUT_PATTERNS.add(Pattern.compile("<script>(.*?)</script>", FLAGS));
89 XSS_INPUT_PATTERNS.add(Pattern.compile("<iframe(.*?)>(.*?)</iframe>", FLAGS));
91 // Avoid anything in a src='...' type of expression
92 XSS_INPUT_PATTERNS.add(Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", FLAGS));
94 XSS_INPUT_PATTERNS.add(Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", FLAGS));
96 XSS_INPUT_PATTERNS.add(Pattern.compile("src[\r\n]*=[\r\n]*([^>]+)", FLAGS));
98 // Remove any lonesome </script> tag
99 XSS_INPUT_PATTERNS.add(Pattern.compile("</script>", FLAGS));
101 XSS_INPUT_PATTERNS.add(Pattern.compile(".*(<script>|</script>).*", FLAGS));
103 XSS_INPUT_PATTERNS.add(Pattern.compile(".*(<iframe>|</iframe>).*", FLAGS));
105 // Remove any lonesome <script ...> tag
106 XSS_INPUT_PATTERNS.add(Pattern.compile("<script(.*?)>", FLAGS));
108 // Avoid eval(...) expressions
109 XSS_INPUT_PATTERNS.add(Pattern.compile("eval\\((.*?)\\)", FLAGS));
111 // Avoid expression(...) expressions
112 XSS_INPUT_PATTERNS.add(Pattern.compile("expression\\((.*?)\\)", FLAGS));
114 // Avoid javascript:... expressions
115 XSS_INPUT_PATTERNS.add(Pattern.compile(".*(javascript:|vbscript:).*", FLAGS));
117 // Avoid onload= expressions
118 XSS_INPUT_PATTERNS.add(Pattern.compile(".*(onload(.*?)=).*", FLAGS));
121 private List<Pattern> XSS_INPUT_PATTERNS = new ArrayList<Pattern>();
124 * * This method takes a string and strips out any potential script injections.
127 * @return String - the new "sanitized" string.
129 public String stripXSS(String value) {
133 if (StringUtils.isNotBlank(value)) {
135 value = StringEscapeUtils.escapeHtml4(value);
137 value = ESAPI.encoder().canonicalize(value);
139 // Avoid null characters
140 value = value.replaceAll("\0", "");
142 for (Pattern xssInputPattern : XSS_INPUT_PATTERNS) {
143 value = xssInputPattern.matcher(value).replaceAll("");
147 } catch (Exception e) {
148 logger.error(EELFLoggerDelegate.errorLogger, "stripXSS() failed", e);
154 public Boolean denyXSS(String value) {
155 Boolean flag = Boolean.FALSE;
157 if (StringUtils.isNotBlank(value)) {
158 if (value.contains("×eclgn"))
160 logger.info(EELFLoggerDelegate.applicationLogger, "denyXSS() replacing ×eclgn with empty string for request value : " + value);
161 value=value.replaceAll("×eclgn", "");
163 value = ESAPI.encoder().canonicalize(value);
164 for (Pattern xssInputPattern : XSS_INPUT_PATTERNS) {
165 if (xssInputPattern.matcher(value).matches()) {
173 } catch (Exception e) {
174 logger.error(EELFLoggerDelegate.errorLogger, "denyXSS() failed for request with value : " + value, e);
180 public Codec getCodec() {
182 if (null == instance) {
183 if (StringUtils.containsIgnoreCase(SystemProperties.getProperty(SystemProperties.DB_DRIVER), MYSQL_DB)
184 || StringUtils.containsIgnoreCase(SystemProperties.getProperty(SystemProperties.DB_DRIVER),
186 instance = new MySQLCodec(Mode.STANDARD);
188 } else if (StringUtils.containsIgnoreCase(SystemProperties.getProperty(SystemProperties.DB_DRIVER),
190 instance = new OracleCodec();
192 throw new NotImplementedException("Handling for data base \""
193 + SystemProperties.getProperty(SystemProperties.DB_DRIVER) + "\" not yet implemented.");
197 } catch (Exception ex) {
198 logger.error(EELFLoggerDelegate.errorLogger, "getCodec() failed", ex);
204 public List<Pattern> getXSS_INPUT_PATTERNS() {
205 return XSS_INPUT_PATTERNS;
208 public void setXSS_INPUT_PATTERNS(List<Pattern> xSS_INPUT_PATTERNS) {
209 XSS_INPUT_PATTERNS = xSS_INPUT_PATTERNS;