赞
踩
compile('org.owasp.esapi:esapi:2.2.3.1') {
exclude group: 'log4j', module: 'log4j'
exclude group: 'org.slf4j', module: 'slf4j-simple'
}
# 是否要打印配置属性,默认为true ESAPI.printProperties=true ESAPI.AccessControl=org.owasp.esapi.reference.DefaultAccessController ESAPI.Authenticator=org.owasp.esapi.reference.FileBasedAuthenticator ESAPI.Encoder=org.owasp.esapi.reference.DefaultEncoder ESAPI.Encryptor=org.owasp.esapi.reference.crypto.JavaEncryptor ESAPI.Executor=org.owasp.esapi.reference.DefaultExecutor ESAPI.HTTPUtilities=org.owasp.esapi.reference.DefaultHTTPUtilities ESAPI.IntrusionDetector=org.owasp.esapi.reference.DefaultIntrusionDetector ESAPI.Logger=org.owasp.esapi.logging.slf4j.Slf4JLogFactory ESAPI.Randomizer=org.owasp.esapi.reference.DefaultRandomizer ESAPI.Validator=org.owasp.esapi.reference.DefaultValidator #=========================================================================== # ESAPI Encoder Encoder.AllowMultipleEncoding=false Encoder.AllowMixedEncoding=false Encoder.DefaultCodecList=HTMLEntityCodec,PercentCodec,JavaScriptCodec #=========================================================================== # ESAPI 加密模块 Encryptor.PreferredJCEProvider= Encryptor.EncryptionAlgorithm=AES Encryptor.CipherTransformation=AES/CBC/PKCS5Padding Encryptor.cipher_modes.combined_modes=GCM,CCM,IAPM,EAX,OCB,CWC Encryptor.cipher_modes.additional_allowed=CBC Encryptor.EncryptionKeyLength=128 Encryptor.ChooseIVMethod=random Encryptor.fixedIV=0x000102030405060708090a0b0c0d0e0f Encryptor.CipherText.useMAC=true Encryptor.PlainText.overwrite=true Encryptor.HashAlgorithm=SHA-512 Encryptor.HashIterations=1024 Encryptor.DigitalSignatureAlgorithm=SHA1withDSA Encryptor.DigitalSignatureKeyLength=1024 Encryptor.RandomAlgorithm=SHA1PRNG Encryptor.CharacterEncoding=UTF-8 Encryptor.KDF.PRF=HmacSHA256 #=========================================================================== # ESAPI Http工具 HttpUtilities.UploadDir=C:\\ESAPI\\testUpload HttpUtilities.UploadTempDir=C:\\temp # Force flags on cookies, if you use HttpUtilities to set cookies HttpUtilities.ForceHttpOnlySession=false HttpUtilities.ForceSecureSession=false HttpUtilities.ForceHttpOnlyCookies=true HttpUtilities.ForceSecureCookies=true # Maximum size of HTTP headers HttpUtilities.MaxHeaderSize=4096 # File upload configuration HttpUtilities.ApprovedUploadExtensions=.zip,.pdf,.doc,.docx,.ppt,.pptx,.tar,.gz,.tgz,.rar,.war,.jar,.ear,.xls,.rtf,.properties,.java,.class,.txt,.xml,.jsp,.jsf,.exe,.dll HttpUtilities.MaxUploadFileBytes=500000000 # Using UTF-8 throughout your stack is highly recommended. That includes your database driver, # container, and any other technologies you may be using. Failure to do this may expose you # to Unicode transcoding injection attacks. Use of UTF-8 does not hinder internationalization. HttpUtilities.ResponseContentType=text/html; charset=UTF-8 # This is the name of the cookie used to represent the HTTP session # Typically this will be the default "JSESSIONID" HttpUtilities.HttpSessionIdName=JSESSIONID #=========================================================================== # ESAPI Executor Executor.WorkingDirectory= Executor.ApprovedExecutables= #=========================================================================== # ESAPI Logging # Set the application name if these logs are combined with other applications Logger.ApplicationName=ExampleApplication # If you use an HTML log viewer that does not properly HTML escape log data, you can set LogEncodingRequired to true Logger.LogEncodingRequired=false # Determines whether ESAPI should log the application name. This might be clutter in some single-server/single-app environments. Logger.LogApplicationName=true # Determines whether ESAPI should log the server IP and port. This might be clutter in some single-server environments. Logger.LogServerIP=true # LogFileName, the name of the logging file. Provide a full directory path (e.g., C:\\ESAPI\\ESAPI_logging_file) if you # want to place it in a specific directory. Logger.LogFileName=ESAPI_logging_file # MaxLogFileSize, the max size (in bytes) of a single log file before it cuts over to a new one (default is 10,000,000) Logger.MaxLogFileSize=10000000 Logger.UserInfo=false Logger.ClientInfo=false #=========================================================================== # ESAPI Intrusion Detection IntrusionDetector.Disable=false IntrusionDetector.event.test.count=2 IntrusionDetector.event.test.interval=10 IntrusionDetector.event.test.actions=disable,log IntrusionDetector.org.owasp.esapi.errors.IntrusionException.count=1 IntrusionDetector.org.owasp.esapi.errors.IntrusionException.interval=1 IntrusionDetector.org.owasp.esapi.errors.IntrusionException.actions=log,disable,logout IntrusionDetector.org.owasp.esapi.errors.IntegrityException.count=10 IntrusionDetector.org.owasp.esapi.errors.IntegrityException.interval=5 IntrusionDetector.org.owasp.esapi.errors.IntegrityException.actions=log,disable,logout IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.count=2 IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.interval=10 IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.actions=log,logout #=========================================================================== # ESAPI 校验器 #校验器的配置文件 Validator.ConfigurationFile=validation.properties # Validators used by ESAPI Validator.AccountName=^[a-zA-Z0-9]{3,20}$ Validator.SystemCommand=^[a-zA-Z\\-\\/]{1,64}$ Validator.RoleName=^[a-z]{1,20}$ #the word TEST below should be changed to your application #name - only relative URL's are supported Validator.Redirect=^\\/test.*$ # Global HTTP Validation Rules # Values with Base64 encoded data (e.g. encrypted state) will need at least [a-zA-Z0-9\/+=] Validator.HTTPScheme=^(http|https)$ Validator.HTTPServerName=^[a-zA-Z0-9_.\\-]*$ Validator.HTTPParameterName=^[a-zA-Z0-9_]{1,32}$ Validator.HTTPParameterValue=^[a-zA-Z0-9.\\-\\/+=@_ ]*$ Validator.HTTPCookieName=^[a-zA-Z0-9\\-_]{1,32}$ Validator.HTTPCookieValue=^[a-zA-Z0-9\\-\\/+=_ ]*$ # Note that max header name capped at 150 in SecurityRequestWrapper! Validator.HTTPHeaderName=^[a-zA-Z0-9\\-_]{1,50}$ Validator.HTTPHeaderValue=^[a-zA-Z0-9()\\-=\\*\\.\\?;,+\\/:&_ ]*$ Validator.HTTPContextPath=^\\/?[a-zA-Z0-9.\\-\\/_]*$ Validator.HTTPServletPath=^[a-zA-Z0-9.\\-\\/_]*$ Validator.HTTPPath=^[a-zA-Z0-9.\\-_]*$ Validator.HTTPQueryString=^[a-zA-Z0-9()\\-=\\*\\.\\?;,+\\/:&_ %]*$ Validator.HTTPURI=^[a-zA-Z0-9()\\-=\\*\\.\\?;,+\\/:&_ ]*$ Validator.HTTPURL=^.*$ Validator.HTTPJSESSIONID=^[A-Z0-9]{10,30}$ # Validation of file related input Validator.FileName=^[a-zA-Z0-9!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1,255}$ Validator.DirectoryName=^[a-zA-Z0-9:/\\\\!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1,255}$ # Validation of dates. Controls whether or not 'lenient' dates are accepted. # See DataFormat.setLenient(boolean flag) for further details. Validator.AcceptLenientDates=false
Validator.SafeString=^[.\\p{Alnum}\\p{Space}]{0,1024}$
Validator.Email=^[A-Za-z0-9._%'-]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,4}$
Validator.IPAddress=^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
Validator.URL=^(ht|f)tp(s?)\\:\\/\\/[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\\:\\'\\/\\\\\\+=&%\\$#_]*)?$
Validator.CreditCard=^(\\d{4}[- ]?){3}\\d{4}$
Validator.SSN=^(?!000)([0-6]\\d{2}|7([0-6]\\d|7[012]))([ -]?)(?!00)\\d\\d\\3(?!0000)\\d{4}$
package com.lensyn.system.filter.xss; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; /** * xss过滤器 * * @author : gumingjun * @date : 2021-07-06 */ public class XssFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request); chain.doFilter(xssRequest, response); } }
package com.lensyn.system.filter; import com.lensyn.system.filter.host.HostCleanFilter; import com.lensyn.system.filter.xss.XssFilter; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.servlet.Filter; /** * xss过滤器配置 * * @author : gumingjun * @date : 2021-07-06 */ @Configuration public class FilterConfig { @Value("${filter.host.hosts}") private String hosts; @Value("${filter.host.host-filter-url}") private String hostFilterUrl; @Bean public FilterRegistrationBean xssFilterRegistrationBean() { FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>(); registration.setFilter(xssFilter()); registration.addUrlPatterns("/users/list"); registration.setName("xssFilter"); return registration; } @Bean public Filter xssFilter() { return new XssFilter(); } @Bean public FilterRegistrationBean hostsFilterRegistrationBean() { FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>(); registration.setFilter(hostsFilter()); registration.addUrlPatterns(hostFilterUrl); registration.setName("hostsFilter"); registration.addInitParameter("hosts", hosts); return registration; } @Bean public Filter hostsFilter() { return new HostCleanFilter(); } }
package com.gumj.system.filter.xss; import org.jsoup.Jsoup; import org.jsoup.safety.Whitelist; import org.owasp.esapi.ESAPI; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.util.regex.Pattern; /** * xss请求处理包装类 * * @author : gumingjun * @date : 2021-07-06 */ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) { super(servletRequest); } @Override public String[] getParameterValues(String parameter) { String[] values = super.getParameterValues(parameter); if (values == null) { return null; } int length = values.length; String[] encodedValues = new String[length]; for (int i = 0; i < length; i++) { //以下二者采用其一即可 //ESAPI方式 encodedValues[i] = cleanXss(values[i]); //Jsoup方式 //encodedValues[i] = Jsoup.clean(values[i], Whitelist.relaxed()).trim(); } return encodedValues; } @Override public String getParameter(String parameter) { String value = super.getParameter(parameter); if (value == null) { return null; } return cleanXss(value); } @Override public String getHeader(String name) { String value = super.getHeader(name); if (value == null) { return null; } return cleanXss(value); } private static Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE); private static Pattern srcPattern1 = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); private static Pattern srcPattern2 = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); private static Pattern scriptPattern2 = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE); private static Pattern scriptPattern3 = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); private static Pattern evalPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); private static Pattern expressionPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); private static Pattern javascriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE); private static Pattern vbScriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE); private static Pattern onloadPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); private static Pattern onPattern = Pattern.compile("on.*(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); private String cleanXss(String value) { if (value != null) { // 推荐使用ESAPI库来避免脚本攻击 value = ESAPI.encoder().canonicalize(value); // 避免空字符串 value = value.replaceAll("\\s", ""); // 避免script 标签 value = scriptPattern.matcher(value).replaceAll(""); // 避免src形式的表达式 value = srcPattern1.matcher(value).replaceAll(""); value = srcPattern2.matcher(value).replaceAll(""); // 删除单个的 </script> 标签 value = scriptPattern2.matcher(value).replaceAll(""); // 删除单个的<script ...> 标签 value = scriptPattern3.matcher(value).replaceAll(""); // 避免 eval(...) 形式表达式 value = evalPattern.matcher(value).replaceAll(""); // 避免 expression(...) 表达式 value = expressionPattern.matcher(value).replaceAll(""); // 避免 javascript: 表达式 value = javascriptPattern.matcher(value).replaceAll(""); // 避免 vbscript: 表达式 value = vbScriptPattern.matcher(value).replaceAll(""); // 避免 οnlοad= 表达式 value = onloadPattern.matcher(value).replaceAll(""); // 避免 onXX= 表达式 value = onPattern.matcher(value).replaceAll(""); } return value; } }
/** * host head漏洞 * * @author : gumingjun * @date : 2021-07-09 */ @Slf4j public class HostCleanFilter implements Filter { /** * host集合 */ private List<String> hosts = new ArrayList<>(); /** * 自定义实现host白名单添加 * * @param filterConfig 过滤器配置 * @throws ServletException */ @Override public void init(FilterConfig filterConfig) throws ServletException { final String hostsStr = filterConfig.getInitParameter("hosts"); if (StringUtils.isNotBlank(hostsStr)) { final String[] hostArr = hostsStr.split(","); for (String host : hostArr) { hosts.add(host.trim()); } } } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String host = request.getHeader("Host"); log.debug("Host-debug:" + host); if (StringUtils.isNotBlank(host)) { if (checkBlankList(host)) { filterChain.doFilter(servletRequest, servletResponse); } else { response.getWriter().print("host deny"); response.flushBuffer(); } } else { filterChain.doFilter(servletRequest, servletResponse); } } /** * 校验当前host是否在白名单中 * * @param host host * @return 是否包含在hosts允许的范围内 */ private boolean checkBlankList(String host) { // 访问白名单 // 127.0.0.1:8080就不能访问 final String[] hostSplit = host.split(":"); return hosts.contains(hostSplit[0]); } }
implementation 'org.jsoup:jsoup:1.13.1'
//详见:XssHttpServletRequestWrapper 类
Jsoup.clean(values[i], Whitelist.relaxed()).trim();
在 nginx.conf 配置文件中,增加如下配置内容:
add_header X-XSS-Protection "1; mode=block";
X-XSS-Protection 的字段有三个可选配置值,说明如下:
参数值 | 描述 |
---|---|
0 | 表示关闭浏览器的XSS防护机制 |
1 | 删除检测到的恶意代码, 如果响应报文中没有看到X-XSS-Protection 字段, 那么浏览器就认为X-XSS-Protection配置为1,这是浏览器的默认设置 |
1; mode=block | 如果检测到恶意代码,则不渲染恶意代码 |
systemctl restart nginx
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。