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:
- O diretório do qual o aplicativo foi carregado.
- O diretório do sistema.
- O diretório do sistema de 16 bits.
- O diretório do Windows.
- O diretório atual.
- 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
- Inicie o Monitor do Processo.
- 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
- 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
- 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.
- 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.