Carregamento seguro de bibliotecas para evitar ataques de pré-carregamento da DLL

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 totalmente qualificado, o Windows tenta localizar o DLL procurando um conjunto bem definido de diretórios. Se um intruso ganhar o controlo de um dos diretórios, podem forçar a aplicação a carregar uma cópia maliciosa do DLL em vez do DLL que estava à espera. Estes ataques são conhecidos como "ataques de pré-carregamento DLL" e são comuns a todos os sistemas operativos que suportam bibliotecas DLL partilhadas dinamicamente. O efeito de tais ataques pode ser que um intruso 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 esta questão tem nos nossos clientes mútuos, estamos a divulgar este documento à comunidade de desenvolvedores para garantir que eles sabem sobre este assunto e têm os instrumentos necessários 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 um DLL sem especificar um caminho totalmente qualificado, o Windows tenta localizar este DLL procurando linearmente através de um conjunto bem definido de diretórios, conhecidos como DLL Search Order. Se o Windows localizar o DLL dentro da Ordem de Pesquisa DLL, carregará esse DLL. No entanto, se o Windows não encontrar o DLL em nenhum dos diretórios da Ordem de Pesquisa DLL, retornará uma falha na operação de carga DLL. Segue-se a Ordem de Pesquisa DLL para as funções LoadLibrarye LoadLibraryEx,que são utilizadas para carregar dinamicamente DLLs:

  1. O diretório a partir do qual a aplicação carregada

  2. O diretório do sistema

  3. O diretório de sistema de 16 bits

  4. O diretório do Windows

  5. O atual diretório de trabalho (CWD)

  6. Os diretórios que estão listados na variável ambiente PATH



Considere o seguinte cenário:


  • Uma aplicação carrega um DLL sem especificar um caminho totalmente qualificado que espera encontrar no CWD da aplicação.

  • O pedido está totalmente preparado para lidar com o caso quando não encontrar o DLL.

  • O intruso conhece esta informação sobre a aplicação e controla o CWD.

  • O agressor copia a sua própria versão especialmente trabalhada do DLL no CWD. Isto pressupõe que o agressor tem permissão para fazer isto.

  • O Windows procura através dos diretórios na Ordem de Pesquisa DLL e encontra o DLL no CWD da aplicação.

Neste cenário, o DLL especialmente trabalhado funciona dentro da aplicação e obtém os privilégios do utilizador atual.

Recomendação

Para prevenir este ataque, as aplicações podem remover o diretório de trabalho atual (CWD) do caminho de pesquisa DLL, chamando a API SetDllDirectory usando uma corda vazia (""). Se uma aplicação depender do carregamento de um DLL do diretório atual, obtenha o diretório de trabalho atual e use-o para passar num caminho totalmente qualificado de LoadLibrary.



Também sabemos que alguns desenvolvedores usam LoadLibrary para validar se um DLL específico está presente para determinar qual a versão do Windows que está a ser executada pelo utilizador. Deve saber que isto pode tornar a aplicação vulnerável. Se a biblioteca afetada não existir na versão do Windows em que a aplicação é executada, um intruso pode introduzir uma biblioteca com o mesmo nome no CWD. Recomendamos vivamente contra a utilização desta técnica. Em vez disso, utilize as técnicas recomendadas que são descritas no artigo da MSDN, "Obter a Versão do Sistema".

Uma aplicação que carregue plugins de terceiros e que não possa forçar os plugins a utilizar um caminho qualificado para as suas chamadas LoadLibrary deve ligar para SetDllDirect("") para remover o CWD e, em seguida, ligar para SetDllDirectory ("plugin install location") para adicionar o diretório de instalação plugin à via de pesquisa DLL.

Ataques baseados em SearchPath

Um ataque semelhante existe quando uma aplicação utiliza a API SearchPath para localizar um DLL e carregar dinamicamente o caminho que é devolvido pelo SearchPath. Segue-se a ordem de pesquisa predefinido para a API SearchPath:

  • O diretório a partir do qual a aplicação carregada

  • O atual diretório de trabalho (CWD)

  • O diretório do sistema

  • O diretório de sistema de 16 bits

  • O diretório do Windows

  • Os diretórios que estão listados na variável ambiente PATH

