Two Tricks Of CAS-CLIENT AUTH Bypass
2021-05-24 10:51:17 Author: xz.aliyun.com(查看原文) 阅读量:156 收藏

cas client 用于限制匿名用户对某些特定api的访问,在一些特殊的环境下可能会有权限绕过问题。下面分享两个实际生活中遇到的案例。

bypass trick1 ignorePattern

场景

/api/admin这个url是需要cas登陆才能访问的。

package today.redteam.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AdminController {

    @RequestMapping("/api/admin")
    public String admin(){
        return "hello admin";
    }

}

/api/guest这个是公共页面,所有人都可以看。

package today.redteam.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GuestController {

    @RequestMapping("/api/guest")
    public String guest(){
        return "hello guest";
    }

}

假设此程序的技术比较老旧,为了实现上面这种需求,那么开发可能会在web.xml中这么配置。

<filter>
        <filter-name>CAS Authentication Filter</filter-name>
        <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
        <init-param>
            <param-name>casServerUrlPrefix</param-name>
            <param-value>https://battags.ad.ess.rutgers.edu:8443/cas</param-value>
        </init-param>
        <init-param>
            <param-name>serverName</param-name>
            <param-value>http://www.acme-client.com</param-value>
        </init-param>
        <init-param>
            <param-name>ignorePattern</param-name>
            <param-value>/api/guest</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CAS Authentication Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

这样配置看起来似乎没有问题

利用

但是其实可以被花式绕过。

原理

原因有两点,第一org.jasig.cas.client.authentication.AuthenticationFilter,在匹配时候获取了原生url(未处理../),甚至包括? 后的内容。

第二,filter的匹配模式有四种,默认是按正则匹配。

同理如果配置成CONTAINS也会有类似的问题。

同理封装了这个库的三方库也会有问题,比较流行的是cas-client-autoconfig-support ,它常与springboot集成使用,如果有如下配置也会出问题。

cas.ignorePattern=/api/guest

修复

所以正确的配置应该改为

<init-param>
  <param-name>ignorePattern</param-name>
  <param-value>^/api/guest$</param-value>
</init-param>

个人认为这个可以算洞(没处理../而且contains这种选项就不应该存在),也可以甩锅给开发没仔细看文档。

bypass trick2 useSuffixPatternMatch

场景

这里假设/admin系列的路由都不允许访问。

package today.redteam.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AdminController {

    @RequestMapping(
            value = {"/admin"},
            method = {RequestMethod.GET}
    )
    public String admin(){
        return "hello admin";
    }

    @RequestMapping(
            value = {"/admin/api"},
            method = {RequestMethod.GET}
    )
    public String admin1(){
        return "hello admin1";
    }

}

这一次开发认真看了文档做了以下配置。

package today.redteam.config;

import net.unicon.cas.client.configuration.CasClientConfigurerAdapter;
import net.unicon.cas.client.configuration.EnableCasClient;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Configuration;
import today.redteam.aop.CasAspect;

@Configuration
@EnableCasClient
public class CasConfig extends CasClientConfigurerAdapter {
    public CasConfig() {
    }

    public void configureAuthenticationFilter(FilterRegistrationBean authenticationFilter) {
        super.configureAuthenticationFilter(authenticationFilter);
        authenticationFilter.addUrlPatterns(new String[]{"/admin/*"});
    }

    static {
        System.setProperty("cas.serverUrlPrefix", "https://cashost.com/cas");
        System.setProperty("cas.serverLoginUrl", "https://cashost.com/cas/login");
        System.setProperty("cas.clientHostUrl", "http://localhost:8888/");
        System.setProperty("cas.validationType", "CAS");
    }
}

/admin这个路由看起来似乎也没有什么问题。

常规的绕过方式也不起作用

利用

但在低版本的springboot上还是能绕过(本地环境是1.5.9.RELEASE)。

原理

原理是在springboot 1.x中useSuffixPatternMatch默认为true,springboot会对路由进行正则匹配。

断点下在org.springframework.web.servlet.mvc.condition.PatternsRequestCondition#getMatchingPattern。

/admin.*自然能匹配上/admin.也就绕过了。

修复

如下关闭setUseSuffixPatternMatch或升级到2.x

package today.redteam.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

@Configuration
@ComponentScan
@EnableWebMvc
public class AppConfig {

    @Bean
    public HandlerMapping requestMappingHandlerMapping() {
        RequestMappingHandlerMapping mapping = new RequestMappingHandlerMapping();
        mapping.setUseSuffixPatternMatch(false);
        return mapping;
    }

}

文章来源: http://xz.aliyun.com/t/9557
如有侵权请联系:admin#unsafe.sh