Skip to main content

Explorando o bypass de autorização do Spring Security (CVE-2022-31692)

Escrito por
feature spring security auth bypass

15 de dezembro de 2022

0 minutos de leitura

No início de novembro, foi encontrada uma nova vulnerabilidade de bypass de autorização no Spring Security 5. Antes de entrar em pânico, vamos analisar o problema para descobrir se você está vulnerável. Embora a vulnerabilidade seja classificada como alta, apenas um conjunto específico de casos de uso está vulnerável. Isso significa que nem todo mundo está vulnerável, e vou mostrar isso daqui a pouco. De qualquer forma, a recomendação é atualizar para uma versão mais recente do Spring Security: a 5.6.9 ou posterior, ou a 5.7.5 ou posterior.

O que é um bypass de autorização

Basicamente, o nome descreve bem o problema. Imagine que temos uma página da Web na nossa aplicação Spring Boot que só deveria ser acessível a usuários configurados com a função de administrador. Um bypass de autorização significa que, em determinados casos de uso, um usuário sem privilégios de administrador pode acessar essa página sem ter essa função (ou uma superior). Obviamente, isso não é desejável e pode levar a vários problemas, incluindo vazamento de dados e alterações, criação ou exclusão não autorizadas de dados.

Como funciona esse bypass de autorização no Spring Security?

Com o Spring Security, é possível criar uma SecurityFilterChain para definir permissões para endpoints específicos. Nas versões mais recentes do Spring, ela fica mais ou menos assim:

@Bean
  public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  http
     .authorizeHttpRequests((authorize) -> authorize
        .antMatchers("/").permitAll()
        .antMatchers("/forward").permitAll()
        .antMatchers("/admin").hasAuthority("ROLE_ADMIN")
        .shouldFilterAllDispatcherTypes(true)
     )
     .httpBasic().and()
     .userDetailsService(userDetailsService());
      return http.build();
  }

No exemplo acima, usei antMatchers para definir as permissões dos padrões de URL, independentemente do método HTTP. Todos têm acesso a / e /forward. Somente usuários com a função de administrador têm acesso à URL /admin.

Até aqui, tudo certo. Nada de especial, e funciona perfeitamente. Agora, vamos analisar a implementação do endpoint forward no meu controller.

@GetMapping("/forward")
public String redirect() {
  return "forward:/admin";
}

Na implementação acima, o endpoint forward encaminha a solicitação para o endpoint admin. Além disso, adicionei todos os tipos de dispatcher à minha configuração do Spring Security, já que, por padrão, apenas request, async e error são cobertos. Adicionei a linha a seguir ao arquivo application.properties da minha aplicação Spring Boot.

spring.security.filter.dispatcher-types = request, error, async, forward, include

Você pode achar que está tudo certo e que o endpoint admin está protegido pelos filtros, mas descobri que agora consigo acessar o endpoint admin por meio de /forward, sem ter a função de administrador nem sequer fazer login. Mesmo adicionando explicitamente forward à configuração e habilitando shouldFilterAllDispatcherTypes(), ainda conseguimos acessar a página de administração. Ao usar forward e incluir todos os tipos de dispatch, é possível contornar a autorização e acessar um endpoint protegido com privilégios mais altos.

Janela do navegador em localhost:8080/forward exibindo o texto “Esta é a página de administração”

Isso é possível no Spring Security 5 porque, por padrão, os filtros não são aplicados mais de uma vez à mesma solicitação. Portanto, os usuários precisam configurar explicitamente o Spring Security para que isso aconteça. Além disso, o FilterChainProxy também não está configurado para ser executado nos tipos de dispatcher forward e include.

O problema também ocorre em versões mais antigas do Spring Security 5

Se você estiver usando uma versão mais antiga de uma aplicação Spring, provavelmente também terá uma versão mais antiga do Spring Security. Uma aplicação Spring Boot antiga que mantenho para workshops usa a versão 2.2.0-RELEASE, que inclui o Spring Security 5.2.0-RELEASE. Nessas versões mais antigas, era preciso configurar a segurança de outra forma. Precisávamos criar uma classe de configuração que estendesse WebSecurityConfigurerAdapter e sobrescrever o método configure() para implementar filtros semelhantes aos mencionados anteriormente.

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

   @Override
   protected void configure(HttpSecurity http) throws Exception {
       http
               .authorizeRequests()
               .antMatchers("/").permitAll()
               .antMatchers("/forward").permitAll()
               .antMatchers("/admin").hasAuthority("ROLE_ADMIN");
   }
}