Não recomendamos este padrão porque não é seguro. Não recomendamos a função SearchPath como um método de localização de um ficheiro .dll se a utilização pretendida da saída 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


Variações destes problemas também podem existir quando os desenvolvedores chamam funções semelhantes, tais como ShellExecutee CreateProcesspara carregar executáveis externos. Recomendamos que os desenvolvedores tenham cuidado quando estão a carregar binários e especifiquem o caminho totalmente qualificado. Isto deve representar menos complexidade quando se carrega um binário em vez de uma biblioteca.

Passos recomendados para desenvolvedores de software

Recomendamos que os desenvolvedores façam o seguinte:

  • Validar as suas aplicações para casos de cargas de biblioteca não-seceis (exemplos de cada um são dados mais tarde neste artigo). Estes incluem o seguinte:

    • 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 totalmente qualificados para todas as chamadas para LoadLibrary, CreateProcess e ShellExecute onde puder.

  • Implementar chamadas para SetDllDirectory com uma corda vazia ("") para remover o diretório de trabalho atual da ordem de pesquisa DLL padrão onde é necessário. Esteja ciente de que o SetDllDirector afeta todo o processo. Portanto, deve fazê-lo uma vez mais cedo na inicialização do processo, não antes e depois de chamadas para LoadLibrary. Como o SetDllDirector afeta todo o processo, vários fios 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 realização de uma definição a nível do processo irá causar incompatibilidades. Um problema conhecido é que quando uma aplicação depende do Base Visual para Aplicações, uma configuração em todo o processo pode causar incompatibilidades.

  • Utilize a função SetSearchPathModepara permitir o modo de pesquisa de processo seguro para o processo. Isto move o diretório de trabalho atual para o último lugar da lista de pesquisa SearchPath para o tempo de vida do processo.

  • Evite utilizar o SearchPath para verificar a existência de um DLL sem especificar um caminho totalmente qualificado, mesmo que o modo de pesquisa seguro esteja ativado, pois isso ainda pode levar a ataques de pré-carregamento DLL.

Orientação sobre a identificação de cargas não-seceis da biblioteca

No código fonte, são exemplos de cargas de biblioteca nãoseceis:

  • No seguinte exemplo de código, a aplicação procura "schannel.dll" utilizando o caminho de pesquisa menos seguro. Se um intruso puder colocar schannel.dll em CWD, será carregado mesmo antes da aplicação procurar nos diretórios do Windows para a biblioteca apropriada.

    DWORD retval = SearchPath(NULL, "schannel", ".dll", err, result, NULL); 
    HMODULE handle = LoadLibrary(result);
  • No seguinte exemplo de código, a aplicação tenta carregar a biblioteca a partir das várias aplicações e locais do sistema operativo descritos no início deste documento para a chamada LoadLibrary(). Se houver algum risco de que o ficheiro não esteja presente, o pedido pode tentar carregar o ficheiro do diretório de trabalho atual. Este cenário é ligeiramente menos perigoso do que o exemplo anterior. No entanto, ainda expõe 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 bibliotecas melhores e mais seguras:

  • No seguinte exemplo de código, a biblioteca é carregada diretamente utilizando um caminho totalmente qualificado. Não existe qualquer risco de o intruso introduzir código malicioso a menos que ele já tenha permissões de escrita para o diretório alvo da aplicação.

    HMODULE handle = LoadLibrary("c:\\windows\\system32\\schannel.dll");



    Nota Para obter informações sobre como determinar o diretório do sistema, consulte os seguintes recursos:

    GetSystemDirectory

    http://msdn.microsoft.com/en-us/library/ms724373%28VS.85%29.aspxSHGetKnownFolderPath

    http://msdn.microsoft.com/en-us/library/bb762188%28v=VS.85%29.aspx

  • No seguinte exemplo de código, o diretório de trabalho atual é removido do caminho de pesquisa antes de chamar LoadLibrary. Isto reduz significativamente o risco, uma vez que o intruso teria de controlar o diretório de aplicações, o diretório do Windows ou quaisquer diretórios especificados no caminho do utilizador para utilizar um ataque de pré-carregamento DLL.

    SetDllDirectory ("");
    HMODULE handle = LoadLibrary("schannel.dll");
  • Em todos os sistemas que tenham instalado a atualização de segurança 963027 (descrito em MS09-014),o seguinte código iria mover permanentemente a CWD para o último local da ordem de pesquisa. Quaisquer chamadas posteriores para a função SetSearchPathMode a partir de dentro desse processo que tentem alterar o modo de pesquisa falharão.

    SetDllDirectory ("");
    HMODULE handle = LoadLibrary("schannel.dll");
  • No seguinte exemplo de código, o diretório de trabalho atual é removido do caminho de pesquisa antes de chamar LoadLibrary. Isto reduz significativamente o risco, uma vez que o intruso teria de controlar o diretório de aplicações, o diretório do windows ou quaisquer diretórios especificados no caminho do utilizador para utilizar um ataque de pré-carregamento DLL.

    SetSearchPathMode (BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT );
    HMODULE handle = LoadLibrary("schannel.dll");

