Por Fernando Campanhã

Como já foi mencionado em outros posts aqui do SideChannel (HENRIQUE, 2021; MORAIS, 2021; MULLER, 2021), em uma parte do programa de estágio na equipe de consultoria da Tempest, os estagiários devem realizar uma pesquisa com foco em segurança ao final de cada ciclo. Assim, esta publicação é resultado do que descobri e desenvolvi durante esse estudo, que foi idealizado e apoiado pela minha bússola, Rodolfo Tavares. Muito obrigado pela ajuda, mestre \0/.

O que é esse tal de HTTP Method Override?

Como já é sabido por boa parte das pessoas que trabalham com TI, o Hypertext Transfer Protocol (HTTP) é, a grosso modo, o protocolo de comunicação utilizado pela web para que websites sejam acessados pelos usuários.

Na primeira linha de uma requisição HTTP é especificado o método a ser utilizado. Basicamente, esse método serve para especificar qual ação o usuário quer executar no servidor. Por exemplo, o método GET comumente é aplicado para ler uma determinada informação e o método PUT para adicionar ou modificar algum dado no servidor.

Apesar de existirem diversos outros métodos HTTP, nem sempre todos possuem suporte nos dispositivos dos usuários. Navegadores muito antigos ou muito simples, ou dispositivos embarcados com recursos muito limitados, podem não ter suporte a todos os métodos disponíveis. Assim, caso os servidores, com os quais esses dispositivos se comuniquem, necessitem utilizar algum desses métodos não suportados, a comunicação não seria possível pela falta de compatibilidade.

De forma a permitir o acesso de tais clientes, a solução encontrada foi implementar, ao lado do servidor, funções que fossem capazes de receber um método, mas, interpretar a requisição com outro método. Por exemplo: receber uma requisição com um método POST e interpretá-la com um método PUT. Esse conceito de sobrescrever o método passado define bem o que é o Method Override: receber um método, interpretando outro.

Porém, como o servidor saberia quais requisições deveriam ter seus métodos originais sobrescritos? A solução encontrada foi a de o cliente passar informações na requisição, indicando que o método deve ser sobrescrito. As informações aparecem nas seguintes formas:

  • Headers: X-Http-Method-Override, X-HTTP-Method-Override, X-Http-Method, X-HTTP-Method, X-Method-Override;
  • Parâmetros na URL: _method, method, httpMethod, _HttpMethod, e também os do item anterior;
  • Corpo da requisição: qualquer um dos nomes supracitados

Assim, caso o servidor tenha suporte ao Method Override, o método será alterado e a requisição será processada da forma correta.

Os desenvolvedores convencionaram que o Method Override só deva ocorrer quando o método original da requisição for POST. Porém, isso não é uma regra. O desenvolvedor é livre para alterar essa condição em sua aplicação.

Na prática

Dessa forma, ao observar esse comportamento na prática, eu criei um laboratório que possui o Method Override ativado. O funcionamento da aplicação é bem simples: ela irá refletir na resposta da página o método que interpretou.

Neste primeiro exemplo, enviei um método GET e a página confirmou que o recebeu:

Fig. 1 – Método GET refletido

Se enviarmos o POST, a página reflete o POST:

Fig. 2 – Método POST refletido

E por aí vai. No entanto, se adicionarmos o header X-Http-Method-Override, Vejamos o que acontece:

Fig. 3 – Demonstração do Method Override

Apesar do método original ser o POST, a aplicação interpretou a requisição como GET. E esse comportamento se repete com qualquer método que a aplicação aceite.

Ponto de vista da segurança

Como vimos, a única função do Method Override é alterar o método da requisição. Com isso, um atacante não poderia fazer muita coisa.

É bem provável que o dispositivo que o atacante utilize para realizar o ataque não sofra das mesmas limitações que os mencionados anteriormente e, desse modo, tenha suporte a todos os métodos HTTP. Nesse caso, ele poderia simplesmente enviar a requisição utilizando o método aceito pela aplicação e, assim, comunicar-se diretamente com ela.

Com isso em mente, surge o seguinte questionamento: então por que um atacante utilizaria o Method Override no lugar de enviar o método diretamente?

Para responder esta questão, criei um laboratório bem simples que busca mostrar na prática como essa técnica pode ser utilizada. O laboratório consiste em um simples servidor HTTP criado, que utiliza o framework de desenvolvimento Express.js, com um proxy reverso Nginx entre o cliente e o servidor.

Para esse laboratório, o Nginx foi configurado para aceitar apenas requisições com os métodos GET, HEAD e POST. Qualquer outro método será impedido de seguir para o servidor. Porém, o servidor HTTP aceita, também, os métodos PUT e DELETE. Sabendo que ele aceita esses métodos, e também que eles costumam realizar algumas operações sensíveis, seria interessante para um atacante testá-los e ver o que poderia conseguir.

Apesar das alterações supracitadas, o laboratório é o mesmo que utilizei para demonstrar o funcionamento do Method Override. Portanto, os métodos interpretados serão refletidos na tela.

Como já vimos, a aplicação aceita os métodos GET e POST normalmente. Mas e se testarmos um método um pouco menos tradicional, como o PUT?

