Segurança da biblioteca de vínculo dinâmico

Quando um aplicativo carrega dinamicamente uma biblioteca de vínculo dinâmico sem especificar um nome de caminho totalmente qualificado, o Windows tenta localizar a DLL pesquisando um conjunto bem definido de diretórios em uma ordem específica, conforme descrito em Ordem de Pesquisa da Biblioteca de Vínculo Dinâmico. Se um invasor obtiver o controle de um dos diretórios no caminho de pesquisa da DLL, ele poderá colocar uma cópia mal-intencionada da DLL nesse diretório. Às vezes, isso é chamado de ataque de pré-carregamento de DLL ou um ataque de plantio binário. Se o sistema não encontrar uma cópia legítima da DLL antes de pesquisar o diretório comprometido, ele carregará a DLL mal-intencionada. Se o aplicativo estiver em execução com privilégios de administrador, o invasor poderá ter êxito na elevação de privilégio local.

Por exemplo, suponha que um aplicativo foi projetado para carregar uma DLL do diretório atual do usuário e falhar normalmente se a DLL não for encontrada. O aplicativo chama LoadLibrary apenas com o nome da DLL, o que faz com que o sistema pesquise a DLL. Supondo que o modo de pesquisa de DLL seguro esteja habilitado e o aplicativo não esteja usando uma ordem de pesquisa alternativa, o sistema pesquisa diretórios na seguinte ordem:

  1. O diretório do qual o aplicativo foi carregado.
  2. O diretório do sistema.
  3. O diretório do sistema de 16 bits.
  4. O diretório do Windows.
  5. O diretório atual.
  6. Os diretórios listados na variável de ambiente PATH.

Continuando o exemplo, um invasor com conhecimento do aplicativo obtém o controle do diretório atual e coloca uma cópia mal-intencionada da DLL nesse diretório. Quando o aplicativo emite a chamada LoadLibrary , o sistema pesquisa a DLL, localiza a cópia mal-intencionada da DLL no diretório atual e a carrega. A cópia mal-intencionada da DLL é executada no aplicativo e obtém os privilégios do usuário.

