Na série anterior
Não faz muito tempo,
publiquei uma descrição da vulnerabilidade para o Steam. Recebi muitos comentários dos leitores. A Valve não disse uma palavra e o HackerOne enviou uma enorme carta chorosa e, basicamente, ficou em silêncio. Como resultado, a Valve me baniu do H1 - não posso participar do programa deles para rejeitar vulnerabilidades (o restante do H1 está disponível para mim).

Para saber mais sobre a história em uma publicação anterior, aqui vou dizer algumas palavras sobre o status atual.
Mas é simples e triste - a válvula ainda falha. A atualização mais recente, projetada para corrigir o problema, é
facilmente ignorada e a vulnerabilidade ainda é relevante. Sim, eu verifiquei - funciona muito bem.
Mas este artigo não é sobre o fato de que a vulnerabilidade antiga ainda está presente, mas sobre a nova. Como a Valve mais uma vez expressou o desejo de ler um relatório público, em vez de privado, não os privaremos desse prazer.
Breve descrição da vulnerabilidade
Uma descrição geral da exploração de uma vulnerabilidade é bastante direta e consiste em três etapas:
- Preparamos o ambiente para a operação (até duas maneiras de escolher, usando falhas de segurança diferentes).
- Faça o Steam copiar e executar nossa DLL.
- A DLL deve atender a pequenos requisitos.
Todas essas ações podem ser executadas por qualquer usuário do sistema operacional ou, mais precisamente, por qualquer programa no computador. Como resultado, você pode
executar qualquer código com privilégios máximos . Essa classe de vulnerabilidades é chamada escalada de privilégios (eop) ou escalada de privilégios local (lpe). Apesar de qualquer aplicativo em si poder causar algum dano, a obtenção de direitos máximos levará a consequências muito mais significativas. Desligar o antivírus e o firewall, instalar um rootkit, ocultar o processo do minerador, roubar os dados pessoais de todos os usuários de PC é apenas uma pequena parte do que você pode imaginar.
Mínimo teórico
Foi muito engraçado assistir aos comentários do artigo anterior, onde as pessoas escreveram "O usuário não pode gravar chaves de registro no HKLM" ou "Direitos de administrador são necessários para criar um link simbólico". Curiosamente, verificar essas alegações dificilmente levará mais tempo do que escrever esse comentário. E, sim, apenas por precaução: ambas as afirmações são falsas. Portanto, neste artigo, decidi fazer uma pequena seção na qual descrevi vários momentos difíceis da operação.
“Você não pode gravar na chave de registro HKLM”
Não existe essa regra geral. Existem regras de segurança específicas para chaves de registro específicas. A válvula define direitos de acesso total para todos os usuários à ramificação
HKLM \ SOFTWARE \ Wow6432Node \ Valve \ steam e, portanto, qualquer usuário pode fazer o que quiser nessa ramificação.
"Você não pode iniciar ou parar um serviço sem direitos de administrador"
Não existe essa regra geral. Existem regras de segurança específicas para serviços específicos. A Valve define os direitos para que o Serviço do Cliente Steam possa ser iniciado e interrompido por qualquer usuário.
"Para criar um link simbólico, você precisa de direitos de administrador"
Essa é uma pergunta engraçada, já que dos 5 principais tipos de links no Windows, apenas um e meio exige esses direitos. Portanto, conheça: link simbólico de arquivo, link simbólico de diretório de objetos, link físico, ponto de nova análise NTFS e reg_link. Os direitos de administrador são necessários apenas para criar um link simbólico de arquivo e para um link simbólico de diretório de objetos permanente (o temporário vive exatamente enquanto a sessão em que ele é criado vive, no sentido geral, antes da reinicialização e não requer direitos especiais).
Simlink de pasta para pasta
Isso é chamado de ponto de nova análise NTFS ou ponto de montagem NTFS. O nome não é particularmente importante, o fato é que isso permite que você use uma pasta como ponteiro para outra. Ele pode ser criado por um usuário comum a partir de uma pasta vazia se ele tiver direitos de gravação. Para a criação, usaremos o utilitário CreateMountPoint.exe em um
conjunto de utilitários para testar o trabalho com links .
Deixando a fechadura
O bloqueio de saída (
OpLock ou Oportunistic Lock ) é um mecanismo especial no qual um aplicativo pode bloquear temporariamente todos os
usuários de acessar um determinado recurso de arquivo. Aqui você pode escrever muitos tipos de detalhes, recursos para trabalhar com pastas e acessos diferentes. A linha inferior é: o programa pode "capturar" o evento de acessar um determinado arquivo e mantê-lo por um tempo. Você pode instalar oplocks usando o utilitário SetOpLock.exe do mesmo
conjunto de testes para trabalhar com links . A execução do utilitário instala o desbloqueio necessário; quando o acesso ocorre, o utilitário grava uma mensagem; pressionar enter remove o desbloqueio.
Baitandndswitch
Este é o nome da técnica, que combina a criação de links e a instalação do oplos para obter o TOCTOU (hora da verificação \ hora da utilização). A essência é mais fácil de explicar com um exemplo.
Imagine que exista algum programa que faça algo parecido com isto:
ReadContentFromFile(“C:\test\myfile.txt”); ReadContentFromFile(“C:\test\myfile.txt”);
É apenas a leitura do mesmo arquivo duas vezes seguidas. O mesmo sempre será lido? Não, não necessariamente.
Primeiro, crie duas pastas com os arquivos C: \ test1 \ myfile.txt e C: \ test2 \ myfile.txt. E, em geral, limparemos a pasta C: \ test e criaremos um ponto de nova análise em C: \ test1. Colocamos o desbloqueio no arquivo do primeiro diretório e executamos o programa. Assim que ela abrir o arquivo, o desbloqueio funcionará. Alteraremos o ponto de nova análise e C: \ test apontará para C: \ test2. Agora, após a remoção do desbloqueio, o programa lerá o arquivo pela segunda vez em outro arquivo.
Por que isso é necessário? Muito simples - uma situação bastante típica em que o arquivo é verificado primeiro (primeira leitura) e depois iniciado (segunda leitura). É assim que enviamos um arquivo para verificação e outro para execução.
Agora tudo está pronto para operação.
Operação 1. Preparando o ambiente
É necessário preparar um pouco o ambiente de trabalho. Para começar, você precisa levar os arquivos executáveis CreateMountPoint.exe e SetOpLock.exe.
Agora precisamos fazer pequenas alterações na estrutura de arquivos do Steam. Nossa tarefa é obter uma pasta com dois arquivos Steam.exe e steamclient.dll e a ausência obrigatória da pasta bin. Existem duas maneiras de fazer isso.
Método 1
Renomeie \ exclua a pasta bin da pasta principal do Steam. Isso é tudo, você é ótimo (o Steam durante a instalação concede a qualquer usuário os direitos de tudo em sua pasta).
Método 2
Na chave do registro HKLM \ SOFTWARE \ Wow6432Node \ Valve \ steam, altere o parâmetro InstallPath para algumas das nossas pastas. Nesta pasta, solte o Steam.exe e o steamclient.dll na pasta principal do Steam.
Suponha que preparamos a pasta C: \ Steam por qualquer um dos métodos (o caminho pode ser qualquer um, mas nos exemplos eu usarei isso). Agora crie outras pastas b1, b2, b3 e b4 nele. Nos três primeiros, carregaremos o arquivo steamservice.dll (do kit Steam, no original, estava na pasta bin) e, na pasta b4, largaremos a biblioteca especialmente formada com o mesmo nome - steamservice.dll. Os detalhes sobre a preparação da biblioteca estarão no parágrafo 3.
Abrimos duas janelas do console. Isso completa a preparação do ambiente.
Operação 2. Substituindo o arquivo
Penso que a partir dos preparativos já ficou claro que haverá algo como o BaitAndSwitch descrito acima.
Screenshot do ProcMon:

