Carregamento seguro de bibliotecas para evitar ataques de pré-carregamento de DLLs

Artigo: 2389418 - Ver produtos para os quais este artigo se aplica.
Expandir tudo | Reduzir tudo

Nesta página

Sumário

Quando uma aplicação carrega uma DLL (Dynamic Link Library) dinamicamente sem especificar um caminho totalmente qualificado, o Windows tenta localizar a DLL procurando num conjunto bem definido de directórios. Se um atacante obtiver o controlo de um dos directórios, poderá forçar a aplicação a carregar uma cópia maliciosa da DLL, em vez da DLL esperada. Estes ataques são conhecidos como “ataques de pré-carregamento de DLLs” e são comuns a todos os sistemas operativos que suportam o carregamento de bibliotecas de DLL partilhadas dinamicamente. Estes ataques podem permitir que um atacante execute código no contexto do utilizador que está a executar a aplicação. Quando a aplicação está a ser executada como Administrador, tal pode dar origem a uma elevação local de privilégios. Temos conhecimento do interesse renovado nestes ataques. Para limitar o efeito deste problema nos nossos clientes mútuos, a Microsoft publica este documento para a comunidade de programadores, de forma a certificar-se de que estes têm conhecimento do problema e dispõem das ferramentas necessárias para o resolver nas respectivas aplicações.

Mais Informação

Descrição dos ataques de pré-carregamento de DLLs

Ataques baseados em LoadLibrary

Quando uma aplicação carrega uma DLL dinamicamente sem especificar um caminho totalmente qualificado, o Windows tenta localizar esta DLL procurando linearmente num conjunto bem definido de directórios, conhecido como Ordem de Procura de DLL. Se o Windows localizar a DLL na Ordem de Procura de DLL, irá carregar essa DLL. No entanto, se o Windows não localizar a DLL em nenhum dos directórios da Ordem de Procura de DLL, devolverá uma falha relativamente à operação de carregamento da DLL. Segue-se a Ordem de Procura de DLL das funções LoadLibrarye LoadLibraryEx, que são utilizadas para carregar DLLs dinamicamente:
  1. O directório a partir do qual a aplicação foi carregada
  2. O directório do sistema
  3. O directório do sistema de 16 bits
  4. O directório do Windows
  5. O directório de trabalho actual (CWD)
  6. Os directórios que aparecem listados na variável de ambiente PATH
Considere o seguinte cenário:
  • Uma aplicação carrega uma DLL sem especificar um caminho totalmente qualificado que espera encontrar no directório de trabalho actual da aplicação.
  • A aplicação está totalmente preparada para lidar com a situação quando não localiza a DLL.
  • O atacante tem conhecimento destas informações sobre a aplicação e controla o directório de trabalho actual.
  • O atacante copia a sua versão especialmente concebida da DLL para o directório de trabalho actual. Este procedimento pressupõe que o atacante tem permissões para efectuar a operação.
  • O Windows procura nos directórios da Ordem de Procura de DLL e localiza a DLL no directório de trabalho actual da aplicação.
Neste cenário, a DLL especialmente concebida é executada na aplicação e obtém os privilégios do utilizador actual.

Recomendação
Para evitar este ataque, as aplicações podem remover o directório de trabalho actual (CWD) do caminho de procura de DLLs através da chamada da API SetDllDirectory com uma cadeia vazia (“”). Se uma aplicação depender do carregamento de uma DLL a partir do directório actual, obtenha o directório de trabalho actual e utilize-o para passar um caminho totalmente qualificado de LoadLibrary.