Utilizar o Monitor de Processo para detetar dinâmicamente cargas não-inseguras

A Microsoft publica uma ferramenta chamada Process Monitor. Esta ferramenta permite que os desenvolvedores e administradores acompanhem de perto o comportamento de um processo de execução. O Monitor de Processos pode ser usado para detetar dinamicamente se uma das suas aplicações pode estar vulnerável a este tipo de problema.

  • Para descarregar o Process Monitor, visite a seguinte página web da Microsoft:

    http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx

  • Tente iniciar a sua aplicação utilizando o conjunto CWD para um diretório específico. Por exemplo, clique duas vezes num ficheiro que tenha uma extensão cujo manipulador de ficheiros está atribuído à sua aplicação.

  • Configurar o Monitor de Processos com os seguintes filtros:



    texto alternativo

  • Se um caminho vulnerável estiver a ser atingido, verá algo semelhante ao seguinte: texto alternativo

    A chamada para a partilha de ficheiros remotos para carregar um DLL indica que este é um programa vulnerável.

Mais Informações

Para mais informações, visite as seguintes páginas web da Microsoft:

Dynamic Link Library Search Order

http://msdn.microsoft.com/en-us/library/ms682586 (VS.85).aspxDocumentação MSDN sobre a função SearchPath

http://msdn.microsoft.com/en-us/library/aa365527 (VS.85).aspxDocumentação MSDN sobre a função LoadLibrary

http://msdn.microsoft.com/en-us/library/ms684175 (VS.85).aspxDocumentação MSDN sobre a função SetDllDirectory

http://msdn.microsoft.com/en-us/library/ms686203 (VS.85).aspxDocumentação MSDN sobre a função SetSearchPathMode

http://msdn.microsoft.com/en-us/library/dd266735 (VS.85).aspxBlog post by David Leblanc, Principal Security Engineer with Microsoft Office

http://blogs.msdn.com/b/david_leblanc/archive/2008/02/20/dll-preloading-attacks.aspxPost de blog de Andrew Roths, equipa de engenharia da MSRC em ataques de pré-carregamento DLL

http://blogs.technet.com/b/srd/archive/2009/04/14/ms09-014-addressing-the-safari-carpet-bomb-vulnerability.aspx

Recursos adicionais

Precisa de mais ajuda?

Aumente os seus conhecimentos
Explore as formações
Seja o primeiro a obter novas funcionalidades
Aderir ao Microsoft insiders

As informações foram úteis?

Obrigado pelos seus comentários!

Obrigado pelo seu feedback! Parece que poderá ser benéfico reencaminhá-lo para um dos nossos agentes de suporte do Office.

×