O suporte para o Windows Vista Service Pack 1 (SP1) termina a 12 de julho de 2011. Para continuar a receber atualizações de segurança para o Windows, certifique-se de que está a executar o Windows Vista com o Service Pack 2 (SP2). Para obter mais informações, consulte esta página Web da Microsoft: O suporte está a terminar para algumas versões do Windows.
Quando uma aplicação carrega dinamicamente uma biblioteca de ligações dinâmica (DLL) sem especificar um caminho completamente qualificado, o Windows tenta localizar a DLL ao procurar um conjunto bem definido de diretórios. Se um atacante obtiver o controlo de um dos diretórios, pode forçar a aplicação a carregar uma cópia maliciosa da DLL em vez da DLL que esperava. Estes ataques são conhecidos como "ataques de pré-carregamento DLL" e são comuns a todos os sistemas operativos que suportam o carregamento dinâmico de bibliotecas DLL partilhadas. O efeito de tais ataques pode ser que um atacante possa executar código no contexto do utilizador que está a executar a aplicação. Quando a aplicação está a ser executada como Administrador, isto pode levar a uma elevação local de privilégios. Sabemos sobre o interesse renovado nestes ataques. Para limitar o efeito que este problema tem nos nossos clientes mútuos, estamos a lançar este documento à comunidade de programadores para garantir que eles sabem deste problema e têm as ferramentas necessárias para resolver o problema nas suas aplicações.
Resumo
Descrição dos ataques de pré-carregamento da DLL
Ataques baseados em LoadLibrary
Quando uma aplicação carrega dinamicamente uma DLL sem especificar um caminho completamente qualificado, o Windows tenta localizar esta DLL ao procurar linearmente através de um conjunto bem definido de diretórios, conhecido como Ordem de Pesquisa de DLL. Se o Windows localizar a DLL na Ordem de Pesquisa da DLL, carregará essa DLL. No entanto, se o Windows não encontrar a DLL em nenhum dos diretórios na Ordem de Pesquisa de DLL, devolverá uma falha na operação de carregamento de DLL. Segue-se a Ordem de Pesquisa de DLL para as funções LoadLibrary e LoadLibraryEx , que são utilizadas para carregar DLLs dinamicamente:
- O diretório a partir do qual a aplicação carregou
- O diretório do sistema
- O diretório de sistema de 16 bits
- O diretório do Windows
- O diretório de trabalho atual (CWD)
- Os diretórios listados na variável de ambiente PATH
Tenha em conta o seguinte cenário:
- Uma aplicação carrega uma DLL sem especificar um caminho completamente qualificado que espera encontrar no CWD da aplicação.
- A aplicação está totalmente preparada para processar o caso quando não encontrar a DLL.
- O atacante sabe estas informações sobre a aplicação e controla o CWD.
- O atacante copia a sua própria versão especialmente concebida da DLL no CWD. Isto pressupõe que o atacante tem permissão para o fazer.
- O Windows procura nos diretórios na Ordem de Pesquisa de DLL e localiza a DLL no CWD da aplicação.
Neste cenário, a DLL especialmente concebida é executada na aplicação e obtém os privilégios do utilizador atual.
Recomendação
Para evitar este ataque, as aplicações podem remover o diretório de trabalho (CWD) atual do caminho de pesquisa DLL ao chamar a API SetDllDirectory com uma cadeia vazia (""). Se uma aplicação depender do carregamento de uma DLL a partir do diretório atual, obtenha o diretório de trabalho atual e utilize-o para transmitir um caminho completamente qualificado do LoadLibrary.
Também temos conhecimento de que alguns programadores utilizam o LoadLibrary para validar se existe uma DLL específica para determinar que versão do Windows está a ser executada pelo utilizador. Deve estar ciente de que isto pode tornar a aplicação vulnerável. Se a biblioteca afetada não existir na versão do Windows na qual a aplicação é executada, um atacante poderá introduzir uma biblioteca com esse mesmo nome no CWD. Recomendamos vivamente que não utilize esta técnica. Em vez disso, utilize as técnicas recomendadas descritas no artigo da MSDN, "Obter a Versão do Sistema".
Uma aplicação que carrega plug-ins de terceiros e que não pode forçar os plug-ins a utilizar um caminho qualificado para as chamadas LoadLibrary deve chamar SetDllDirectory("") para remover CWD e, em seguida, chamar SetDllDirectory("localização de instalação do plug-in") para adicionar o diretório de instalação do plug-in ao caminho de pesquisa DLL.
Ataques baseados em SearchPath
Existe um ataque semelhante quando uma aplicação utiliza a API SearchPath para localizar uma DLL e carregar dinamicamente o caminho devolvido pelo SearchPath. Segue-se a ordem de pesquisa predefinida para a API SearchPath:
- O diretório a partir do qual a aplicação carregou
- O diretório de trabalho atual (CWD)
- O diretório do sistema
- O diretório de sistema de 16 bits
- O diretório do Windows
- Os diretórios listados na variável de ambiente PATH
Não recomendamos este padrão porque não é seguro. Não recomendamos a função SearchPath como um método para localizar um ficheiro de .dll se a utilização pretendida do resultado estiver numa chamada para a função LoadLibrary. Isto pode resultar na localização do ficheiro .dll errado porque a ordem de pesquisa da função SearchPath difere da ordem de pesquisa utilizada pela função LoadLibrary. Se tiver de localizar e carregar um ficheiro .dll, utilize a função LoadLibrary.
ShellExecute e CreateProcess
Também podem existir variações destes problemas quando os programadores chamam funções semelhantes, como ShellExecute e CreateProcess , para carregar executáveis externos. Recomendamos que os programadores tenham cuidado quando estiverem a carregar binários e especifiquem o caminho completamente qualificado. Isto deve representar menos complexidade quando carrega um binário em vez de uma biblioteca.
Passos recomendados para programadores de software
Recomendamos que os programadores façam o seguinte:
Valide as respetivas aplicações para instâncias de cargas de bibliotecas não seguras (os exemplos de cada um são fornecidos mais à frente neste artigo). Estes tipos de ficheiros incluem:
- A utilização do SearchPath para identificar a localização de uma biblioteca ou componente.
- A utilização do LoadLibrary para identificar a versão do sistema operativo.
Utilize caminhos completamente qualificados para todas as chamadas para LoadLibrary, CreateProcess e ShellExecute, onde puder.
Implemente chamadas para SetDllDirectory com uma cadeia vazia ("") para remover o diretório de trabalho atual da ordem de pesquisa DLL predefinida onde é necessário. Tenha em atenção que SetDllDirectory afeta todo o processo. Por conseguinte, deve fazê-lo uma vez no início da inicialização do processo, não antes e depois das chamadas para LoadLibrary. Uma vez que SetDllDirectory afeta todo o processo, vários threads que chamam SetDllDirectory com valores diferentes podem causar um comportamento indefinido. Além disso, se o processo for concebido para carregar DLLs de terceiros, serão necessários testes para determinar se a criação de uma definição ao nível do processo causará incompatibilidades. Um problema conhecido é que, quando uma aplicação depende de Visual Basic for Applications, uma definição ao nível do processo pode causar incompatibilidades.
Utilize a função SetSearchPathMode para ativar o modo de pesquisa de processo seguro para o processo. Esta ação move o diretório de trabalho atual para o último local na lista de pesquisa do SearchPath para a duração do processo.
Evite utilizar o SearchPath para verificar a existência de uma DLL sem especificar um caminho completamente qualificado, mesmo que o modo de pesquisa segura esteja ativado, uma vez que ainda pode levar a ataques de Pré-carregamento da DLL.
Documentação de orientação sobre a identificação de cargas de biblioteca não seguras
No código fonte, seguem-se exemplos de cargas de biblioteca não seguras:
No exemplo de código seguinte, a aplicação procura "schannel.dll" ao utilizar o caminho de pesquisa menos seguro. Se um atacante conseguir colocar schannel.dll no CWD, será carregado mesmo antes de a aplicação procurar nos diretórios do Windows a biblioteca adequada.
DWORD retval = SearchPath(NULL, "schannel", ".dll", err, result, NULL); HMODULE handle = LoadLibrary(result);No exemplo de código seguinte, a aplicação tenta carregar a biblioteca a partir das várias localizações da aplicação e do sistema operativo descritas no início deste documento para a chamada LoadLibrary(). Se existir algum risco de o ficheiro não estar presente, a aplicação poderá tentar carregar o ficheiro a partir do diretório de trabalho atual. Este cenário é ligeiramente menos perigoso do que o exemplo anterior. No entanto, continua a expor o utilizador da aplicação ao risco se o ambiente não for completamente previsível.
HMODULE handle = LoadLibrary("schannel.dll");
Seguem-se exemplos de cargas de biblioteca melhores e mais seguras:
No exemplo de código seguinte, a biblioteca é carregada diretamente através de um caminho completamente qualificado. Não existe qualquer risco de o atacante introduzir código malicioso, a menos que já tenha permissões de escrita no diretório de destino da aplicação.
HMODULE handle = LoadLibrary("c:\\windows\\system32\\schannel.dll");Nota Para obter informações sobre como determinar o diretório do sistema, veja os seguintes recursos:
GetSystemDirectory
http://msdn.microsoft.com/en-us/library/ms724373%28VS.85%29.aspx SHGetKnownFolderPath
http://msdn.microsoft.com/en-us/library/bb762188%28v=VS.85%29.aspxNo exemplo de código seguinte, o diretório de trabalho atual é removido do caminho de pesquisa antes de chamar LoadLibrary. Isto reduz significativamente o risco, uma vez que o atacante teria de controlar o diretório da aplicação, o diretório do Windows ou quaisquer diretórios especificados no caminho do utilizador para utilizar um ataque de pré-carregamento de DLL.
SetDllDirectory (""); HMODULE handle = LoadLibrary("schannel.dll");Em todos os sistemas que instalaram a atualização de segurança 963027 (descrito em MS09-014), o código seguinte moveria permanentemente o CWD para o último local na ordem de pesquisa. Quaisquer chamadas posteriores para a função SetSearchPathMode a partir desse processo que tentem alterar o modo de pesquisa falharão.
SetDllDirectory (""); HMODULE handle = LoadLibrary("schannel.dll");No exemplo de código seguinte, o diretório de trabalho atual é removido do caminho de pesquisa antes de chamar LoadLibrary. Isto reduz significativamente o risco, uma vez que o atacante teria de controlar o diretório da aplicação, o diretório do windows ou quaisquer diretórios especificados no caminho do utilizador para utilizar um ataque de pré-carregamento de DLL.
SetSearchPathMode (BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT ); HMODULE handle = LoadLibrary("schannel.dll");
Utilizar o Monitor de Processos para detetar cargas não seguras de forma dinâmica
A Microsoft publica uma ferramenta denominada Monitor de Processos. Esta ferramenta permite que os programadores e administradores controlem de perto o comportamento de um processo em execução. O Monitor de Processos pode ser utilizado para detetar dinamicamente se uma das suas aplicações pode estar vulnerável a este tipo de problema.
Para transferir o Monitor de Processos, visite a seguinte página Web da Microsoft:
http://technet.microsoft.com/en-us/sysinternals/bb896645.aspxTente iniciar a sua aplicação com o CWD definido para um diretório específico. Por exemplo, faça duplo clique num ficheiro que tenha uma extensão cujo processador de ficheiros está atribuído à sua aplicação.
Configure o Monitor de Processos com os seguintes filtros:
Se um caminho vulnerável estiver a ser atingido, verá algo semelhante ao seguinte:
A chamada para a partilha de ficheiros remota para carregar uma DLL indica que se trata de um programa vulnerável.
Mais Informações
Para obter mais informações, visite as seguintes páginas Web da Microsoft:
Ordem de Pesquisa da Biblioteca de Ligações Dinâmicas
http://msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx Documentação do MSDN sobre a função SearchPath
http://msdn.microsoft.com/en-us/library/aa365527(VS.85).aspx Documentação do MSDN sobre a função LoadLibrary
http://msdn.microsoft.com/en-us/library/ms684175(VS.85).aspx Documentação do MSDN sobre a função SetDllDirectory
http://msdn.microsoft.com/en-us/library/ms686203(VS.85).aspx Documentação do MSDN sobre a função SetSearchPathMode
http://msdn.microsoft.com/en-us/library/dd266735(VS.85).aspx Mensagem de blogue de David Leblanc, Engenheiro de Segurança Principal com o Microsoft Office
http://blogs.msdn.com/b/david_leblanc/archive/2008/02/20/dll-preloading-attacks.aspx Publicação de blogue de Andrew Roths, equipa de Engenharia da MSRC sobre ataques de pré-carregamento da DLL