Os desenvolvedores podem ajudar a proteger seus aplicativos contra ataques de pré-carregamento de DLL seguindo estas diretrizes:

  • Sempre que possível, especifique um caminho totalmente qualificado ao usar as funções LoadLibrary, LoadLibraryEx, CreateProcess ou ShellExecute .

  • Use os sinalizadores LOAD_LIBRARY_SEARCH com a função LoadLibraryEx ou use esses sinalizadores com a função SetDefaultDllDirectories para estabelecer uma ordem de pesquisa de DLL para um processo e, em seguida, use as funções AddDllDirectory ou SetDllDirectory para modificar a lista. Para obter mais informações, confira Ordem de pesquisa da biblioteca de vínculo dinâmico.

    Windows 7, Windows Server 2008 R2, Windows Vista e Windows Server 2008: Esses sinalizadores e funções estão disponíveis em sistemas com KB2533623 instalados.

  • Em sistemas com KB2533623 instalados, use os sinalizadores LOAD_LIBRARY_SEARCH com a função LoadLibraryEx ou use esses sinalizadores com a função SetDefaultDllDirectories para estabelecer uma ordem de pesquisa de DLL para um processo e, em seguida, use as funções AddDllDirectory ou SetDllDirectory para modificar a lista. Para obter mais informações, confira Ordem de pesquisa da biblioteca de vínculo dinâmico.

  • Considere usar o redirecionamento de DLL ou um manifesto para garantir que seu aplicativo use a DLL correta.

  • Ao usar a ordem de pesquisa padrão, verifique se o modo de pesquisa de DLL seguro está habilitado. Isso coloca o diretório atual do usuário posteriormente na ordem de pesquisa, aumentando as chances de o Windows encontrar uma cópia legítima da DLL antes de uma cópia mal-intencionada. O modo de pesquisa de DLL segura é habilitado por padrão, começando com o Windows XP com Service Pack 2 (SP2) e é controlado pelo HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\ valor do registro SafeDllSearchMode. Para obter mais informações, confira Ordem de pesquisa da biblioteca de vínculo dinâmico.

  • Considere remover o diretório atual do caminho de pesquisa padrão chamando SetDllDirectory com uma cadeia de caracteres vazia (""). Isso deve ser feito uma vez no início da inicialização do processo, não antes e depois de chamadas para LoadLibrary. Lembre-se de que SetDllDirectory afeta todo o processo e que vários threads que chamam SetDllDirectory com valores diferentes podem causar um comportamento indefinido. Se o aplicativo carregar DLLs de terceiros, teste cuidadosamente para identificar quaisquer incompatibilidades.

  • Não use a função SearchPath para recuperar um caminho para uma DLL para uma chamada LoadLibrary subsequente, a menos que o modo de pesquisa de processo seguro esteja habilitado. Quando o modo de pesquisa de processo seguro não está habilitado, a função SearchPath usa uma ordem de pesquisa diferente de LoadLibrary e é provável que primeiro pesquise o diretório atual do usuário para a DLL especificada. Para habilitar o modo de pesquisa de processo seguro para a função SearchPath , use a função SetSearchPathMode com BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE. Isso move o diretório atual para o final da lista de pesquisa searchPath para a vida útil do processo. Observe que o diretório atual não é removido do caminho de pesquisa, portanto, se o sistema não encontrar uma cópia legítima da DLL antes de atingir o diretório atual, o aplicativo ainda estará vulnerável. Assim como acontece com SetDllDirectory, chamar SetSearchPathMode deve ser feito no início da inicialização do processo e afeta todo o processo. Se o aplicativo carregar DLLs de terceiros, teste cuidadosamente para identificar quaisquer incompatibilidades.

  • Não faça suposições sobre a versão do sistema operacional com base em uma chamada LoadLibrary que pesquisa uma DLL. Se o aplicativo estiver em execução em um ambiente em que a DLL não está legitimamente presente, mas uma cópia mal-intencionada da DLL estiver no caminho de pesquisa, a cópia mal-intencionada da DLL poderá ser carregada. Em vez disso, use as técnicas recomendadas descritas em Obtendo a versão do sistema.

A ferramenta Monitor de Processo pode ser usada para ajudar a identificar operações de carregamento de DLL que podem estar vulneráveis. A ferramenta Monitor de Processo pode ser baixada de https://technet.microsoft.com/sysinternals/bb896645.aspx.

O procedimento a seguir descreve como usar o Monitor de Processo para examinar as operações de carregamento de DLL em seu aplicativo.

Para usar o Monitor de Processo para examinar as operações de carregamento de DLL em seu aplicativo

  1. Inicie o Monitor do Processo.
  2. No Monitor de Processo, inclua os seguintes filtros:
    • A operação é CreateFile
    • A operação é LoadImage
    • O caminho contém .cpl
    • O caminho contém .dll
    • O caminho contém .drv
    • O caminho contém .exe
    • O caminho contém .ocx
    • O caminho contém .scr
    • O caminho contém .sys
  3. Exclua os seguintes filtros:
    • O Nome do Processo é procmon.exe
    • O Nome do Processo é Procmon64.exe
    • Nome do Processo é Sistema
    • A operação começa com IRP_MJ_
    • A operação começa com FASTIO_
    • O resultado é SUCCESS
    • O caminho termina com pagefile.sys
  4. Tente iniciar seu aplicativo com o diretório atual definido como um diretório específico. Por exemplo, clique duas vezes em um arquivo com uma extensão cujo manipulador de arquivos é atribuído ao seu aplicativo.
  5. Verifique a saída do Monitor de Processo em busca de caminhos que pareçam suspeitos, como uma chamada para o diretório atual para carregar uma DLL. Esse tipo de chamada pode indicar uma vulnerabilidade em seu aplicativo.