Fig. 4 – Método PUT bloqueado

E quanto ao DELETE?

Fig. 5 – Método DELETE bloqueado

Como podemos ver, não foi possível utilizar os métodos supracitados devido a política do Nginx. E agora?

É aí que o Method Override pode ser utilizado. Vamos usá-lo para tunelar os métodos proibidos dentro de um método permitido e, com isso, nos comunicarmos diretamente com o servidor.

Como sabemos que o Nginx aceita o método POST, e que ele é o método que tem suporte ao Method Override, vamos utilizá-lo e passar o header X-Http-Method-Override, com um dos métodos proibidos, e ver o que acontece:

Fig. 6 – Bypass do filtro do método PUT

Como podemos observar, conseguimos utilizar o método PUT na aplicação. E o mesmo acontece com o DELETE:

Fig. 7 – Bypass do filtro do método DELETE

Essa é a essência do Method Override: nos comunicarmos diretamente com o servidor, contornando possíveis filtros de métodos HTTP que estejam no caminho, como, por exemplo, um API gateway, um proxy reverso ou um firewall.

Um cenário de ataque real foi publicado através do write up disponível em How I exploit the JSON CSRF with method override technique

Apesar de o foco da publicação ser a exploração de um JSON CSRF, a falha só pode ser explorada graças ao Method Override, pois o endpoint só aceitava o método PUT e, o formulário HTML, só permitia os métodos GET e POST.

Outro possível cenário de exploração leva em consideração a arquitetura atual de algumas aplicações, na qual existem diversos componentes entre o cliente e ela. Por exemplo, imaginemos um cenário onde exista um API gateway responsável por autenticar e encaminhar as requisições do usuário a um outro servidor. Por sua vez, o primeiro encaminha a requisição para um segundo servidor e por aí vai. Pelo fato de a única comunicação externa acontecer entre o cliente e o API gateway, os componentes que estiverem por trás dele tendem a confiar mais nas informações passadas entre si porque, em tese, são de fontes confiáveis. Dessa forma, um atacante poderia utilizar o Method Override para executar ações indevidas em outros servidores, passando um método aceito pelo API gateway e o sobrescrevendo por outro, podendo realizar ações que somente deveriam ser executadas pelos outros componentes reconhecidos.

Apesar de termos visto que é possível explorar algumas falhas utilizando esta técnica, ela por si só não pode ser considerada uma falha de segurança.

Voltando ao caso do JSON CSRF, podemos observar que a falha de segurança é o JSON CSRF, e não o Method Override. Ele foi apenas um meio utilizado para explorar a falha. Caso o suporte a ele seja removido da aplicação, ela continuará vulnerável ao JSON CSRF, só que, agora, o atacante precisaria utilizar alguma outra técnica para explorá-lo.

Method Overrider

Para auxiliar na detecção dessa técnica, decidi criar uma ferramenta que auxiliasse em sua detecção. Decidi chamá-la de Method Overrider. A ferramenta em questão é um plugin, ou extensão, para a ferramenta de proxy Burp Suite.

Basicamente, ela analisa todas as requisições e suas respectivas respostas que passam pelo proxy, buscando palavras-chave que indiquem a presença do Method Override. Caso as encontre, o usuário é notificado, cabendo a ele avaliar o que pode ser feito com essa informação.

Mais detalhes da implementação podem ser encontrados no meu repositório do Github, disponível em [5].

Conclusões

Um dos intuitos deste estudo foi trazer à tona essa técnica que não é muito conhecida pelos profissionais da segurança.

Como vimos, ela pode ser fundamental para a exploração de algumas falhas em certos cenários, especialmente quando existem filtros de métodos HTTP.

Alguns CVEs envolvendo essa técnica já foram registrados, entre eles:

Apesar de ser uma breve introdução sobre o assunto, espero que tenha sido esclarecedor e que o Method Override possa ser útil em algum momento durante os seus testes. É um comportamento que vale a pena ser testado e que possui poucos reportes públicos disponíveis para nos basearmos, sendo uma técnica pouco conhecida e com grande potencial de expansão.

Referências

CAMPANHA, Fernando. Method overrider. Disponível em https://github.com/fernandocampanha/MethodOverrider. Acesso em 08 de janeiro de 2022.

HENRIQUE, Ricardo. URL Filter Subversion. Disponível em https://sidechannel.blog/url-filter-subversio/index.html. Acesso em 20 de dezembro de 2021.

MORAIS, Vinicius. A Saga do Cypher Injection. Disponível em https://www.sidechannel.blog/a-saga-do-cypher-injection/index.html. Acesso em 21 de dezembro de 2021.

MULLER, Eduardo. Conversores de HTML para PDF, dá para hackear? Disponível em https://www.sidechannel.blog/conversores-de-html-para-pdf-da-para-hackear/index.html. Acesso em 22 de dezembro de 2021.

SECUREITMANIA. How I exploit the JSON CSRF with method override technique. Disponível em https://infosecwriteups.com/how-i-exploit-the-json-csrf-with-method-override-technique-71c0a9a7f3b0. Acesso em 04 de janeiro de 2022.