Isso faz parte do lançamento típico do Serviço ao Cliente Steam. Observe a parte em que a dll é copiada primeiro para C: \ Arquivos de Programas (x86) \ Common Files \ Steam e, em seguida, carregada. Garantiremos que nossa biblioteca seja copiada de C: \ Steam \ b4. Infelizmente, as verificações são conduzidas primeiro, incluindo a assinatura da biblioteca, para que não possa ser substituída (oh, ironia).
Então, vou assinar as etapas. As etapas são combinadas em grupos das mesmas ações. Para cada etapa, será indicado onde o que iniciar e o que acontece (chamei as diferentes janelas do console cmd1 e cmd2).
- Crie a pasta C: \ Steam \ bin e, em cmd1, execute:
CreateMountPoint.exe C: \ Steam \ bin C: \ Steam \ b1 - No cmd1, colocamos o oplock:
SetOpLock.exe C: \ Steam \ b1 \ steamservice.dll - Iniciamos o Serviço de Cliente Steam, vemos no cmd1 que obtivemos acesso ao arquivo.
*** - Exclua C: \ Steam \ bin, crie a pasta C: \ Steam \ bin em seu lugar e, em cmd2, execute:
CreateMountPoint.exe C: \ Steam \ bin C: \ Steam \ b2 - No cmd2, colocamos o oplock:
SetOpLock.exe C: \ Steam \ b2 \ steamservice.dll - No cmd1, liberamos o desbloqueio, vemos que o cmd2 obteve acesso ao arquivo.
*** - Exclua C: \ Steam \ bin, crie a pasta C: \ Steam \ bin em seu lugar e execute cmd1:
CreateMountPoint.exe C: \ Steam \ bin C: \ Steam \ b3 - No cmd1, colocamos o oplock:
SetOpLock.exe C: \ Steam \ b3 \ steamservice.dll - No cmd2, liberamos o desbloqueio, vemos que o cmd1 obteve acesso ao arquivo.
*** - Exclua C: \ Steam \ bin, crie a pasta C: \ Steam \ bin em seu lugar e execute cmd2:
CreateMountPoint.exe C: \ Steam \ bin C: \ Steam \ b2 - No cmd2, colocamos o oplock:
SetOpLock.exe C: \ Steam \ b2 \ steamservice.dll - No cmd1, liberamos o desbloqueio, vemos que o cmd2 obteve acesso ao arquivo.
*** - Exclua C: \ Steam \ bin, crie a pasta C: \ Steam \ bin em seu lugar e execute cmd1:
CreateMountPoint.exe C: \ Steam \ bin C: \ Steam \ b3 - No cmd1, colocamos o oplock:
SetOpLock.exe C: \ Steam \ b3 \ steamservice.dll - No cmd2, liberamos o desbloqueio, vemos que o cmd1 obteve acesso ao arquivo.
*** - Exclua C: \ Steam \ bin, crie a pasta C: \ Steam \ bin em seu lugar e execute cmd2:
CreateMountPoint.exe C: \ Steam \ bin C: \ Steam \ b4 - No cmd1, liberamos o desbloqueio
Embora pareça complicado, na verdade a idéia é simples: de 6 acessos ao arquivo C: \ Steam \ bin \ steamservice.dll, nas primeiras 5 vezes em que foram fornecidos os arquivos originais de diferentes pastas (na ordem de acesso: b1, b2, b3, b2, b3) e, pela sexta vez, foi fornecido um arquivo com uma carga útil para cópia.
Esquematicamente, eu o descrevi assim:

