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

简介

sql注入、xss注入、cors攻击的简介以及解决方案,可以参考下面链接: https://blog.csdn.net/yhhyhhyhhyhh/article/details/84504487 这里我就不做的的介绍了,解决sql注入根本方案在于使用预编译而不是拼接sql, 而通常拦截参数都只有针对GET方法,下面介绍下POST方法

POST防注入方案

1、增加httprequest包装类

1import java.io.BufferedReader; 2import java.io.ByteArrayInputStream; 3import java.io.IOException; 4import java.io.InputStreamReader; 5import java.util.*; 6import java.util.regex.Pattern; 7 8import javax.servlet.ReadListener; 9import javax.servlet.ServletInputStream; 10import javax.servlet.http.HttpServletRequest; 11import javax.servlet.http.HttpServletRequestWrapper; 12 13import lombok.extern.slf4j.Slf4j; 14import org.apache.commons.lang3.StringUtils; 15import org.springframework.util.StreamUtils; 16 17@Slf4j 18public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper { 19 private static String key = "and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+"; 20 private static Set<string> notAllowedKeyWords = new HashSet<string>(0); 21 static { 22 String keyStr[] = key.split("\\|"); 23 for (String str : keyStr) { 24 notAllowedKeyWords.add(str); 25 } 26 } 27 HttpServletRequest orgRequest = null; 28 private Map<string, string[]> parameterMap; 29 private final byte[] body; //用于保存读取body中数据 30 31 public XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) throws IOException{ 32 super(request); 33 orgRequest = request; 34 parameterMap = request.getParameterMap(); 35 body = StreamUtils.copyToByteArray(request.getInputStream()); 36 } 37 38 // 重写几个HttpServletRequestWrapper中的方法 39 /** 40 * 获取所有参数名 41 * 42 * @return 返回所有参数名 43 */ 44 @Override 45 public Enumeration<string> getParameterNames() { 46 Vector<string> vector = new Vector<string>(parameterMap.keySet()); 47 return vector.elements(); 48 } 49 50 /** 51 * 覆盖getParameter方法,将参数名和参数值都做xss &amp; sql过滤。<br> 52 * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取<br> 53 * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖 54 */ 55 @Override 56 public String getParameter(String name) { 57 String[] results = parameterMap.get(name); 58 if (results == null || results.length &lt;= 0) 59 return null; 60 else { 61 String value = results[0]; 62 if (value != null) { 63 value = xssEncode(value); 64 } 65 return value; 66 } 67 } 68 69 /** 70 * 获取指定参数名的所有值的数组,如:checkbox的所有数据 接收数组变量 ,如checkobx类型 71 */ 72 @Override 73 public String[] getParameterValues(String name) { 74 String[] results = parameterMap.get(name); 75 if (results == null || results.length &lt;= 0) 76 return null; 77 else { 78 int length = results.length; 79 for (int i = 0; i &lt; length; i++) { 80 results[i] = xssEncode(results[i]); 81 } 82 return results; 83 } 84 } 85 86 /** 87 * 覆盖getHeader方法,将参数名和参数值都做xss &amp; sql过滤。<br> 88 * 如果需要获得原始的值,则通过super.getHeaders(name)来获取<br> 89 * getHeaderNames 也可能需要覆盖 90 */ 91 @Override 92 public String getHeader(String name) { 93 94 String value = super.getHeader(xssEncode(name)); 95 if (value != null) { 96 value = xssEncode(value); 97 } 98 return value; 99 } 100 101 /** 102 * 将容易引起xss &amp; sql漏洞的半角字符直接替换成全角字符 103 * 104 * @param s 105 * @return 106 */ 107 private static String xssEncode(String s) { 108 if (s == null || s.isEmpty()) { 109 return s; 110 } else { 111 s = stripXSSAndSql(s); 112 } 113 StringBuilder sb = new StringBuilder(s.length() + 16); 114 for (int i = 0; i &lt; s.length(); i++) { 115 char c = s.charAt(i); 116 switch (c) { 117 case '&gt;': 118 sb.append(">");// 转义大于号 119 break; 120 case '&lt;': 121 sb.append("<");// 转义小于号 122 break; 123 // case '\'': 124 // sb.append("'");// 转义单引号 125 // break; 126 // case '\"': 127 // sb.append(""");// 转义双引号 128 // break; 129 case '&amp;': 130 sb.append("&");// 转义&amp; 131 break; 132 case '#': 133 sb.append("#");// 转义# 134 break; 135 default: 136 sb.append(c); 137 break; 138 } 139 } 140 return sb.toString(); 141 } 142 143 /** 144 * 获取最原始的request 145 * 146 * @return 147 */ 148 public HttpServletRequest getOrgRequest() { 149 return orgRequest; 150 } 151 152 /** 153 * 获取最原始的request的静态方法 154 * 155 * @return 156 */ 157 public static HttpServletRequest getOrgRequest(HttpServletRequest req) { 158 if (req instanceof XssAndSqlHttpServletRequestWrapper) { 159 return ((XssAndSqlHttpServletRequestWrapper) req).getOrgRequest(); 160 } 161 162 return req; 163 } 164 165 /** 166 * 167 * 防止xss跨脚本攻击(替换,根据实际情况调整) 168 */ 169 170 public static String stripXSSAndSql(String value) { 171 if (value != null) { 172 // NOTE: It's highly recommended to use the ESAPI library and 173 // uncomment the following line to 174 // avoid encoded attacks. 175 // value = ESAPI.encoder().canonicalize(value); 176 // Avoid null characters 177 /** value = value.replaceAll("", ""); ***/ 178 // Avoid anything between script tags 179 Pattern scriptPattern = Pattern.compile( 180 "&lt;[\r\n| | ]*script[\r\n| | ]*&gt;(.*?)<!--[\r\n| | ]*script[\r\n| | ]*-->", Pattern.CASE_INSENSITIVE); 181 value = scriptPattern.matcher(value).replaceAll(""); 182 // Avoid anything in a 183 // src="http://www.yihaomen.com/article/java/..." type of 184 // e-xpression 185 scriptPattern = Pattern.compile("src[\r\n| | ]*=[\r\n| | ]*[\\\"|\\\'](.*?)[\\\"|\\\']", 186 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 187 value = scriptPattern.matcher(value).replaceAll(""); 188 // Remove any lonesome tag 189 scriptPattern = Pattern.compile("<!--[\r\n| | ]*script[\r\n| | ]*-->", Pattern.CASE_INSENSITIVE); 190 value = scriptPattern.matcher(value).replaceAll(""); 191 // Remove any lonesome <script ...> tag 192 scriptPattern = Pattern.compile("<[\r\n| | ]*script(.*?)>", 193 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 194 value = scriptPattern.matcher(value).replaceAll(""); 195 // Avoid eval(...) expressions 196 scriptPattern = Pattern.compile("eval\\((.*?)\\)", 197 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 198 value = scriptPattern.matcher(value).replaceAll(""); 199 // Avoid e-xpression(...) expressions 200 scriptPattern = Pattern.compile("e-xpression\\((.*?)\\)", 201 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 202 value = scriptPattern.matcher(value).replaceAll(""); 203 // Avoid javascript:... expressions 204 scriptPattern = Pattern.compile("javascript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE); 205 value = scriptPattern.matcher(value).replaceAll(""); 206 // Avoid vbscript:... expressions 207 scriptPattern = Pattern.compile("vbscript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE); 208 value = scriptPattern.matcher(value).replaceAll(""); 209 // Avoid onload= expressions 210 scriptPattern = Pattern.compile("onload(.*?)=", 211 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 212 value = scriptPattern.matcher(value).replaceAll(""); 213 } 214 return value; 215 } 216 217 public boolean checkXSSAndSql(String value) { 218 boolean flag = false; 219 if (value != null) { 220 // NOTE: It's highly recommended to use the ESAPI library and 221 // uncomment the following line to 222 // avoid encoded attacks. 223 // value = ESAPI.encoder().canonicalize(value); 224 // Avoid null characters 225 /** value = value.replaceAll("", ""); ***/ 226 // Avoid anything between script tags 227 Pattern scriptPattern = Pattern.compile( 228 "<[\r\n| | ]*script[\r\n| | ]*>(.*?)</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE); 229 flag = scriptPattern.matcher(value).find(); 230 if (flag) { 231 return flag; 232 } 233 // Avoid anything in a 234 // src="http://www.yihaomen.com/article/java/..." type of 235 // e-xpression 236 scriptPattern = Pattern.compile("src[\r\n| | ]*=[\r\n| | ]*[\\\"|\\\'](.*?)[\\\"|\\\']", 237 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 238 flag = scriptPattern.matcher(value).find(); 239 if (flag) { 240 return flag; 241 } 242 // Remove any lonesome </script> tag 243 scriptPattern = Pattern.compile("<!--[\r\n| | ]*script[\r\n| | ]*-->", Pattern.CASE_INSENSITIVE); 244 flag = scriptPattern.matcher(value).find(); 245 if (flag) { 246 return flag; 247 } 248 // Remove any lonesome <script ...> tag 249 scriptPattern = Pattern.compile("<[\r\n| | ]*script(.*?)>", 250 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 251 flag = scriptPattern.matcher(value).find(); 252 if (flag) { 253 return flag; 254 } 255 // Avoid eval(...) expressions 256 scriptPattern = Pattern.compile("eval\\((.*?)\\)", 257 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 258 flag = scriptPattern.matcher(value).find(); 259 if (flag) { 260 return flag; 261 } 262 // Avoid e-xpression(...) expressions 263 scriptPattern = Pattern.compile("e-xpression\\((.*?)\\)", 264 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 265 flag = scriptPattern.matcher(value).find(); 266 if (flag) { 267 return flag; 268 } 269 // Avoid javascript:... expressions 270 scriptPattern = Pattern.compile("javascript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE); 271 flag = scriptPattern.matcher(value).find(); 272 if (flag) { 273 return flag; 274 } 275 // Avoid vbscript:... expressions 276 scriptPattern = Pattern.compile("vbscript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE); 277 flag = scriptPattern.matcher(value).find(); 278 if (flag) { 279 return flag; 280 } 281 // Avoid onload= expressions 282 scriptPattern = Pattern.compile("onload(.*?)=", 283 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 284 flag = scriptPattern.matcher(value).find(); 285 if (flag) { 286 return flag; 287 } 288 289 flag=checkSqlKeyWords(value); 290 } 291 return flag; 292 } 293 294 public boolean checkSqlKeyWords(String value){ 295 String paramValue = value; 296 for (String keyword : notAllowedKeyWords) { 297 if (paramValue.length() > keyword.length() + 4 298 && (paramValue.contains(" "+keyword)||paramValue.contains(keyword+" ")||paramValue.contains(" "+keyword+" "))) { 299 log.error(this.getRequestURI()+ "参数中包含不允许sql的关键词(" + keyword 300 + ")"); 301 return true; 302 } 303 } 304 return false; 305 } 306 307 public final boolean checkParameter() { 308 Map<String, String[]> submitParams = new HashMap(parameterMap); 309 Set<String> submitNames = submitParams.keySet(); 310 for (String submitName : submitNames) { 311 Object submitValues = submitParams.get(submitName); 312 if ((submitValues instanceof String)) { 313 if (checkXSSAndSql((String) submitValues)) { 314 return true; 315 } 316 } else if ((submitValues instanceof String[])) { 317 for (String submitValue : (String[])submitValues){ 318 if (checkXSSAndSql(submitValue)) { 319 return true; 320 } 321 } 322 } 323 } 324 return false; 325 } 326 327 @Override 328 public BufferedReader getReader() throws IOException { 329 return new BufferedReader(new InputStreamReader(getInputStream())); 330 } 331 332 @Override 333 public ServletInputStream getInputStream() throws IOException { 334 final ByteArrayInputStream bais = new ByteArrayInputStream(body); 335 return new ServletInputStream() { 336 337 @Override 338 public int read() throws IOException { 339 return bais.read(); 340 } 341 342 @Override 343 public boolean isFinished() { 344 // TODO Auto-generated method stub 345 return false; 346 } 347 348 @Override 349 public boolean isReady() { 350 // TODO Auto-generated method stub 351 return false; 352 } 353 354 @Override 355 public void setReadListener(ReadListener arg0) { 356 // TODO Auto-generated method stub 357 358 } 359 }; 360 } 361 362}

2、增加过滤器

1import java.io.BufferedReader; 2import java.io.IOException; 3import java.io.PrintWriter; 4import java.util.UUID; 5 6import javax.servlet.DispatcherType; 7import javax.servlet.Filter; 8import javax.servlet.FilterChain; 9import javax.servlet.FilterConfig; 10import javax.servlet.ServletException; 11import javax.servlet.ServletRequest; 12import javax.servlet.ServletResponse; 13import javax.servlet.annotation.WebFilter; 14import javax.servlet.http.HttpServletRequest; 15import javax.servlet.http.HttpServletResponse; 16 17import com.alibaba.fastjson.JSON; 18import com.code.base.BaseResponse; 19import org.apache.commons.lang3.StringUtils; 20import org.springframework.beans.factory.annotation.Autowired; 21 22import lombok.extern.slf4j.Slf4j; 23 24@Slf4j 25@WebFilter( 26 filterName = "xssFilter", 27 urlPatterns = "/*", 28 dispatcherTypes = DispatcherType.REQUEST 29) 30public class XssFilter implements Filter { 31 32 @Override 33 public void init(FilterConfig filterConfig) { 34 // no init operation 35 } 36 37 @Override 38 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, 39 FilterChain filterChain) throws IOException, ServletException { 40 HttpServletRequest request = (HttpServletRequest) servletRequest; 41 XssAndSqlHttpServletRequestWrapper xssRequest=new XssAndSqlHttpServletRequestWrapper( 42 request); 43 String method = ((HttpServletRequest) request).getMethod(); 44 String param = ""; 45 if ("POST".equalsIgnoreCase(method)) { 46 param = this.getBodyString(xssRequest.getReader()); 47 if(StringUtils.isNotBlank(param)){ 48 if(xssRequest.checkXSSAndSql(param)){ 49 servletResponse.setCharacterEncoding("UTF-8"); 50 servletResponse.setContentType("application/json;charset=UTF-8"); 51 PrintWriter out = servletResponse.getWriter(); 52 out.write(JSON.toJSONString(BaseResponse.error(AppErrorCode.PARAMS_ERROR))); 53 return; 54 } 55 } 56 } 57 if (xssRequest.checkParameter()) { 58 servletResponse.setCharacterEncoding("UTF-8"); 59 servletResponse.setContentType("application/json;charset=UTF-8"); 60 PrintWriter out = servletResponse.getWriter(); 61 out.write(JSON.toJSONString(BaseResponse.error(AppErrorCode.PARAMS_ERROR))); 62 return; 63 } 64 filterChain.doFilter(xssRequest, servletResponse); 65 66 67 } 68 69 // 获取request请求body中参数 70 public static String getBodyString(BufferedReader br) { 71 String inputLine; 72 String str = ""; 73 try { 74 while ((inputLine = br.readLine()) != null) { 75 str += inputLine; 76 } 77 br.close(); 78 } catch (IOException e) { 79 System.out.println("IOException: " + e); 80 } 81 return str; 82 83 } 84 85 @Override 86 public void destroy() { 87 // no destroy operation 88 } 89}
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

sql注入

反引号是个比较特别的字符,下面记录下怎么利用0x00SQL注入反引号可利用在分隔符及注释作用,不过使用范围只于表名、数据库名、字段名、起别名这些场景,下面具体说下1)表名payload:select\from\users\whereuser\_id1limit0,1;!(https://o