Compartilhar via


Considerações de segurança para reflexão

A reflexão fornece a capacidade de obter informações sobre tipos e membros e acessar membros (ou seja, chamar métodos e construtores, obter e definir valores de propriedade, adicionar e remover manipuladores de eventos e assim por diante). O uso da reflexão para obter informações sobre tipos e membros não é restrito. Todo o código pode usar reflexão para executar as seguintes tarefas:

  • Enumerar tipos e membros e examinar seus metadados.
  • Enumerar e examine os módulos e assemblies.

Usar reflexão para acessar membros está, por outro lado, sujeitos a restrições. A partir do .NET Framework 4, somente o código confiável pode usar a reflexão para acessar membros críticos à segurança. Além disso, somente o código confiável pode usar reflexão para acessar membros não públicos que não estariam diretamente acessíveis ao código compilado. Por fim, o código que utiliza reflexão para acessar um membro seguro-crítico deve possuir todas as permissões que este membro exige, assim como acontece com o código compilado.

Sujeito às permissões necessárias, o código pode usar reflexão para executar os seguintes tipos de acesso:

  • Acesse os membros públicos que não são críticos para segurança.

  • Acesse membros não públicos que estariam acessíveis ao código compilado, desde que não sejam críticos de segurança. Exemplos desses membros não públicos incluem:

    • Membros protegidos de classes base do código de chamada. (Na reflexão, isso é chamado de acesso em nível familiar.)

    • Membros internal (membros Friend no Visual Basic) no assembly do código de chamada. (Na reflexão, isso é chamado de acesso no nível do assembly.)

    • Membros privados de outras instâncias da classe que contém o código de chamada.

Por exemplo, o código executado em um domínio de aplicativo em área restrita é limitado ao acesso descrito nesta lista, a menos que o domínio do aplicativo conceda permissões adicionais.

A partir do .NET Framework 2.0 Service Pack 1, tentar acessar membros que normalmente não podem ser acessados gera uma demanda para o conjunto de concessões do objeto de destino mais ReflectionPermission com o sinalizador ReflectionPermissionFlag.MemberAccess. O código em execução com confiança total (por exemplo, código em um aplicativo que é iniciado a partir da linha de comando) sempre pode satisfazer essas permissões. (Isso está sujeito a limitações no acesso a membros críticos à segurança, conforme descrito posteriormente neste artigo.)

Como opção, um domínio do aplicativo em área restrita pode conceder ReflectionPermission com o sinalizador ReflectionPermissionFlag.MemberAccess, conforme descrito na seção Acessando membros que são normalmente inacessíveis, mais adiante neste artigo.

Acessando membros críticos para segurança

Um membro é crítico para segurança se ele tiver o SecurityCriticalAttribute, se ele pertencer a um tipo que tem o SecurityCriticalAttribute ou se ele está em um assembly crítico para segurança. A partir do .NET Framework 4, as regras para acessar membros críticos de segurança são as seguintes:

  • O código transparente não pode usar a reflexão para acessar membros críticos à segurança, mesmo que o código seja totalmente confiável. Um MethodAccessException, FieldAccessException ou TypeAccessException é gerado.

  • O código em execução com confiança parcial é tratado como transparente.

Essas regras são as mesmas se um membro crítico de segurança é acessado diretamente pelo código compilado ou acessado usando reflexão.

O código do aplicativo executado na linha de comando é executado com total confiança. Desde que não esteja marcado como transparente, ele pode usar reflexão para acessar membros críticos para segurança. Quando o mesmo código é executado com confiança parcial (por exemplo, em um domínio de aplicativo em área restrita), o nível de confiança do assembly determina se ele pode acessar o código crítico de segurança: se o assembly tiver um nome forte e estiver instalado no cache de assembly global, ele será um assembly confiável e poderá chamar membros críticos à segurança. Se não for confiável, ele se tornará transparente mesmo que não tenha sido marcado como transparente e não possa acessar membros críticos à segurança.

Reflexão e transparência

Do .NET Framework 4 em diante, o Common Language Runtime determina o nível de transparência de um tipo ou membro de vários fatores, incluindo o nível de confiança do assembly e o nível de confiança do domínio do aplicativo. A reflexão fornece as propriedades IsSecurityCritical, IsSecuritySafeCritical e IsSecurityTransparent para permitir que você descubra o nível de transparência de um tipo. A tabela a seguir mostra as combinações válidas dessas propriedades.