À esquerda está o comportamento normal, à direita está o comportamento de exploração.
Operação 3. Biblioteca Implementada
Para a carga útil, usei minha dll mais típica, que no DllEntry cria um console interativo. Como o código da dll será executado no contexto do Serviço de Cliente Steam, ele será executado com os mesmos direitos que o próprio serviço - NT AUTHORITY \ SYSTEM. Mas, como resultado da operação, o console não apareceu.
Após o download, o serviço Steam ainda entende que eles colocaram uma tília nele e finalizam o trabalho, para que a carga da minha dll não consiga ser executada.
Eu tive que me virar um pouco, e aconteceu que o serviço após carregar a dll verifica a existência de funções
int WINAPI SteamService_RunMainLoop() void WINAPI SteamService_Stop()
na biblioteca. Além disso, o serviço chama a primeira função, onde eu decidi colocar a carga (iniciando um console interativo com os direitos do serviço - NT AUTHORITY \ SYSTEM). Agora é tudo - repetimos todas as etapas e obtemos um console com permissões máximas.
Conclusão
Você pode agrupar tudo isso em um arquivo exe, mas, sinceramente, não quero incomodar. Eu acho que um vídeo com uma demonstração será suficiente (
opção com o registro ,
opção com o sistema de arquivos ).
Não copiarei aqui a seção "Especulação" de um artigo anterior. Apenas os fatos: a antiga vulnerabilidade é atual, você acabou de ler sobre a nova, a Valve ainda não quer ouvir sobre os problemas.
Atualização (22/08/2019)
No momento, existem duas notícias:
- O cliente beta recebeu correção do patch . Observarei quando a atualização chegar ao cliente principal.
- A válvula mudou a política do LPE . E esta é uma ótima notícia!
Atualização (27/08/2019)
Boas notícias.
- O cliente principal recebeu a atualização do patch .
- Fui banido do H1 e paguei uma recompensa
Este artigo em inglês.