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

O Reflection 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 a reflexão para executar as seguintes tarefas:

  • Enumere tipos e membros e examine seus metadados.
  • Enumerar e examinar componentes e módulos.

O uso da reflexão para aceder aos membros, por outro lado, está sujeito a restrições. A partir do .NET Framework 4, apenas o código confiável pode usar a reflexão para acessar membros críticos de segurança. Além disso, apenas o código confiável pode usar a reflexão para acessar membros não públicos que não seriam diretamente acessíveis ao código compilado. Finalmente, o código que usa reflexão para aceder a um membro sensível à segurança deve ter as permissões que o membro sensível à segurança exige, tal como acontece com o código compilado.

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

  • Aceda a membros públicos que não sejam críticos em termos de segurança.

  • Acesse membros não públicos que seriam acessíveis ao código compilado, se esses membros não forem críticos para a segurança. Exemplos de tais membros não públicos incluem:

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

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

    • 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.

Começando com o .NET Framework 2.0 Service Pack 1, tentar acessar membros que normalmente são inacessíveis gera uma exigência pelo conjunto de permissões do objeto de destino mais ReflectionPermission com o sinalizador ReflectionPermissionFlag.MemberAccess. O código que está sendo executado 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 de segurança, conforme descrito mais adiante neste artigo.)

Opcionalmente, um domínio de aplicação em área restrita pode conceder a ReflectionPermission com a ReflectionPermissionFlag.MemberAccess flag, conforme descrito na seção Acessando membros que normalmente estão inacessíveis, mais adiante neste artigo.

Aceder a Membros de Security-Critical

Um membro é crítico de segurança se tiver o SecurityCriticalAttribute, se pertencer a um tipo que tenha o SecurityCriticalAttribute, ou se estiver num conjunto crítico de 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 de segurança, mesmo que o código seja totalmente confiável. A MethodAccessException, FieldAccessException, ou TypeAccessException é lançado.

  • O código que está sendo executado com confiança parcial é tratado como transparente.

Essas regras são as mesmas, quer um membro crítico de segurança seja acessado diretamente por código compilado ou acessado usando reflexão.

O código do aplicativo que é executado a partir da linha de comando é executado com confiança total. Desde que não esteja marcado como transparente, ele pode usar a reflexão para acessar membros críticos para a 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 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 de segurança. Se não for confiável, torna-se transparente, mesmo que não tenha sido marcado como transparente, e não pode acessar membros críticos de segurança.

Reflexão e Transparência

Começando com o .NET Framework 4, o Common Language Runtime determina o nível de transparência de um tipo ou membro a partir 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. O mecanismo de reflexão fornece as propriedades IsSecurityCritical, IsSecuritySafeCritical e IsSecurityTransparent para permitir que se 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 ÉCríticoParaSegurança IsSecuritySafeCritical IsSecurityTransparent
Crítico true false false
Segurança crítica 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 tempo de execução. Por exemplo, o mesmo tipo pode ser crítico para a segurança quando é executado a partir da linha de comando ou segurança transparente quando é executado num domínio de aplicação sandbox.

Existem propriedades semelhantes nas MethodBaseclasses , FieldInfo, TypeBuilder, MethodBuilder, e DynamicMethod . (Para outras abstrações de reflexão e emissão de reflexão, atributos de segurança são aplicados aos métodos associados; por exemplo, no caso de propriedades, eles são aplicados aos métodos de acesso da propriedade.)

Aceder a membros que são normalmente inacessíveis

Para usar a reflexão para invocar membros que são 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: O seu código deve ser concedido ReflectionPermission com o sinalizador ReflectionPermissionFlag.MemberAccess.

    Observação

    Por padrão, a política de segurança nega essa permissão ao código originário da Internet. Esta permissão nunca deve ser concedida a 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ão do assembly que contém o membro invocado seja o mesmo ou um subconjunto do conjunto de concessão 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-se que conceda a um domínio de aplicação permissões da Internet mais ReflectionPermission com o sinalizador ReflectionPermissionFlag.RestrictedMemberAccess e, em seguida, execute uma aplicação da Internet com dois assemblies, A e B.

  • A assemblagem A pode usar reflexão para aceder a membros privados da assemblagem B, porque o conjunto de permissões da assemblagem B não inclui nenhuma permissão que não tenha sido concedida à A.

  • A Assembly A não pode usar reflection para aceder a membros privados de assemblies do .NET Framework como mscorlib.dll, porque mscorlib.dll é totalmente confiável e, por isso, tem permissões que não foram concedidas à assembly A. A MemberAccessException é lançado quando a segurança de acesso ao código percorre a pilha em tempo de execução.

Serialização

Para serialização, SecurityPermission com o SecurityPermissionAttribute.SerializationFormatter sinalizador fornece a capacidade de obter e definir 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 aceitam MethodInfo parâmetros, especialmente para código de confiança. Esses membros podem ser mais vulneráveis a códigos maliciosos. Por exemplo, considere um membro público em código altamente confiável que aceita um MethodInfo parâmetro. Suponha que o membro público da classe chame indiretamente o método Invoke utilizando o 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, porque o sistema de segurança determina que o chamador é altamente confiável. Mesmo que o código mal-intencionado não tenha a permissão para invocar diretamente o método, ele ainda pode fazê-lo indiretamente chamando o membro público.

Informações sobre a versão

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

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

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

Ver também