erupt框架-黑盒测试手工安全渗透漏洞-修改流程
1. 漏洞名称:未加密的通道
在项目中使用https证书
2. 漏洞名称:Referer头未校验、跨域漏洞、Host头攻击
使用spring Security的某些注解可以解决(公司封装了,我这里只有思路)
3. 漏洞名称:Host头攻击
Host头攻击解决方法,编写拦截器,拦截所有请求,放行host符合要求的
package com.example.demo.action;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "hostFilter", urlPatterns = "/*")
public class HostFilter implements Filter {
private static final String[] allowedHosts = {"127.0.0.1:8080"};//换成你的ip
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
String hostHeader = httpServletRequest.getHeader("Host");
boolean hostAllowed = false;
for (String allowedHost : allowedHosts) {
if (allowedHost.equals(hostHeader)) {
hostAllowed = true;
break;
}
}
if (hostAllowed) {
chain.doFilter(request, response);
} else {
httpServletResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Host is not allowed");
}
}
}
记得在Appliction启动类上加@ServletComponentScan注解,扫描fiflter配置类
4. 漏洞名称:用户名传输过程未加密
在安全测试中登录的传参:账号密码都需要去加密,如果使用的是erupt框架,就需要自定义登录界面和自定义登录流程来解决这个问题。
5 漏洞名称:多地登录
测试反馈漏洞描述:在同一端登录(PC),不同的浏览器登录相同的账号需要顶掉另一个账号的会话。
解决方法:使用sa-tokenSa-Token
在登录成功后加一行代码
StpUtil.login("本次登录的账号ID", "PC");
然后根据官网文档全局过滤器 (sa-token.cc)设置全局过滤器,并在没登录的状态中返回401状态码(erupt会识别401状态码自动返回登录页面)
// 异常处理函数:每次认证函数发生异常时执行此函数
.setError(e -> {
System.out.println("---------- 进入Sa-Token异常处理 -----------");
System.out.println(e.getMessage());
System.out.println(e);
testLoginProxy.logout(eruptContextService.getCurrentToken());
//对话框方式提示
// throw new EruptApiErrorTip("其他浏览器登录,请右上角退出");
SaHolder.getResponse().setStatus(401);
return SaResult.error("未登录或会话已过期,请重新登录");
})
6. 漏洞名称:敏感信息泄露-应用程序错误消息、敏感信息泄露-暴露执行SQL等
正常项目写一个全局异常处理类就可以将报错信息返回指定文字,异常处理类如下
package com.example.demo.action;
import com.mysql.cj.jdbc.exceptions.MysqlDataTruncation;
import org.apache.commons.lang.math.RandomUtils;
import org.hibernate.HibernateException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import xyz.erupt.core.exception.EruptApiErrorTip;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Pattern EXCEPTION_PATTERN = Pattern.compile(".*Exception:");
@ExceptionHandler(InvalidDataAccessApiUsageException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public String handleInvalidDataAccessApiUsageException(InvalidDataAccessApiUsageException ex) {
return "发生了错误,!";
}
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ResponseEntity<String> handleRuntimeException(RuntimeException ex, WebRequest request) {
return new ResponseEntity<>("报错了", HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler(EruptApiErrorTip.class)
public ResponseEntity<String> handleEruptApiErrorTip(EruptApiErrorTip ex, WebRequest request) {
// 返回自定义的错误提示信息
return new ResponseEntity<>("报错了", HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler(NoHandlerFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public ResponseEntity<String> handleNoHandlerFoundException(NoHandlerFoundException ex, WebRequest request) {
return new ResponseEntity<>("报错了", HttpStatus.NOT_FOUND);
}
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
public ResponseEntity<String> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException ex, WebRequest request) {
return new ResponseEntity<>("报错了", HttpStatus.METHOD_NOT_ALLOWED);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseEntity<String> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, WebRequest request) {
return new ResponseEntity<>("报错了", HttpStatus.BAD_REQUEST);
}
}
注意 erupt框架使用了hibernate,405状态码可以在异常处理类中正确处理,但500状态码的hibernate异常却无法触发异常处理类
这是因为hibernate已经处理了,所以走不到spring中
解决方法:写一个spring aop切面,扫描所有包,你不需要去处理返回值,只需要把异常在切面中取出来,全局异常处理类就可以识别,返回你设置的返回值。
package com.example.demo.action;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import xyz.erupt.core.view.EruptExceptionVo;
@Aspect
@Component
public class ResponseModifierAspect {
// 定义切点,匹配所有Controller的方法
@AfterReturning(pointcut = "execution(* com.example..*.*.*(..))", returning = "response")
public void afterReturningAdvice(Object response) {
System.out.println(response);
if (response instanceof EruptExceptionVo){
System.out.println(response);
HttpStatus status = ((ResponseEntity<?>) response).getStatusCode();
}
}
}