3

Two Tricks Of CAS-CLIENT AUTH Bypass

 2 years ago
source link: https://xz.aliyun.com/t/9557
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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;
    }

}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK