O compartilhamento de recursos de origem cruzada é um mecanismo que permite que uma página da Web faça XMLHttpRequests para outro domínio (da wikipedia ).
Eu tenho mexido com o CORS nos últimos dias e acho que tenho um bom entendimento de como tudo funciona.
Portanto, minha pergunta não é sobre como o CORS / preflight funciona, é sobre o motivo de apresentar os preflights como um novo tipo de solicitação . Não vejo nenhuma razão para o servidor A precisar enviar um preflight (PR) para o servidor B apenas para descobrir se a solicitação real (RR) será aceita ou não - certamente seria possível para B aceitar / rejeitar RR sem qualquer PR anterior.
Depois de pesquisar bastante, encontrei esta informação em www.w3.org (7.1.5):
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.
Acho que esta é a frase mais difícil de entender de todos os tempos. Minha interpretação (deveria melhor chamá-lo de 'melhor palpite') é que se trata de proteger o servidor B contra solicitações do servidor C que não está ciente das especificações.
Alguém pode explicar um cenário / mostrar um problema que o PR + RR resolve melhor que o RR sozinho?
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 maliciosoB.com
, essa página inclui algum Javascript que tenta enviar umaDELETE
solicitação paraA.com/account
. Como o usuário está logadoA.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 seA.com
não estiver ciente do protocolo CORS? Pode seguir em frente e executar o perigosoDELETE
. 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 serPOST
usadoA.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 umDELETE
!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çõesA.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 oContent-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".fonte
Considere o mundo das solicitações entre domínios antes do CORS. Você pode fazer um formulário padrão POST ou usar
script
umaimage
tag ou para emitir uma solicitação GET. Você não pôde fazer nenhum outro tipo de solicitação além de GET / POST e não pôde emitir cabeçalhos personalizados para essas solicitações.Com o advento do CORS, os autores das especificações foram confrontados com o desafio de introduzir um novo mecanismo entre domínios sem quebrar a semântica existente na web. Eles optaram por fazer isso, oferecendo aos servidores uma maneira de aceitar qualquer novo tipo de solicitação. Esse opt-in é a solicitação de comprovação.
Portanto, solicitações GET / POST sem nenhum cabeçalho personalizado não precisam de um preflight, pois essas solicitações já eram possíveis antes do CORS. Mas qualquer pedido com os cabeçalhos personalizados ou solicitações PUT / DELETE, não precisa de um pré-voo, uma vez que estes são novos para o CORS spec. Se o servidor não souber nada sobre o CORS, ele responderá sem nenhum cabeçalho específico do CORS e a solicitação real não será feita.
Sem a solicitação de comprovação, os servidores podem começar a ver solicitações inesperadas dos navegadores. Isso pode levar a um problema de segurança se os servidores não estiverem preparados para esses tipos de solicitações. A comprovação do CORS permite que solicitações entre domínios sejam introduzidas na Web de maneira segura.
fonte
O CORS permite especificar mais cabeçalhos e tipos de métodos do que era possível anteriormente com origem cruzada
<img src>
ou<form action>
.Alguns servidores podem ter sido (mal) protegidos com a suposição de que um navegador não pode fazer, por exemplo,
DELETE
solicitação de origem cruzada ou solicitação de origem cruzada comX-Requested-With
cabeçalho, portanto essas solicitações são "confiáveis".Para garantir que o servidor realmente ofereça suporte ao CORS e não apenas responda a solicitações aleatórias, o preflight é executado.
fonte
Aqui está outra maneira de ver, usando o código:
Antes do CORS, a tentativa de exploração acima falharia porque viola a política de mesma origem. Uma API projetada dessa maneira não precisava de proteção XSRF, porque estava protegida pelo modelo de segurança nativo do navegador. Era impossível para um navegador pré-CORS gerar um JSON POST de origem cruzada.
Agora o CORS entra em cena - se não fosse necessário optar pelo CORS via pré-vôo, esse site teria uma enorme vulnerabilidade, de repente, sem culpa própria.
Para explicar por que alguns pedidos têm permissão para pular o pré-vôo, isso é respondido pela especificação:
Para desvendar isso, o GET não é pré-veiculado porque é um "método simples", conforme definido em 7.1.5. (Os cabeçalhos também devem ser "simples" para evitar o pré-vôo). A justificativa para isso é que a solicitação GET de origem "simples" já pode ser executada por exemplo
<script src="">
(é assim que o JSONP funciona). Como qualquer elemento com umsrc
atributo pode acionar um GET de origem cruzada, sem pré-voo, não haveria benefício de segurança em exigir pré-combate em XHRs "simples".fonte
Sinto que as outras respostas não estão focadas no motivo pelo qual a pré-luta aumenta a segurança.
Cenários:
1) Com pré-voo . Um invasor falsifica uma solicitação do site dummy-forums.com enquanto o usuário é autenticado em safe-bank.com.
Se o servidor não verificar a origem e, de alguma forma, apresentar uma falha, o navegador emitirá uma solicitação antes do voo, OPTION método. O servidor não sabe nada disso sobre o CORS que o navegador espera como resposta, de modo que o navegador não prossiga (nenhum dano)
2) Sem pré-vôo . Um invasor falsifica a solicitação no mesmo cenário acima, o navegador emitirá a solicitação POST ou PUT imediatamente, o servidor a aceitará e poderá processá-la, o que poderá causar algum dano.
Se o invasor envia uma solicitação diretamente, com origem cruzada, de algum host aleatório, é mais provável que alguém esteja pensando em uma solicitação sem autenticação. Essa é uma solicitação forjada, mas não uma solicitação xsrf. portanto, o servidor verificará as credenciais e falhará. O CORS não tenta impedir um invasor com credenciais de emitir solicitações, embora uma lista de permissões possa ajudar a reduzir esse vetor de ataque.
O mecanismo de pré-vôo adiciona segurança e consistência entre clientes e servidores. Não sei se vale a pena o aperto de mão extra para cada solicitação, pois o cache é difícil de usar, mas é assim que funciona.
fonte
Fonte
fonte
Solicitações pré-vôo são necessárias para solicitações que podem mudar de estado no servidor. Existem 2 tipos de pedidos -
1) Chamadas que não podem mudar de estado no servidor (como GET) - O usuário pode obter uma resposta para a solicitação (se o servidor não verificar a origem), mas se o domínio solicitante não for adicionado ao cabeçalho de resposta Access-Control- Allow-Origin, o navegador não mostra os dados para o usuário, ou seja, a solicitação é enviada do navegador, mas o usuário não pode visualizar / utilizar a resposta.
2) Chamadas que podem mudar de estado no servidor (como POST, DELETE) - Como em 1), vemos que o navegador não bloqueia a solicitação, mas a resposta, mas as chamadas de alteração de estado não devem ser feitas sem verificações anteriores . Essas chamadas podem fazer alterações em um servidor confiável que não verifica a origem das chamadas (chamada falsificação de solicitação entre sites), mesmo que a resposta ao navegador possa estar com falha. Por esse motivo, temos o conceito de solicitações pré-voo que fazem uma chamada OPTIONS antes que qualquer chamada de alteração de estado possa ser enviada ao servidor.
fonte
As solicitações pré-comprovadas não são sobre desempenho ? Com as solicitações pré-comprovadas, um cliente pode saber rapidamente se a operação é permitida antes de enviar uma grande quantidade de dados, por exemplo, no método JSON com PUT. Ou antes de viajar com dados confidenciais em cabeçalhos de autenticação por fio.
O fato de PUT, DELETE e outros métodos, além de cabeçalhos personalizados, não é permitido por padrão (eles precisam de permissão explícita com "Métodos de solicitação de controle de acesso" e "Cabeçalhos de solicitação de controle de acesso"). assim como uma verificação dupla, porque essas operações podem ter mais implicações nos dados do usuário, em vez de solicitações GET. Então, soa como:
"Vi que você permite solicitações entre sites de http: //foo.example , MAS TEM CERTEZA de permitir DELETE solicitações? Você considerou os impactos que essas solicitações podem causar nos dados do usuário?"
Não entendi a correlação citada entre as solicitações pré-comprovadas e os benefícios dos servidores antigos. Um serviço da Web que foi implementado antes do CORS, ou sem um reconhecimento do CORS, nunca receberá QUALQUER solicitação entre sites, porque primeiro sua resposta não terá o cabeçalho "Access-Control-Allow-Origin".
fonte
Em um navegador que suporta CORS, as solicitações de leitura (como GET) já estão protegidas pela política de mesma origem: um site mal-intencionado que tenta fazer uma solicitação autenticada entre domínios (por exemplo, o site de serviços bancários na Internet da vítima ou a interface de configuração do roteador) não conseguir ler os dados retornados porque o banco ou o roteador não define o
Access-Control-Allow-Origin
cabeçalho.No entanto, com solicitações de gravação (como POST), o dano é causado quando a solicitação chega ao servidor da Web. * Um servidor da Web pode verificar o
Origin
cabeçalho para determinar se a solicitação é legítima, mas essa verificação geralmente não é implementada porque o servidor da Web não precisa para o CORS ou o servidor da Web é mais antigo que o CORS e, portanto, pressupõe que POSTs entre domínios sejam completamente proibidos pela política de mesma origem.É por isso que os servidores da web têm a chance de optar por receber solicitações de gravação entre domínios .
* Essencialmente a versão AJAX do CSRF.
fonte