Vulnerabilidade no Nginx que expõe o cofre do Bitwarden
(labs.hakaioffsec.com)- Nginx, um servidor web versátil com participação de mercado dominante desde 2004
- Configurações incorretas do Nginx podem levar a vulnerabilidades de segurança e exposição de dados
- Apresentação do NavGix, uma ferramenta automatizada para detectar vulnerabilidades no Nginx
- Essa vulnerabilidade pode permitir acesso a arquivos e diretórios além do escopo pretendido
- Estudos de caso sobre o Bitwarden e o HPC Toolkit do Google mostram a gravidade dessa vulnerabilidade
1 comentários
Comentários do Hacker News
Para referência, o gixy (verificador de configuração do nginx) detecta esse problema: https://github.com/yandex/gixy/blob/master/docs/en/plugins/a...
E o NixOS executava o gixy automaticamente nas configurações geradas por ele, recusando a build do sistema se houvesse algum problema
$uriem um redirecionamento 301Mas fico curioso se existe um buscador de opções melhor. Não gostei muito de pesquisar em milhares de opções de uma vez; eu queria ver apenas um pacote como
sshe só as opções relacionadas a ele, mas aparecem resultados irrelevantes demaisPode ser uma pergunta boba, mas existe algum bom motivo para o nginx permitir subir para o diretório pai com
..no caminho da URL? Isso parece só um comportamento esperando para dar problemaEdit: ainda estou um pouco confuso sobre o que acontece exatamente na vulnerabilidade original. Parece que http://localhost/foo../secretfile.txt é interpretado como
/var/www/foo/../secretfile.txt, mas então, em um servidor sem a vulnerabilidade, por que http://localhost/foo/../secretfile.txt não seria interpretado da mesma forma? Não entendo por que..dentro do caminho só funciona em alguns casosNesse caso, parte da URL é interpretada como um diretório (http://localhost/foo) pelo nginx por causa de como o mapeamento para o sistema de arquivos local foi definido na configuração. Como isso parece apontar para um diretório, ao montar o caminho completo do recurso solicitado o nginx acaba com
"${mapped_path}/../secretfile.txt", que pode não fazer sentido do ponto de vista da URL, mas é válido no sistema de arquivos local. URL é só uma string, não um conjunto real de componentes de caminho, então a posição das barras também não é intrinsecamente importanteIsso é algo muito comum em servidores web desde o início da web. Mapear URL diretamente para caminho de arquivo ficou popular porque começou com servidores simples de arquivos com índice, mas logo evoluiu para ambientes híbridos em que a URL deixa de ser um caminho e passa a ser um identificador de aplicação. Parte do caminho identifica o app, e o resto é tratado como parâmetro ou argumento
E, de modo geral, respeitar
.ou..da URL para objetos do sistema de arquivos normalmente não faz sentido. Meus apps limpam o caminho da requisição para garantir um mapeamento correto. Navegadores tratam URLs como caminhos ao criar links relativos, então também é preciso ter cuidado com quando e como usar a/final. No lado do servidor, isso pode apontar para recursos com significado diferentelocation, tipoallow_parent_traversal on;"/foo/bar/.."para bloquear ou normalizar para"/foo/". Mas"/foo/bar.."é um nome de arquivo totalmente válido, então parece escapar desse tipo de verificação..funciona em um caminho depende inteiramente das permissões de arquivoNeste caso, suponha que a partir do diretório indexado pela web (
../index.html) exista permissão de leitura até o diretório raiz (/). Se você tem permissão para subir até a raiz, então também passa a poder ver qualquer arquivo legível por todos a partir dela, como/etc/passwdPense em um garfo de três pontas, com o servidor web na ponta da direita. Se a parte do cabo, onde as pontas se encontram, for o sistema de arquivos, então, quando o servidor web tem permissão para acessar os arquivos e diretórios do caminho da ponta direita até o cabo, ao chegar ao cabo ele também consegue continuar acessando arquivos das outras pontas
Não entendo por que isso não é visto como uma vulnerabilidade do nginx. Esse comportamento é completamente absurdo, não parece ter nenhuma utilidade e pode ser explorado imediatamente
Também vale lembrar que o nginx ganhou popularidade graças a benchmarks que o mostravam mais “web scale” do que o Apache2
Fiquei pensando em uma abordagem assim: colocar no parser de nomes de arquivo do kernel Linux uma opção parecida com uma capability do Linux para remover a possibilidade de
..Em apps web, desde a época do modem discado, continuam surgindo várias formas de burlar isso e enfiar dois pontos no caminho de algum jeito. Assim como o kernel Linux já fez com várias outras classes de bugs em espaço de usuário, talvez tenha chegado a hora de encontrar um jeito de fechar esse problema de uma vez
RESOLVE_BENEATHem https://man7.org/linux/man-pages/man2/openat2.2.htmlNo FreeBSD, essa funcionalidade existe no
openat(2)comum comoO_RESOLVE_BENEATHDá para rodar o nginx com um usuário separado com privilégios bem limitados ou dentro de um Docker. Somando isso a atualizações regulares, normalmente 90% dos problemas de segurança já ficam resolvidos
/some/../pathdeveria ser proibido em quase 100% dos casos. Não existe um caso de uso razoável além de “alguém escreveu um código horroroso”../some/pathpelo menos às vezes faz sentidoAinda assim, talvez não fosse tão útil quanto parece. Muitos apps já resolvem
..antes de passar para o sistema operacionalSe você está servindo arquivos de uma pasta para a web, o framework web precisa garantir que não dá para escapar da pasta raiz pública que ele controla. Se você está fazendo isso manualmente, precisa considerar todo tipo de situação, inclusive essa
“A equipe do Google VRP deu uma recompensa de 500 dólares por ter encontrado essa vulnerabilidade. Considerou que o impacto na aplicação não era grave o bastante para justificar uma recompensa maior”, então exposição do e-mail da conta GCP e da chave privada vale só 500 dólares? Que história é essa. Bem a cara do Google mesmo
Ainda bem que o que vazou continuava criptografado. Se até uma empresa especializada nessa área não está livre de vazamentos, sinceramente esse parece o melhor cenário possível
O título foi bastante editado. O título original é Hunting for Nginx Alias Traversals in the wild
O título enviado no HN destaca a vulnerabilidade do Bitwarden, mas o texto também cobre o caso do Google
Se a necessidade for apenas servir arquivos estáticos de forma segura e estável, com uso mínimo de recursos, qual seria hoje a melhor opção? Antigamente eu escolheria Nginx, mas do ponto de vista de segurança fico pensando se uma ferramenta mais específica e com menos possibilidades de configuração não seria melhor
É multiplataforma, escrito em Rust, tem configuração simples e valores padrão seguros. Também há imagem de contêiner reforçada e módulo NixOS reforçado
Não recomendo o Caddy. A imagem oficial de Docker roda como root por padrão [1], e eles também não fornecem um arquivo de unidade systemd devidamente sandboxed [2]
[1]: https://github.com/caddyserver/caddy-docker/issues/104
[2]: https://github.com/caddyserver/dist/blob/master/init/caddy.s...
Edit: ajuste de redação
file_serversólidoTalvez seja uma pergunta boba, mas por que o Bitwarden permitia requisições não autenticadas para
/attachmentsem primeiro lugar? Mesmo com o bug do Nginx, se aquela URL exigisse autenticação, a requisição não falharia?Ainda assim, como eles distribuíram uma configuração perigosa via Docker, isso de fato é responsabilidade do Bitwarden. E o Bitwarden aparentemente reconheceu isso e corrigiu depois
Perdoem a pergunta idiota. Com a propriedade adequada de diretórios e arquivos, esse tipo de varredura não seria bloqueado?
Se o nginx não estiver rodando como root, como ele pode ler outros arquivos além daqueles explicitamente atribuídos ao usuário do nginx?
go-rwxem todos os arquivos do app, defina o grupo dos arquivos “static” comowww-datae dê apenasg+r; assim o servidor web não consegue acessar os arquivos da aplicaçãoIsso é literalmente hospedagem de aplicações 101, e as pessoas já faziam isso 20 anos atrás
/homeTalvez seja preciso ajustar um pouco mais a associação a grupos, mas vale muito a pena
Talvez eu esteja fazendo uma besteira enorme. Ai
www-data. Se a aplicação gera dados sensíveis, faz todo sentido usar umask 077Infelizmente, o nginx e outros servidores web geralmente precisam rodar como root em aplicações web comuns. Porque precisam escutar nas portas 80 ou 443. Portas abaixo de 1024 só podem ser abertas por root
Há uma explicação mais detalhada aqui: https://unix.stackexchange.com/questions/134301/why-does-ngi...