Nível de segurança IsSecurityCritical IsSecuritySafeCritical IsSecurityTransparent
Crítico true false false
Crítico para segurança true true false
Transparente false false true

Usar essas propriedades é muito mais simples do que examinar as anotações de segurança de um assembly e seus tipos, verificar o nível de confiança atual e tentar duplicar as regras do runtime. Por exemplo, o mesmo tipo pode ser crítico para a segurança quando é executado na linha de comando ou transparente para a segurança quando é executado em um domínio de aplicativo em área isolada.

Há propriedades semelhantes nas classes MethodBase, FieldInfo, TypeBuilder, MethodBuilder e DynamicMethod. (Para outras reflexão e abstrações de emissão de reflexão, os atributos de segurança são aplicados aos métodos associados; por exemplo, no caso de propriedades que são aplicadas aos acessadores de propriedade).

Acessando membros que são normalmente inacessíveis

Para usar a reflexão para invocar membros inacessíveis de acordo com as regras de acessibilidade do common language runtime, seu código deve receber uma das duas permissões:

  • Para permitir que o código invoque qualquer membro não público: seu código deve receber a concessão de ReflectionPermission com o sinalizador ReflectionPermissionFlag.MemberAccess.

    Observação

    Por padrão, a política de segurança nega essa permissão ao código que se origina da Internet. Essa permissão nunca deve ser concedida ao código originário da Internet.

  • Para permitir que o código invoque qualquer membro não público, desde que o conjunto de concessões do assembly que contém o membro invocado seja o mesmo ou um subconjunto do conjunto de concessões do assembly que contém o código de invocação: seu código deve ser concedido ReflectionPermission com o ReflectionPermissionFlag.RestrictedMemberAccess sinalizador.

Por exemplo, suponha que você concedeu permissões da Internet a um domínio do aplicativo mais ReflectionPermission com o sinalizador ReflectionPermissionFlag.RestrictedMemberAccess e, em seguida, executou um aplicativo da Internet com dois assemblies, A e B.

  • O assembly A pode usar reflexão para acessar membros particulares do assembly B, pois o conjunto de concessões do assembly B não inclui permissões que não foram concedidas a A.

  • O Assembly A não pode usar a reflexão para acessar membros privados de assemblies do .NET Framework, como mscorlib.dll, porque mscorlib.dll é totalmente confiável e, portanto, tem permissões que não foram concedidas ao assembly A. Um MemberAccessException é gerado quando a segurança de acesso ao código percorre a pilha em runtime.

Serialização

Para serialização, SecurityPermission com o sinalizador SecurityPermissionAttribute.SerializationFormatter fornece a capacidade de obter e definir os membros de tipos serializáveis, independentemente da acessibilidade. Essa permissão permite que o código descubra e altere o estado privado de uma instância. (Além de receber as permissões apropriadas, o tipo deve ser marcado como serializável em metadados.)

Parâmetros do tipo MethodInfo

Evite escrever membros públicos que utilizam parâmetros MethodInfo, especialmente para código confiável. Esses membros podem ser mais vulneráveis a códigos mal-intencionados. Por exemplo, considere um membro público no código altamente confiável que utiliza um parâmetro MethodInfo. Suponha que o membro público chama indiretamente o método Invoke no parâmetro fornecido. Se o membro público não executar as verificações de permissão necessárias, a chamada para o Invoke método sempre terá êxito, pois o sistema de segurança determina que o chamador é altamente confiável. Mesmo que o código mal-intencionado não tenha permissão para invocar diretamente o método, ele ainda poderá fazê-lo indiretamente chamando o membro público.

Informações de versão

  • A partir do .NET Framework 4, o código transparente não pode usar reflexão para acessar membros críticos à segurança.

  • O ReflectionPermissionFlag.RestrictedMemberAccess sinalizador é introduzido no Service Pack 1 do .NET Framework 2.0. Versões anteriores do .NET Framework requerem a flag ReflectionPermissionFlag.MemberAccess para o código que utiliza reflexão para acessar membros não públicos. Essa é uma permissão que nunca deve ser concedida ao código parcialmente confiável.

  • A partir do .NET Framework 2.0, usar reflexão para obter informações sobre tipos e membros não públicos não requer permissões. Em versões anteriores, o ReflectionPermission com o sinalizador ReflectionPermissionFlag.TypeInformation é obrigatório.

Consulte também