No exemplo acima, recriamos uma vulnerabilidade semelhante à anterior. Basicamente, usamos a mesma cadeia de filtros em que o problema ocorre.

Qual é a gravidade desse problema no Spring Security?

Como sempre, depende de como você usa o produto. Embora a CVE-2022-31692 tenha uma pontuação de 9,8 (crítica) de acordo com o National Vulnerability Database (NVD), na Snyk atribuímos uma pontuação um pouco menor, 7,4, o que a classifica como uma vulnerabilidade de alta gravidade.

Embora seja muito fácil explorar essa vulnerabilidade e haja ferramentas amplamente disponíveis para isso, apenas um conjunto específico de casos de uso está realmente vulnerável. Se você depende dos tipos de dispatch forward e include e usa AuthorizationFilters, como nos exemplos acima, pode haver um problema. Se, nesses tipos de dispatch, você chamar um endpoint com um nível de privilégio mais alto e usar o AuthorizationFilter para especificar privilégios, isso pode, de fato, resultar em um bypass de autorização.

Isso significa que há vários pré-requisitos para que você seja afetado por essa vulnerabilidade. Para ver a lista completa, consulte nosso comunicado sobre esse problema de segurança na Snyk Vulnerability Database.

Como mitigar esse problema de segurança

A maneira mais simples e eficaz de corrigir o problema é atualizar sua versão do Spring Security para 5.7.5 ou posterior. Se você ainda estiver usando a série 5.6.x, o problema foi corrigido na versão 5.6.9. Se você trabalha com uma aplicação Spring Boot, o melhor é atualizar para a versão 2.7.6 ou posterior, que inclui automaticamente a versão correta do Spring Security, caso você o esteja usando.

Se não for possível atualizar, você pode alterar a definição do filtro de authorizeHttpRequests().shouldFilterAllDispatcherTypes(true) para .authorizeRequests().filterSecurityInterceptorOncePerRequest(false). Isso garante que o tipo de dispatch forward seja filtrado como esperado.

Ao reescrever o primeiro exemplo desta publicação, a correção fica assim:

@Configuration
public class SecurityConfig {

   @Bean
   public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
       http
               .authorizeRequests()
               .filterSecurityInterceptorOncePerRequest(false)
               .antMatchers("/").permitAll()
               .antMatchers("/forward").permitAll()
               .antMatchers("/admin").hasAuthority("ROLE_ADMIN")
               .and()
               .httpBasic().and()
               .userDetailsService(userDetailsService());
       return http.build();
   }
}

Da mesma forma, podemos adicionar .filterSecurityInterceptorOncePerRequest(false) à forma antiga de definir um filtro, na qual era necessário estender WebSecurityConfigurerAdapter.

Mantenha suas dependências atualizadas para ficar em segurança

Isso reforça que é fundamental manter suas dependências atualizadas. Quando um problema de segurança como esse afeta sua aplicação e suas dependências estão desatualizadas, a mitigação exige muito mais esforço. Com recursos de análise de SCA, como os do Snyk Open Source, você tem acesso a essas informações e às recomendações de correção assim que elas ficam disponíveis. Você pode usar a Snyk gratuitamente. E, especificamente para desenvolvimento em Java, escrevi um artigo simples sobre como começar.

Comece a resolver desafios de capture the flag

Aprenda a resolver desafios de capture the flag assistindo sob demanda ao nosso workshop virtual introdutório.

Leia mais

illustration hero ai
Blog

PHP corrige duas vulnerabilidades críticas de RCE sem autenticação (CVE-2026-109618, CVE-2026-109619): atualize agora

Duas falhas críticas no ciclo de requisições do PHP podem permitir execução remota de código sem autenticação. Atualize para uma versão corrigida ou instale um backport do fornecedor para versões mais antigas.

blog feature ai lilac
Blog

Transforme seu backlog de vulnerabilidades em pull requests com remediação agentiva

O Evo Remediation Agent está em Open Preview e traz a resolução automatizada de dependências para o Evo Agentic AppSec. Agora, as equipes de AppSec podem executar campanhas contínuas de remediação

AI Background min crop
Blog

A IA está acionando todos os riscos que você aceitou: sete insights do painel de segurança de IA sem filtros

A IA está tornando os ataques mais baratos e rápidos, expondo riscos que as organizações já carregam. Quatro líderes de segurança explicam por que a defesa na velocidade das máquinas e a correção mais rápida são essenciais.