
Todas as versões do nosurf anteriores à 1.2.0 não aplicavam verificações de mesma origem para requisições recebidas.
Isso acontecia devido à dependência do campo .URL.Scheme no tipo net/http.Request da biblioteca padrão do Go
para primeiro garantir que a requisição é servida via HTTPS, e só então aplicar verificações de mesma origem.
O referido campo Scheme não é preenchido pelo servidor HTTP do Go em requisições recebidas:
// For server requests, the URL is parsed from the URI // supplied on the Request-Line as stored in RequestURI. For // most requests, fields other than Path and RawQuery will be // empty.
pois no caso geral o Go não consegue determinar se a requisição está ocorrendo via TLS (devido à possível presença de um proxy reverso que termina TLS, etc.).
Isso pode permitir que atacantes façam requisições entre origens não seguras para o seu site.
Além de implementar verificações de mesma origem, o nosurf também protege contra CSRF usando um padrão de cookie de duplo envio.
Isso significa que, para fazer com sucesso uma requisição entre origens mutável,
o atacante também precisa ter controle sobre o conteúdo de uma página no seu site,
ou em um subdomínio do seu site.
Isso pode ser alcançado via XSS, ou se você intencionalmente dá controle do conteúdo HTML para usuários no seu site
(por exemplo, você é um provedor de hospedagem example.com que permite que usuários hospedem seus sites em alice.example.com).
O PoC neste repositório demonstra esse ataque no último caso, onde o atacante tem controle do conteúdo em um subdomínio do domínio principal do site.
Requer Go e Caddy. Execute os servidores manualmente:
$ go run attacker.go & go run target.go & caddy run
ou via Process Compose:
$ process-compose
Visite https://attacker.target.localhost.
Clique no botão para enviar o formulário para https://target.localhost e observe que a requisição é concluída com sucesso.
Uma correção para este problema foi lançada no nosurf 1.2.0.
Agradecimentos a Patrick O'Doherty por relatar o problema.