【问题标题】:HttpServletRequest, csrf check for referrer headerHttpServletRequest, csrf 检查referrer header
【发布时间】:2018-07-10 21:17:09
【问题描述】:

我需要添加一个检查以查看域是否与引用者匹配,并且对于 csrf 概念和 servlet 来说是全新的。我想知道是否有办法验证推荐人是否存在

如果referrer 标头不是https://[samedomain]/abc/sso?module=console,则失败。请注意,这里的检查应该非常严格。不能只用“/abc/sso?module=console”比较ends,因为它可以被https://attacker.com/abc/sso?module=consolehttps://[samedomain].attacker.com/abc/sso?module=console绕过 如果没有失败,继续

我正在寻找关于代码的正确验证,例如可能还需要比较端口和服务器名称。我不是在寻找过于复杂的东西 我已经走到这一步了,

    String refererHeader = request.getHeader("referer");
    final String PATH = '/abc/sso?module=console',
    String host = request.getServerName();
    int port = request.getServerPort();

    String portstr="";
    if(port!=80 || port!= 443){
      portstr=":"+port;
    }

    if (refererHeader == null) {
        response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
        return;
    }

    if (refererHeader != null &&  host!== null) {
     //check if port is not the default ports, in that case construct the url 

     //append with PATH and compare if the referrer header and this matches 

    }

任何帮助将不胜感激

【问题讨论】:

  • 让我们知道您遇到的问题 - 您可能希望以 servlet filtertake a look 开头,以帮助您入门。
  • @stdunbar 谢谢,如果服务器名称和端口匹配,然后请求通过,我正在寻找一些非常简单的东西来比较,请参阅上面我到目前为止的内容,可能这需要一个正则表达式也是?

标签: servlets httprequest csrf


【解决方案1】:

这实际上比我想象的要难一些,所以我想我会分享我的想法。代码可以优化——if 语句太多,但看起来你来自不同的语言,所以我试着让它相当直截了当。此外,我可能遗漏了一些错误情况,但应该很接近。

import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

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;

@WebFilter
public class RefererFilter implements Filter {
    private static final String PATH = "/abc/sso?module=console";
    // the domains that you will accept a referrer from
    private static final List<String> acceptableDomains = Arrays.asList("google.com", "mydomain.com");

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // unused in this application
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        String refererHeader = request.getHeader("referer");
        // no need to continue if the header is missing
        if (refererHeader == null) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            return;
        }

        // parse the given referrer
        URL refererURL = new URL(refererHeader);
        // split the host name by the '.' character (but quote that as it is a regex special char)
        String[] hostParts = refererURL.getHost().split(Pattern.quote("."));

        if (hostParts.length == 1) { // then we have something like "localhost"
            if (!acceptableDomains.contains(hostParts[0])) {
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                return;
            }
        } else if (hostParts.length >= 2) { // handle domain.tld, www.domain.tld, and net1.net2.domain.tld
            if (!acceptableDomains.contains(hostParts[hostParts.length - 2] + "." + hostParts[hostParts.length - 1])) {
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                return;
            }
        }
        // if we've gotten this far then the domain is ok, how about the path and query?
        if( !(refererURL.getPath() + "?" + refererURL.getQuery()).equals(PATH) ) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            return;
        }
        // all tests pass - continue filter chain
        filterChain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // unused in this implementation
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-21
    • 1970-01-01
    • 1970-01-01
    • 2018-07-11
    • 2010-09-19
    • 1970-01-01
    相关资源
    最近更新 更多