记一次解决CSRF的坑

た 入场券 2023-05-30 06:18 85阅读 0赞

漏洞扫描,需要解决csrf问题,先贴上代码,使用的是过滤器

  1. package com.jdd.appim.web.filter;
  2. import com.alibaba.fastjson.JSONObject;
  3. import org.apache.commons.lang3.StringUtils;
  4. import org.slf4j.Logger;
  5. import org.slf4j.LoggerFactory;
  6. import org.springframework.util.CollectionUtils;
  7. import javax.servlet.*;
  8. import javax.servlet.http.HttpServletRequest;
  9. import java.io.IOException;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. import java.util.Properties;
  13. /**
  14. * @author dataochen
  15. * @Description 拦截请求 防止CSRF漏洞
  16. * @date: 2019/9/6 14:26
  17. */
  18. public class CsrfCheckFilter implements Filter {
  19. private static final Logger LOGGER = LoggerFactory.getLogger(CsrfCheckFilter.class);
  20. public CsrfCheckFilter(List<String> whiteHost) {
  21. this.whiteHost = whiteHost;
  22. }
  23. public CsrfCheckFilter() {
  24. }
  25. /**
  26. * 域名白名单
  27. * 无需校验的
  28. */
  29. private List<String> whiteHost = new ArrayList<String>();
  30. @Override
  31. public void init(FilterConfig filterConfig) throws ServletException {
  32. LOGGER.info("####CsrfCheckFilter init");
  33. // 把单点登录的加进白名单
  34. try {
  35. Properties props = new Properties();
  36. props.load(CsrfCheckFilter.class.getResourceAsStream("/sso-client.properties"));
  37. String property = props.getProperty("sso.server.host");
  38. whiteHost.add(property);
  39. LOGGER.info("###whiteHost=[{}]", JSONObject.toJSONString(whiteHost));
  40. } catch (Exception e) {
  41. LOGGER.error("###CsrfCheckFilter put sso host into white host exception,e={}", e);
  42. }
  43. }
  44. @Override
  45. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  46. HttpServletRequest req = (HttpServletRequest) servletRequest;
  47. String referer = req.getHeader("Referer");
  48. String serverName = req.getServerName();
  49. String scheme = req.getScheme();
  50. LOGGER.debug("###CsrfCheckFilter doFilter referer={},serverName={}", referer, serverName);
  51. LOGGER.debug("###CsrfCheckFilter doFilter scheme={}", scheme);
  52. if (StringUtils.isNotBlank(referer)) {
  53. // 判断是否是域名白名单中的域名
  54. LOGGER.debug("###CsrfCheckFilter doFilter whiteHost={}", JSONObject.toJSONString(whiteHost));
  55. if (!CollectionUtils.isEmpty(whiteHost)) {
  56. for (String host : whiteHost) {
  57. if (host.startsWith("http")) {
  58. if (referer.startsWith(host)) {
  59. filterChain.doFilter(servletRequest, servletResponse);
  60. return;
  61. }
  62. } else {
  63. if (referer.startsWith("http://" + host) || referer.startsWith("https://" + host)) {
  64. filterChain.doFilter(servletRequest, servletResponse);
  65. return;
  66. }
  67. }
  68. }
  69. }
  70. // 判断是否是本系统的域名
  71. if (!referer.startsWith(scheme + "://" + serverName)) {
  72. throw new ServletException("System identified as cross-site request forgery, access denied");
  73. }
  74. }
  75. filterChain.doFilter(servletRequest, servletResponse);
  76. return;
  77. }
  78. @Override
  79. public void destroy() {
  80. }
  81. }

本来这个过滤器没什么问题,后来项目改成了HTTPS访问应用,一直报静态资源找不到。后来经过排查,发现是这个过滤器的问题。在这个应用的上面有一层nginx反向代理,https请求到nginx后,nginx在转发时候,转发的是http,同时转发的响应头里面,多了一个refer,这个refer是https。因此问题就来了,在这个filter代码中,refer=https,scheme=http,因此代码执行到

  1. if (!referer.startsWith(scheme + "://" + serverName)) 方法里面,扔出了一个servlet异常

发表评论

表情:
评论列表 (有 0 条评论,85人围观)

还没有评论,来说两句吧...

相关阅读

    相关 使用Cobar踩到

    起因 起因是因为日志里经常报出锁等待超时的错误,并且这个是环环相扣的,一个锁等待会直接引发另外的锁等待,所以危害非常严重,影响非常深远。寻找原因发现是`C3P0`报出了`