Também sabemos que alguns programadores utilizam LoadLibrary para validar a presença de uma DLL específica de forma a determinar a versão do Windows que está a ser executada pelo utilizador. Deve ter em atenção que isto pode tornar a aplicação vulnerável. Se a biblioteca afectada não existir na versão do Windows em que está a executar a aplicação, um atacante poderá introduzir uma biblioteca com esse mesmo nome no directório de trabalho actual. A Microsoft recomenda 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 carregue plug-ins de terceiros e que não consiga forçar os plug-ins a utilizarem um caminho qualificado para as chamadas de LoadLibrary, deverá chamar SetDllDirectory(“”) para remover o directório de trabalho actual e, em seguida, chamar SetDllDirectory(“localização de instalação do plug-in”) para adicionar o directório de instalação do plug-in ao caminho de procura de DLLs.

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 por SearchPath. Segue-se a ordem de procura predefinida para a API SearchPath:
  • O directório a partir do qual a aplicação foi carregada
  • O directório de trabalho actual (CWD)
  • O directório do sistema
  • O directório do sistema de 16 bits
  • O directório do Windows
  • Os directórios que aparecem listados na variável de ambiente PATH
Este padrão não é recomendado por não ser seguro. Não recomendamos a utilização da função SearchPath como um método de localização de um ficheiro .dll se a utilização prevista dos resultados da mesma for uma chamada da função LoadLibrary. O resultado de tal procedimento pode ser a localização do ficheiro .dll errado, uma vez que a ordem de procura da função SearchPath é diferente da ordem de procura utilizada pela função LoadLibrary. Se tiver de localizar e carregar um ficheiro .dll, utilize a função LoadLibrary.

ShellExecute e CreateProcess

Poderão igualmente existir variações destes problemas quando os programadores chamam funções semelhantes como ShellExecutee CreateProcesspara carregar executáveis externos. Recomendamos que os programadores tenham cuidado quando carregarem binários e especificarem o caminho totalmente qualificado. Este processo deverá ser menos complexo quando carregar um binário em vez de uma biblioteca.

Passos recomendados para os programadores de software

Recomendamos que os programadores procedam da seguinte forma:
  • Validem as aplicações nos casos de carregamentos de bibliotecas não seguros (poderá consultar exemplos de cada um mais adiante neste artigo). Estes incluem o seguinte:
    • A utilização de SearchPath para identificar a localização de uma biblioteca ou de um componente.
    • A utilização de LoadLibrary para identificar a versão do sistema operativo.
  • Utilizem caminhos totalmente qualificados para todas as chamadas de LoadLibrary, CreateProcess e ShellExecute, sempre que for possível.
  • Implementem chamadas de SetDllDirectory com uma cadeia vazia (“”) para remover o directório de trabalho actual da ordem de procura de DLLs predefinida, quando for necessário. Tenha em atenção que SetDllDirectory afecta todo o processo. Por conseguinte, deve efectuar este procedimento uma vez logo no início do processo de inicialização, e não antes nem depois das chamadas de LoadLibrary. Uma vez que SetDllDirectory afecta todo o processo, se vários threads chamarem SetDllDirectory com valores diferentes, tal poderá provocar um comportamento inesperado. Além disso, se o processo estiver concebido para carregar DLLs de terceiros, será necessário efectuar testes para determinar se a criação de uma definição ao nível do processo poderá provocar incompatibilidades. Existe um problema conhecido que consiste no facto de, quando uma aplicação depende do Visual Basic for Applications, uma definição ao nível do processo poder provocar incompatibilidades.
  • Utilizem a função SetSearchPathModepara activar o modo de procura segura de processos para o processo. Esta opção move o directório de trabalho actual para o último lugar na lista de procura SearchPath enquanto durar o processo.
  • Evitem utilizar SearchPath para verificar a existência de uma DLL sem especificar um caminho totalmente qualificado, mesmo que o modo de pesquisa segura esteja activado, uma vez que tal pode levar a ataques de pré-carregamento de DLLs.

Orientações sobre como identificar carregamentos de bibliotecas não seguros

No código fonte, eis alguns exemplos de carregamentos de bibliotecas não seguros:
  • No seguinte código de exemplo, a aplicação procura “schannel.dll” utilizando o caminho de procura menos seguro. Se um atacante puder colocar schannel.dll no directório de trabalho actual, esta será carregada antes de a aplicação procurar a biblioteca adequada nos directórios do Windows.
    DWORD retval = SearchPath(NULL, "schannel", ".dll", err, result, NULL); 
    HMODULE handle = LoadLibrary(result);
  • No seguinte código de exemplo, a aplicação tenta carregar a biblioteca a partir das várias localizações de aplicações e sistemas operativos descritas no início deste documento para a chamada LoadLibrary(). Se existir algum risco de o ficheiro não estar presente, a aplicação pode tentar carregar o ficheiro a partir do directório de trabalho actual. Este cenário é ligeiramente menos perigoso do que o do exemplo anterior. No entanto, coloca o utilizador da aplicação em risco se o ambiente não for totalmente previsível.
    HMODULE handle = LoadLibrary("schannel.dll");
