框架学习使用收藏spring

Spring的getRequestURI与getRequestU

2021-12-08  本文已影响0人  小胖学编程

我们有时候会在Filter中对某些URL进行权限校验。若使用getRequestURI与getRequestURL方法获取URL,可能会导致权限绕过的风险。

漏洞原理:请求URL中可以填充一些特殊字符,来跳过权限校验。

1. 测试代码

权限验证器代码:

@Slf4j
@Service
public class URIRiskInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        //校验数据
        String requestURI = request.getRequestURI();
        String requestURL = request.getRequestURL().toString();
        String servletPath = request.getServletPath();
        log.info("输出数据requestURI:{}\n,requestURL:{}\n,servletPath:{}\n", requestURI, requestURL, servletPath);
        return true;
    }
}

Controller层代码:

@Slf4j
@RestController
public class FirstController {

    @RequestMapping(value = "/test")
    public String test(@RequestParam("id") Long id, @RequestParam("name") String name) {
        log.info("test,请求进来了");
        return id + "-" + name + " is success";
    }
}

2. 绕过方式

2.1 非标准化绕过

例如/system/login开头的接口是白名单,不需要进行访问控制(登陆页面所有人都可以访问),其他接⼝都需要进⾏登陆检查,防止未授权访问:

@Slf4j
@Service
public class URIRiskInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        //校验数据
        String requestURI = request.getRequestURI();
        String requestURL = request.getRequestURL().toString();
        String servletPath = request.getServletPath();
        log.info("输出数据requestURI:{}\n,requestURL:{}\n,servletPath:{}\n", requestURI, requestURL, servletPath);
        //放行登录请求
        if (requestURI.startsWith("/system/login")) {
            log.info("yes,跳过校验{}", requestURI);
        } else {
            log.info("no,进行校验{}", requestURI);
        }
        return true;
    }
}

执行结果:

2021-12-07 16:13:23.114  INFO 11917 --- [nio-8080-exec-1] c.tellme.Interceptor.URIRiskInterceptor  : 输出数据requestURI:/system/login/../../test
,requestURL:http://localhost:8080/system/login/../../test
,servletPath:/test

2021-12-07 16:13:23.115  INFO 11917 --- [nio-8080-exec-1] c.tellme.Interceptor.URIRiskInterceptor  : yes,跳过校验/system/login/../../test
2021-12-07 16:13:23.127  INFO 11917 --- [nio-8080-exec-1] com.tellme.controller.FirstController    : test,请求进来了

可以看到:当访问http://localhost:8080/system/login/../../test是可以访问到Controller方法的,且跳过了验证。

2.2 URL截断绕过

针对的是String.endsWith()的权限校验。

@Slf4j
@Service
public class URIRiskInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        //校验数据
        String requestURI = request.getRequestURI();
        String requestURL = request.getRequestURL().toString();
        String servletPath = request.getServletPath();
        log.info("输出数据requestURI:{}\n,requestURL:{}\n,servletPath:{}\n", requestURI, requestURL, servletPath);
        //若结尾为.do或者.action的请求进行校验,但是SpringMVC很少有这种后缀的。
        if (requestURI.endsWith("test")) {
            log.info("no,进行校验{}", requestURI);
        } else {
            log.info("yes,跳过校验{}", requestURI);
        }
        return true;
    }
}

测试结果:

2021-12-07 17:03:03.299  INFO 15815 --- [nio-8080-exec-1] c.tellme.Interceptor.URIRiskInterceptor  : 输出数据requestURI:/test;123
,requestURL:http://localhost:8080/test;123
,servletPath:/test

2021-12-07 17:03:03.299  INFO 15815 --- [nio-8080-exec-1] c.tellme.Interceptor.URIRiskInterceptor  : yes,跳过校验/test;123
2021-12-07 17:03:03.314  INFO 15815 --- [nio-8080-exec-1] com.tellme.controller.FirstController    : test,请求进来了

可以看到:当访问http://localhost:8080/test;123是可以访问到Controller方法的,且跳过了验证。

3. 预防措施

推荐阅读

Tomcat URL解析差异性导致的安全问题

filter设计缺陷导致的权限绕过

上一篇 下一篇

猜你喜欢

热点阅读