springboot经验之sql注入、xss注入拦截(POST)

编程

POST防注入方案

1、增加httprequest包装类

import java.io.BufferedReader;

import java.io.ByteArrayInputStream;

import java.io.IOException;

import java.io.InputStreamReader;

import java.util.*;

import java.util.regex.Pattern;

import javax.servlet.ReadListener;

import javax.servlet.ServletInputStream;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletRequestWrapper;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;

import org.springframework.util.StreamUtils;

@Slf4j

public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper {

private static String key = "and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+";

private static Set<string> notAllowedKeyWords = new HashSet<string>(0);

static {

String keyStr[] = key.split("\|");

for (String str : keyStr) {

notAllowedKeyWords.add(str);

}

}

HttpServletRequest orgRequest = null;

private Map<string, string[]> parameterMap;

private final byte[] body; //用于保存读取body中数据

public XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) throws IOException{

super(request);

orgRequest = request;

parameterMap = request.getParameterMap();

body = StreamUtils.copyToByteArray(request.getInputStream());

}

// 重写几个HttpServletRequestWrapper中的方法

/**

* 获取所有参数名

*

* @return 返回所有参数名

*/

@Override

public Enumeration<string> getParameterNames() {

Vector<string> vector = new Vector<string>(parameterMap.keySet());

return vector.elements();

}

/**

* 覆盖getParameter方法,将参数名和参数值都做xss &amp; sql过滤。<br>

* 如果需要获得原始的值,则通过super.getParameterValues(name)来获取<br>

* getParameterNames,getParameterValues和getParameterMap也可能需要覆盖

*/

@Override

public String getParameter(String name) {

String[] results = parameterMap.get(name);

if (results == null || results.length &lt;= 0)

return null;

else {

String value = results[0];

if (value != null) {

value = xssEncode(value);

}

return value;

}

}

/**

* 获取指定参数名的所有值的数组,如:checkbox的所有数据 接收数组变量 ,如checkobx类型

*/

@Override

public String[] getParameterValues(String name) {

String[] results = parameterMap.get(name);

if (results == null || results.length &lt;= 0)

return null;

else {

int length = results.length;

for (int i = 0; i &lt; length; i++) {

results[i] = xssEncode(results[i]);

}

return results;

}

}

/**

* 覆盖getHeader方法,将参数名和参数值都做xss &amp; sql过滤。<br>

* 如果需要获得原始的值,则通过super.getHeaders(name)来获取<br>

* getHeaderNames 也可能需要覆盖

*/

@Override

public String getHeader(String name) {

String value = super.getHeader(xssEncode(name));

if (value != null) {

value = xssEncode(value);

}

return value;

}

/**

* 将容易引起xss &amp; sql漏洞的半角字符直接替换成全角字符

*

* @param s

* @return

*/

private static String xssEncode(String s) {

if (s == null || s.isEmpty()) {

return s;

} else {

s = stripXSSAndSql(s);

}

StringBuilder sb = new StringBuilder(s.length() + 16);

for (int i = 0; i &lt; s.length(); i++) {

char c = s.charAt(i);

switch (c) {

case "&gt;":

sb.append(">");// 转义大于号

break;

case "&lt;":

sb.append("<");// 转义小于号

break;

// case """:

// sb.append("'");// 转义单引号

// break;

// case """:

// sb.append(""");// 转义双引号

// break;

case "&amp;":

sb.append("&");// 转义&amp;

break;

case "#":

sb.append("#");// 转义#

break;

default:

sb.append(c);

break;

}

}

return sb.toString();

}

/**

* 获取最原始的request

*

* @return

*/

public HttpServletRequest getOrgRequest() {

return orgRequest;

}

/**

* 获取最原始的request的静态方法

*

* @return

*/

public static HttpServletRequest getOrgRequest(HttpServletRequest req) {

if (req instanceof XssAndSqlHttpServletRequestWrapper) {

return ((XssAndSqlHttpServletRequestWrapper) req).getOrgRequest();

}

return req;

}

/**

*

* 防止xss跨脚本攻击(替换,根据实际情况调整)

*/