Seguem-se exemplos de carregamentos de bibliotecas melhores e mais seguros:
  • No seguinte código de exemplo, a biblioteca é carregada directamente utilizando um caminho totalmente qualificado. Não há qualquer risco de o atacante introduzir código malicioso, a menos que tenha permissões de escrita para o directório de destino da aplicação.
    HMODULE handle = LoadLibrary("c:\\windows\\system32\\schannel.dll");


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

    GetSystemDirectory
    http://msdn.microsoft.com/pt-pt/library/ms724373(v=VS.85).aspx
    SHGetKnownFolderPath
    http://msdn.microsoft.com/pt-pt/library/bb762188%28v=VS.85%29.aspx
  • No seguinte código de exemplo, o directório de trabalho actual foi removido do caminho de procura antes de chamar LoadLibrary. Esta opção reduz significativamente o risco, uma vez que o atacante teria de controlar o directório da aplicação, o directório do Windows ou quaisquer directórios especificados no caminho do utilizador para utilizar um ataque de pré-carregamento de DLLs.
    SetDllDirectory ("");
    HMODULE handle = LoadLibrary("schannel.dll");
  • Em todos os sistemas que tenham a actualização de segurança 963027 instalada (descrita em MS09-014), o seguinte código deslocará de forma permanente o directório de trabalho actual para o último lugar na ordem de pesquisa. Quaisquer chamadas posteriores da função SetSearchPathMode a partir do interior desse processo que tentem alterar o modo de procura falharão.
    
    
    SetDllDirectory ("");
    HMODULE handle = LoadLibrary("schannel.dll");
  • No seguinte código de exemplo, o directório de trabalho actual foi removido do caminho de procura antes de chamar LoadLibrary. Esta opção reduz significativamente o risco, uma vez que o atacante teria de controlar o directório da aplicação, o directório do Windows ou quaisquer directórios especificados no caminho do utilizador para utilizar um ataque de pré-carregamento de DLLs.
    SetSearchPathMode (BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT );
    HMODULE handle = LoadLibrary("schannel.dll");

Utilizar o Monitor do Processo para detectar dinamicamente carregamentos não seguros

A Microsoft publica uma ferramenta denominada Monitor do Processo. Esta ferramenta permite que os programadores e os administradores controlem rigorosamente o comportamento de um processo em execução. O Monitor do Processo pode ser utilizado para detectar dinamicamente se uma das aplicações pode ser vulnerável a este tipo de problema.
  • Para transferir o Monitor do Processo, visite a seguinte página Web da Microsoft:
    http://technet.microsoft.com/pt-pt/sysinternals/bb896645(en-us).aspx
  • Tente iniciar a aplicação utilizando o directório de trabalho actual definido como um directório específico. Por exemplo, faça duplo clique num ficheiro que tenha uma extensão cuja rotina de tratamento de ficheiros esteja atribuída à aplicação.
  • Configure o Monitor do Processo com os seguintes filtros:
    Reduzir esta imagemExpandir esta imagem
    Imagem dos filtros do monitor do processo
  • Se estiver a ser utilizado um caminho vulnerável, verá algo semelhante ao seguinte exemplo:
    Reduzir esta imagemExpandir esta imagem
    Imagem 2 dos filtros do monitor do processo


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

Recursos adicionais

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

