java-sec-code中重定向

重定向
状态码3xx
存在问题的代码段

@GetMapping("/redirect")
public String redirect(@RequestParam("url") String url) {
    return "redirect:" + url;
}

用户访问/redirect路径时,redirect方法会获取web请求中的url参数内容,并使用springboot中的redirect控制器,重定向到用户想要前往的界面

复现

http://127.0.0.1:8080/urlRedirect/redirect?url=http://www.baidu.com

网站会直接打开百度界面,burpsuite中则为302重定向状态码
java-sec-code中重定向_第1张图片

@RequestMapping("/setHeader")
@ResponseBody
public static void setHeader(HttpServletRequest request, HttpServletResponse response) {
    String url = request.getParameter("url");
    response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); // 301 redirect
    response.setHeader("Location", url);
}

访问/setHeader路由时,服务端会接受url参数内容,设置网站响应状态码为301,并将网站相应的Location头(用于指向重定向的目标url)设置为url内容,并且没有任何过滤

复现

http://localhost:8080/urlRedirect/setHeader?url=http://www.baidu.com

网站显示为baidu界面,burpsuite显示的内容为301状态码
java-sec-code中重定向_第2张图片

@RequestMapping("/sendRedirect")
@ResponseBody
public static void sendRedirect(HttpServletRequest request, HttpServletResponse response) throws IOException {
    String url = request.getParameter("url");
    response.sendRedirect(url);
}

代码段采用Java Servlet API中的redirect方法,用于将HTTP请求重定向到指定的URL(302)。

复现

http://127.0.0.11:8080/urlRedirect/sendRedirect?url=http://www.baidu.com

网站显示为百度界面,burpsuite显示的内容为302状态码
java-sec-code中重定向_第3张图片
安全的代码写法

@RequestMapping("/forward")
@ResponseBody
public static void forward(HttpServletRequest request, HttpServletResponse response) {
    String url = request.getParameter("url");
    RequestDispatcher rd = request.getRequestDispatcher(url);
    try {
        rd.forward(request, response);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

从用户请求中获取url参数内容,设置RequestDispatcher对象,将用户的请求发送到url地址中,调用forward方法将请求和响应对象转发到url中,由于RequestDispatcher是用来在服务器端进行请求的内部处理和转发,所以只能在同源网站内进行跳转,无法跳转到外部网站
复现

http://127.0.0.1:8080/urlRedirect/forward?url=/urlRedirect/redirect

burpsuite中请求包,首先有一个重定向的数据包,然后请求重定向后的路由
java-sec-code中重定向_第4张图片
java-sec-code中重定向_第5张图片
如果是外部网站,状态码为200,路由,界面显示均无变化,并且idea中会显示请求转发到错误页面时出现了问题。

java-sec-code中重定向_第6张图片

@RequestMapping("/sendRedirect/sec")
@ResponseBody
public void sendRedirect_seccode(HttpServletRequest request, HttpServletResponse response)
        throws IOException {
    String url = request.getParameter("url");
    if (SecurityUtil.checkURL(url) == null) {
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        response.getWriter().write("url forbidden");
        return;
    }
    response.sendRedirect(url);
}

}

接受url参数,使用check方法过滤,白名单黑名单位置在url/url_safe_domain.xml

<safedomains>//白名单
    <!-- 支持一级域名或多级域名 -->
    <domain>joychou.com</domain>
    <domain>joychou.org</domain>
    <domain>test.joychou.org</domain>
    <domain>localhost</domain>
</safedomains>

<!-- 支持一级域名或多级域名 -->
<blockdomains>//黑名单名单
    <domain>baidu.com</domain>
    <domain>evil.joychou.org</domain>
</blockdomains>

check方法,假设传入的参数为http://test.joychou.org

public static String checkURL(String url) {

    if (null == url){ //检测是否为空
        return null;
    }
       //读取文件中的黑白名单
    ArrayList safeDomains = WebConfig.getSafeDomains();//白名单
    ArrayList blockDomains = WebConfig.getBlockDomains();//黑名单

    try {
        String host = gethost(url);//test.joychou.org 获取host值

        // 检测是否为http/https
        if (!isHttp(url)) {
            return null;
        }

        // 如果满足黑名单返回null   将host与黑名单中进行比对,有则null
        if (blockDomains.contains(host)){
            return null;
        }
      //检测host属性值是否有黑名单后缀,用于去除黑名单域名与其子域名
        for(String blockDomain: blockDomains) {
            if(host.endsWith("." + blockDomain)) {
                return null;
            }
        }

        // 支持一级域名 白名单
        if (safeDomains.contains(host)){
            return url;
        }

        // 支持多级域名  白名单
        for(String safedomain: safeDomains) {
            if(host.endsWith("." + safedomain)) {
                return url;
            }
        }
        return null;
    } catch (NullPointerException e) {
        logger.error(e.toString());
        return null;
    }
}

当用户传入的为白名单的网址则进行跳转,否则输出url forbidden

你可能感兴趣的:(java)