Qual foi a motivação por trás da introdução de pedidos de comprovação?
Solicitações de comprovação foram introduzidas para que um navegador pudesse ter certeza de que estava lidando com um servidor compatível com CORS antes de enviar determinadas solicitações. Essas solicitações foram definidas como aquelas potencialmente perigosas (mudança de estado) e novas (não possíveis antes do CORS devido à mesma política de origem ). O uso de solicitações de comprovação significa que os servidores devem aceitar (respondendo adequadamente à comprovação) os novos tipos de solicitação potencialmente perigosos que o CORS possibilita.
Esse é o significado desta parte da especificação : "Para proteger recursos contra solicitações de origem cruzada que não puderam se originar de determinados agentes do usuário antes que essa especificação existisse, é feita uma solicitação de comprovação para garantir que o recurso esteja ciente dessa especificação".
Você pode me dar um exemplo?
Vamos imaginar que um usuário do navegador esteja logado no site bancário em A.com
. Quando eles navegam para o malicioso B.com
, essa página inclui algum Javascript que tenta enviar uma DELETE
solicitação para A.com/account
. Como o usuário está logado A.com
, essa solicitação, se enviada, incluiria cookies que identificam o usuário.
Antes do CORS, a mesma política de origem do navegador o impedia de enviar essa solicitação. Mas como o objetivo do CORS é tornar possível esse tipo de comunicação entre origens, isso não é mais apropriado.
O navegador pode simplesmente enviar o DELETE
e deixar o servidor decidir como lidar com isso. Mas e se A.com
não estiver ciente do protocolo CORS? Pode seguir em frente e executar o perigoso DELETE
. Pode ter assumido que, devido à mesma política de origem do navegador, nunca poderia receber uma solicitação e, portanto, nunca teria sido reforçado contra esse ataque.
Para proteger esses servidores não compatíveis com CORS, o protocolo exige que o navegador envie primeiro uma solicitação de comprovação . Esse novo tipo de solicitação é algo que apenas os servidores compatíveis com CORS podem responder adequadamente, permitindo que o navegador saiba se é ou não seguro enviar o atual DELETE
.
Por que toda essa confusão sobre o navegador, o invasor não pode simplesmente enviar uma DELETE
solicitação de seu próprio computador?
Claro, mas essa solicitação não inclui os cookies do usuário. O ataque projetado para evitar se baseia no fato de o navegador enviar cookies (em particular, informações de autenticação para o usuário) para o outro domínio, juntamente com a solicitação.
Isso soa como falsificação de solicitação entre sites , onde um formulário no site B.com
pode ser POST
usado A.com
com os cookies do usuário e causar danos.
Está certo. Outra maneira de colocar isso é que as solicitações de comprovação foram criadas para não aumentar a superfície de ataque do CSRF para servidores não compatíveis com CORS.
Mas, analisando os requisitos para solicitações "simples" que não exigem preflight, vejo que POST
ainda é permitido. Isso pode mudar de estado e excluir dados como um DELETE
!
Isso é verdade! O CORS não protege seu site contra ataques de CSRF. Por outro lado, sem o CORS, você também não está protegido contra ataques de CSRF. O objetivo das solicitações de comprovação é apenas limitar sua exposição ao CSRF ao que já existia no mundo anterior ao CORS.
Suspiro. OK, aceito de má vontade a necessidade de pedidos de comprovação. Mas por que precisamos fazer isso para todos os recursos (URL) do servidor? O servidor lida com o CORS ou não.
Você tem certeza sobre isso? Não é incomum que vários servidores tratem solicitações para um único domínio. Por exemplo, pode ser que as solicitações A.com/url1
sejam tratadas por um tipo de servidor e as solicitações A.com/url2
sejam tratadas por um tipo diferente de servidor. Geralmente, não é o caso que o servidor que lida com um único recurso pode garantir garantias de segurança sobre todos os recursos desse domínio.
Bem. Vamos nos comprometer. Vamos criar um novo cabeçalho CORS que permita que o servidor indique exatamente quais recursos ele pode falar, para que solicitações de comprovação adicionais a esses URLs possam ser evitadas.
Boa ideia! De fato, o cabeçalho Access-Control-Policy-Path
foi proposto exatamente para esse fim. Por fim, ele foi deixado de fora da especificação, aparentemente porque alguns servidores implementaram incorretamente a especificação de URI de tal maneira que solicitações para caminhos que pareciam seguros para o navegador não seriam de fato seguros nos servidores quebrados.
Foi uma decisão prudente que priorizou a segurança sobre o desempenho, permitindo que os navegadores implementassem imediatamente a especificação CORS sem colocar em risco os servidores existentes? Ou foi míope condenar a Internet a desperdiçar largura de banda e duplicar a latência apenas para acomodar erros em um servidor específico em um determinado momento?
As opiniões são diferentes.
Bem, pelo menos, os navegadores armazenarão em cache o preflight para um único URL?
Sim. Embora provavelmente não por muito tempo. Nos navegadores WebKit, o tempo máximo de cache de comprovação é atualmente de 10 minutos .
Suspiro. Bem, se eu sei que meus servidores são compatíveis com CORS e, portanto, não precisam da proteção oferecida por solicitações de comprovação, existe alguma maneira de evitá-las?
Sua única opção real é garantir que você atenda aos requisitos para solicitações "simples". Isso pode significar excluir cabeçalhos personalizados que você incluiria (como X-Requested-With
), mentir sobre o Content-Type
ou mais.
Faça o que fizer, verifique se você possui as proteções adequadas de CSRF, pois a especificação CORS não trata de rejeitar solicitações "simples", incluindo as não seguras POST
. Como especifica a especificação : "os recursos para os quais solicitações simples têm significado diferente da recuperação devem se proteger da falsificação de solicitação entre sites".