Ordem de Procura Dynamic Link Library
http://msdn.microsoft.com/pt-pt/library/ms682586(VS.85).aspx
Documentação da MSDN sobre a função SearchPath
http://msdn.microsoft.com/pt-pt/library/aa365527(VS.85).aspx
Documentação da MSDN sobre a função LoadLibrary
http://msdn.microsoft.com/pt-pt/library/ms684175(VS.85).aspx
Documentação da MSDN sobre a função SetDllDirectory
http://msdn.microsoft.com/pt-pt/library/ms686203(VS.85).aspx
Documentação da MSDN sobre a função SetSearchPathMode
http://msdn.microsoft.com/pt-pt/library/dd266735(VS.85).aspx
Artigo do blogue de David Leblanc, Engenheiro de Segurança Principal do Microsoft Office
http://blogs.msdn.com/b/david_leblanc/archive/2008/02/20/dll-preloading-attacks.aspx
Artigo do blogue de Andrew Roths, equipa de Engenharia de MSRC dedicada aos ataques de pré-carregamento de DLLs
http://blogs.technet.com/b/srd/archive/2009/04/14/ms09-014-addressing-the-safari-carpet-bomb-vulnerability.aspx

Propriedades

Artigo: 2389418 - Última revisão: segunda-feira, 30 de Agosto de 2010 - Revisão: 2.0
A informação contida neste artigo aplica-se a:
  • Windows 7 Enterprise
  • Windows 7 Home Basic
  • Windows 7 Home Premium
  • Windows 7 Professional
  • Windows 7 Ultimate
  • Windows Server 2008 R2 Standard
  • Windows Server 2008 R2 Enterprise
  • Windows Server 2008 R2 Datacenter
  • Windows Server 2008 Service Pack 2 nas seguintes plataformas
    • Windows Server 2008 for Itanium-Based Systems
    • Windows Server 2008 Datacenter
    • Windows Server 2008 Enterprise
    • Windows Server 2008 Standard
    • Windows Web Server 2008
  • Windows Server 2008 for Itanium-Based Systems
  • Windows Server 2008 Datacenter
  • Windows Server 2008 Enterprise
  • Windows Server 2008 Standard
  • Windows Web Server 2008
  • Windows Vista Service Pack 2 nas seguintes plataformas
    • Windows Vista Business
    • Windows Vista Enterprise
    • Windows Vista Home Basic
    • Windows Vista Home Premium
    • Windows Vista Starter
    • Windows Vista Ultimate
    • Windows Vista Enterprise 64-bit edition
    • Windows Vista Home Basic 64-bit edition
    • Windows Vista Home Premium 64-bit edition
    • Windows Vista Ultimate 64-bit edition
    • Windows Vista Business 64-bit edition
  • Windows Vista Service Pack 1 nas seguintes plataformas
    • Windows Vista Business
    • Windows Vista Enterprise
    • Windows Vista Home Basic
    • Windows Vista Home Premium
    • Windows Vista Starter
    • Windows Vista Ultimate
    • Windows Vista Enterprise 64-bit edition
    • Windows Vista Home Basic 64-bit edition
    • Windows Vista Home Premium 64-bit edition
    • Windows Vista Ultimate 64-bit edition
    • Windows Vista Business 64-bit edition
  • Microsoft Windows Server 2003 Service Pack 2 nas seguintes plataformas
    • Microsoft Windows Server 2003 Standard Edition
    • Microsoft Windows Server 2003 Enterprise Edition
    • Microsoft Windows Server 2003 Datacenter Edition
    • Microsoft Windows Server 2003 Web Edition
    • Microsoft Windows Server 2003, Datacenter x64 Edition
    • Microsoft Windows Server 2003, Enterprise x64 Edition
    • Microsoft Windows Server 2003, Standard x64 Edition
    • Microsoft Windows XP Professional x64 Edition
    • Microsoft Windows Server 2003, Datacenter Edition for Itanium-Based Systems
    • Microsoft Windows Server 2003, Enterprise Edition for Itanium-based Systems
  • Microsoft Windows XP Service Pack 3 nas seguintes plataformas
    • Microsoft Windows XP Home Edition
    • Microsoft Windows XP Professional Edition
Palavras-chave: 
atdownload kbbug kbexpertiseinter kbfix kbsecbulletin kbsecurity kbsecvulnerability KB2389418

Submeter comentários