springboot 防请求过程sql盲注-请求body加密
背景
博主好不容易熬到了项目终于把bug修改完毕,开始迎来了项目的安全测试和性能测试以及疲劳测试。于是就先做了安全测试,公司的安全测试目前是由软件完成的叫:Appscan 以及monkey(是开发的app)完成。扫描之后发现出现了十多个sql盲注问题。看到这问题内心是凉凉的,因为上一次扫描出了几十个盲注问题,让我改了很多代码。百度之后统一采用mybatis的#{}可以解决大部分盲注问题。因为我们项目业务比较复杂,所以里面有直接的jdbc操作,所以导致了第一次扫描盲注问题较多。回归主题,这次我们领导下定决心我们要从根源上解决问题,所以我们采用请求头加密实现。这一文章主要讲解如何对Java请求的@requestBody前端加密后端解密。为了方便所以我采用的最简单的base64加解密作为讲解。直接上干货。
技术讲解
Spring中处理JSON请求使用@RequestBody和@ResponseBody注解,针对JSON请求加解密和过滤字符串,Spring提供了RequestBodyAdvice和ResponseBodyAdvice两个接口。在这我只讲解@RequestBody注解的相关使用
实现RequestBodyAdvice接口
package com.dengf.rent.interceptor;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;
import java.io.IOException;
import java.lang.reflect.Type;
@ControllerAdvice(basePackages = "com.dengf.rent.controller")
public class MyRequestBodyAdvice implements RequestBodyAdvice {
@Override
public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
try {
return new MyHttpInputMessage(httpInputMessage);
} catch (Exception e) {
e.printStackTrace();
return httpInputMessage;
}
}
@Override
public Object afterBodyRead(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
return o;
}
@Override
public Object handleEmptyBody(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
return o;
}
}
在beforeBodyRead中处理相关
package com.dengf.rent.interceptor;
import com.alibaba.fastjson.JSONObject;
import com.dengf.rent.util.CommonUtil;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import java.io.IOException;
import java.io.InputStream;
public class MyHttpInputMessage implements HttpInputMessage {
private HttpHeaders headers;
private InputStream body;
public MyHttpInputMessage(HttpInputMessage inputMessage) throws Exception {
String data = IOUtils.toString(inputMessage.getBody(), "UTF-8");
JSONObject json = JSONObject.parseObject(data);
if(json.containsKey("data")){
this.body = IOUtils.toInputStream(CommonUtil.decript(json.getString("data")), "UTF-8");
}else{
this.body = IOUtils.toInputStream(data,"UTF-8");
}
}
@Override
public InputStream getBody() throws IOException {
return body;
}
@Override
public HttpHeaders getHeaders() {
return headers;
}
}
base64加解密工具类
package com.dengf.rent.util;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import java.io.IOException;
public class CommonUtil {
public static String decript(String data) throws IOException {
BASE64Decoder decoder = new BASE64Decoder();
byte[] bytes = decoder.decodeBuffer(data);
return new String(bytes);
}
public static String encript(Object data){
BASE64Encoder encoder = new BASE64Encoder();
String res = encoder.encode(data.toString().getBytes());
return res;
}
}
注意
今天因为初心出了一个小问题博主真的是找了好一会儿才找到根节。下面上报错问题:
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Invalid UTF-8 middle byte 0xd0
at [Source: (ByteArrayInputStream); line: 1, column: 146]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Invalid UTF-8 middle byte 0xd0
at [Source: (ByteArrayInputStream); line: 1, column: 146]
at [Source: (ByteArrayInputStream); line: 1, column: 143] (through reference chain: com.yanhua.ydyh.mobilenurse.vo.BaseListVo["LstRow"]->java.util.ArrayList[0]->com.yanhua.ydyh.mobilenurse.vo.patient.EscortsInformationVo["CPHRXB"])
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:241)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:223)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:206)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:157)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:130)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:124)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:131)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:877)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Invalid UTF-8 middle byte 0xd0
at [Source: (ByteArrayInputStream); line: 1, column: 146]
at [Source: (ByteArrayInputStream); line: 1, column: 143] (through reference chain: com.yanhua.ydyh.mobilenurse.vo.BaseListVo["LstRow"]->java.util.ArrayList[0]->com.yanhua.ydyh.mobilenurse.vo.patient.EscortsInformationVo["CPHRXB"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:391))
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3084)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:235)
... 55 common frames omitted
Caused by: com.fasterxml.jackson.core.JsonParseException: Invalid UTF-8 middle byte 0xd0
at [Source: (ByteArrayInputStream); line: 1, column: 146]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1804)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:669)
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidOther(UTF8StreamJsonParser.java:3543)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:369)
... 65 common frames omitted
这问题就是在说:有中文但是没有用utf-8编码,因为spring框架默认的不是用utf-8编码
注意查看代码这两个地方是否使用utf-8编码,都是粗心惹的祸!
嗷呜 再次完成了领导的需求,下班~