public static String stripXSSAndSql(String value) {

if (value != null) {

// NOTE: It"s highly recommended to use the ESAPI library and

// uncomment the following line to

// avoid encoded attacks.

// value = ESAPI.encoder().canonicalize(value);

// Avoid null characters

/** value = value.replaceAll("", ""); ***/

// Avoid anything between script tags

Pattern scriptPattern = Pattern.compile(

"&lt;[

| | ]*script[

| | ]*&gt;(.*?)<!--[

| | ]*script[

| | ]*-->", Pattern.CASE_INSENSITIVE);

value = scriptPattern.matcher(value).replaceAll("");

// Avoid anything in a

// src="http://www.yihaomen.com/article/java/..." type of

// e-xpression

scriptPattern = Pattern.compile("src[

| | ]*=[

| | ]*[\"|\"](.*?)[\"|\"]",

Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

value = scriptPattern.matcher(value).replaceAll("");

// Remove any lonesome tag

scriptPattern = Pattern.compile("<!--[

| | ]*script[

| | ]*-->", Pattern.CASE_INSENSITIVE);

value = scriptPattern.matcher(value).replaceAll("");

// Remove any lonesome <script ...> tag

scriptPattern = Pattern.compile("<[

| | ]*script(.*?)>",

Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

value = scriptPattern.matcher(value).replaceAll("");

// Avoid eval(...) expressions

scriptPattern = Pattern.compile("eval\((.*?)\)",

Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

value = scriptPattern.matcher(value).replaceAll("");

// Avoid e-xpression(...) expressions

scriptPattern = Pattern.compile("e-xpression\((.*?)\)",

Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

value = scriptPattern.matcher(value).replaceAll("");

// Avoid javascript:... expressions

scriptPattern = Pattern.compile("javascript[

| | ]*:[

| | ]*", Pattern.CASE_INSENSITIVE);

value = scriptPattern.matcher(value).replaceAll("");

// Avoid vbscript:... expressions

scriptPattern = Pattern.compile("vbscript[

| | ]*:[

| | ]*", Pattern.CASE_INSENSITIVE);

value = scriptPattern.matcher(value).replaceAll("");

// Avoid onload= expressions

scriptPattern = Pattern.compile("onload(.*?)=",

Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

value = scriptPattern.matcher(value).replaceAll("");

}

return value;

}

public boolean checkXSSAndSql(String value) {

boolean flag = false;

if (value != null) {

// NOTE: It"s highly recommended to use the ESAPI library and

// uncomment the following line to

// avoid encoded attacks.

// value = ESAPI.encoder().canonicalize(value);

// Avoid null characters

/** value = value.replaceAll("", ""); ***/

// Avoid anything between script tags

Pattern scriptPattern = Pattern.compile(

"<[

| | ]*script[

| | ]*>(.*?)</[

| | ]*script[

| | ]*>", Pattern.CASE_INSENSITIVE);

flag = scriptPattern.matcher(value).find();

if (flag) {

return flag;

}

// Avoid anything in a

// src="http://www.yihaomen.com/article/java/..." type of

// e-xpression

scriptPattern = Pattern.compile("src[

| | ]*=[

| | ]*[\"|\"](.*?)[\"|\"]",

Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

flag = scriptPattern.matcher(value).find();

if (flag) {

return flag;

}

// Remove any lonesome </script> tag

scriptPattern = Pattern.compile("<!--[

| | ]*script[

| | ]*-->", Pattern.CASE_INSENSITIVE);

flag = scriptPattern.matcher(value).find();

if (flag) {

return flag;

}

// Remove any lonesome <script ...> tag

scriptPattern = Pattern.compile("<[

| | ]*script(.*?)>",

Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

flag = scriptPattern.matcher(value).find();

if (flag) {

return flag;

}

// Avoid eval(...) expressions

scriptPattern = Pattern.compile("eval\((.*?)\)",

Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

flag = scriptPattern.matcher(value).find();

if (flag) {

return flag;

}

// Avoid e-xpression(...) expressions

scriptPattern = Pattern.compile("e-xpression\((.*?)\)",

Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

flag = scriptPattern.matcher(value).find();

if (flag) {

return flag;

}

// Avoid javascript:... expressions

scriptPattern = Pattern.compile("javascript[

| | ]*:[

| | ]*", Pattern.CASE_INSENSITIVE);

flag = scriptPattern.matcher(value).find();

if (flag) {

return flag;

}

// Avoid vbscript:... expressions

scriptPattern = Pattern.compile("vbscript[

| | ]*:[

| | ]*", Pattern.CASE_INSENSITIVE);

flag = scriptPattern.matcher(value).find();

if (flag) {

return flag;

}

// Avoid onload= expressions

scriptPattern = Pattern.compile("onload(.*?)=",

Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

flag = scriptPattern.matcher(value).find();

if (flag) {

return flag;

}

flag=checkSqlKeyWords(value);

}

return flag;

}

public boolean checkSqlKeyWords(String value){

String paramValue = value;

for (String keyword : notAllowedKeyWords) {

if (paramValue.length() > keyword.length() + 4

&& (paramValue.contains(" "+keyword)||paramValue.contains(keyword+" ")||paramValue.contains(" "+keyword+" "))) {

log.error(this.getRequestURI()+ "参数中包含不允许sql的关键词(" + keyword

+ ")");

return true;

}

}

return false;

}

public final boolean checkParameter() {

Map<String, String[]> submitParams = new HashMap(parameterMap);

Set<String> submitNames = submitParams.keySet();

for (String submitName : submitNames) {

Object submitValues = submitParams.get(submitName);

if ((submitValues instanceof String)) {

if (checkXSSAndSql((String) submitValues)) {

return true;

}

} else if ((submitValues instanceof String[])) {

for (String submitValue : (String[])submitValues){

if (checkXSSAndSql(submitValue)) {

return true;

}

}

}

}

return false;

}

@Override

public BufferedReader getReader() throws IOException {

return new BufferedReader(new InputStreamReader(getInputStream()));

}

@Override

public ServletInputStream getInputStream() throws IOException {

final ByteArrayInputStream bais = new ByteArrayInputStream(body);

return new ServletInputStream() {

@Override

public int read() throws IOException {

return bais.read();

}

@Override

public boolean isFinished() {

// TODO Auto-generated method stub

return false;

}

@Override

public boolean isReady() {

// TODO Auto-generated method stub

return false;

}

@Override

public void setReadListener(ReadListener arg0) {

// TODO Auto-generated method stub

}

};

}

}

2、增加过滤器

import java.io.BufferedReader;

import java.io.IOException;

import java.io.PrintWriter;

import java.util.UUID;

import javax.servlet.DispatcherType;

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.annotation.WebFilter;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSON;

import com.code.base.BaseResponse;

import org.apache.commons.lang3.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;

import lombok.extern.slf4j.Slf4j;

@Slf4j

@WebFilter(

filterName = "xssFilter",

urlPatterns = "/*",

dispatcherTypes = DispatcherType.REQUEST

)

public class XssFilter implements Filter {

@Override

public void init(FilterConfig filterConfig) {

// no init operation

}

@Override

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,

FilterChain filterChain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) servletRequest;

XssAndSqlHttpServletRequestWrapper xssRequest=new XssAndSqlHttpServletRequestWrapper(

request);

String method = ((HttpServletRequest) request).getMethod();

String param = "";

if ("POST".equalsIgnoreCase(method)) {

param = this.getBodyString(xssRequest.getReader());

if(StringUtils.isNotBlank(param)){

if(xssRequest.checkXSSAndSql(param)){

servletResponse.setCharacterEncoding("UTF-8");

servletResponse.setContentType("application/json;charset=UTF-8");

PrintWriter out = servletResponse.getWriter();

out.write(JSON.toJSONString(BaseResponse.error(AppErrorCode.PARAMS_ERROR)));

return;

}

}

}

if (xssRequest.checkParameter()) {

servletResponse.setCharacterEncoding("UTF-8");

servletResponse.setContentType("application/json;charset=UTF-8");

PrintWriter out = servletResponse.getWriter();

out.write(JSON.toJSONString(BaseResponse.error(AppErrorCode.PARAMS_ERROR)));

return;

}

filterChain.doFilter(xssRequest, servletResponse);

}

// 获取request请求body中参数

public static String getBodyString(BufferedReader br) {

String inputLine;

String str = "";

try {

while ((inputLine = br.readLine()) != null) {

str += inputLine;

}

br.close();

} catch (IOException e) {

System.out.println("IOException: " + e);

}

return str;

}

@Override

public void destroy() {

// no destroy operation

}

}

以上是 springboot经验之sql注入、xss注入拦截(POST) 的全部内容, 来源链接: utcz.com/z/513287.html

回到顶部