Questões de segurança no Reflection Emit

O .NET Framework fornece três maneiras de emitir linguagem intermediária comum (CIL), cada uma com seus próprios problemas de segurança:

Independentemente da maneira como você gera o código dinâmico, a execução do código gerado requer todas as permissões exigidas pelos tipos e métodos usados pelo código gerado.

Observação

As permissões necessárias para refletir sobre o código e emitir código foram alteradas com versões subsequentes do .NET Framework. Consulte Informações de versão, mais adiante neste artigo.

Montagens dinâmicas

Montagens dinâmicas são criadas usando sobrecargas do AppDomain.DefineDynamicAssembly método. A maioria das sobrecargas desse método são preteridas no .NET Framework 4, devido à eliminação da diretiva de segurança em toda a máquina. As sobrecargas restantes podem ser executadas por qualquer código, independentemente do nível de confiança. Essas sobrecargas se dividem em dois grupos: aqueles que especificam uma lista de atributos a serem aplicados à assemblagem dinâmica quando ela é criada e aqueles que não o fazem. Se você não especificar o modelo de transparência para o assembly, aplicando o SecurityRulesAttribute atributo ao criá-lo, o modelo de transparência será herdado do assembly emissor.

Observação

Os atributos que você aplica ao assembly dinâmico depois que ele é criado, usando o SetCustomAttribute método, não entram em vigor até que o assembly tenha sido salvo no disco e carregado na memória novamente.

O código num assembly dinâmico pode aceder a tipos e membros visíveis em outros assemblies.

Observação

Os assemblies dinâmicos não usam os sinalizadores ReflectionPermissionFlag.MemberAccess e ReflectionPermissionFlag.RestrictedMemberAccess que possibilitam que métodos dinâmicos acedam a tipos e membros não-públicos.

Os assemblies dinâmicos transitórios são criados na memória e nunca são guardados no disco, por isso, não requerem permissões de acesso a arquivos. Salvar um conjunto dinâmico em disco requer FileIOPermission com os sinalizadores apropriados.

Gerando conjuntos dinâmicos a partir de código parcialmente de confiança

Pondere as condições nas quais uma assemblagem com permissões da Internet pode gerar uma assemblagem dinâmica transitória e executar seu código.

  • O assembly dinâmico usa apenas tipos públicos e membros de outros assemblies.

  • As permissões exigidas por esses tipos e membros estão incluídas no conjunto de permissões do assembly parcialmente confiável.

  • A assembleia não é guardada no disco.

  • Os símbolos de depuração não são gerados. Internet( e LocalIntranet os conjuntos de permissões não incluem as permissões necessárias.)

Métodos dinâmicos hospedados anonimamente

Métodos dinâmicos hospedados anonimamente são criados usando os dois DynamicMethod construtores que não especificam um tipo ou módulo DynamicMethod(String, Type, Type[]) associado e DynamicMethod(String, Type, Type[], Boolean). Esses construtores colocam os métodos dinâmicos numa assembly fornecida pelo sistema, totalmente confiável e transparente em termos de segurança. Nenhuma permissão é necessária para usar esses construtores ou para emitir código para os métodos dinâmicos.

Em vez disso, quando um método dinâmico hospedado anonimamente é criado, a pilha de chamadas é capturada. Quando o método é construído, as demandas de segurança são feitas em relação à pilha de chamadas capturada.

Observação

Conceitualmente, as requisições são feitas durante a construção do método. Ou seja, podem ser feitas exigências à medida que cada instrução da CIL é emitida. Na implementação atual, todas as demandas são feitas quando o DynamicMethod.CreateDelegate método é chamado ou quando o compilador just-in-time (JIT) é invocado, se o método é invocado sem chamar CreateDelegate.

Se o domínio do aplicativo permitir, os métodos dinâmicos hospedados anonimamente poderão ignorar as verificações de visibilidade JIT, sujeitas à seguinte restrição: Os tipos e membros não públicos acessados por um método dinâmico hospedado anonimamente devem estar em assemblies cujos conjuntos de concessão sejam iguais a, ou subconjuntos de, o conjunto de concessão da pilha de chamadas emissora. Essa capacidade limitada de ignorar verificações de visibilidade JIT será ativada se o domínio de aplicação conceder ReflectionPermission com a bandeira ReflectionPermissionFlag.RestrictedMemberAccess.

  • Se o seu método usa apenas tipos públicos e membros, nenhuma permissão é necessária durante a construção.

  • Se você especificar que as verificações de visibilidade JIT devem ser ignoradas, a demanda feita quando o método é construído, inclui ReflectionPermission com o ReflectionPermissionFlag.RestrictedMemberAccess flag e o conjunto de concessão do assembly que contém o membro não público que está sendo acessado.

Como o conjunto de permissões do membro não público é levado em consideração, o código parcialmente confiável ao qual foi concedido ReflectionPermissionFlag.RestrictedMemberAccess não pode elevar os seus privilégios executando membros não públicos de assemblies confiáveis.

Tal como acontece com qualquer outro código emitido, a execução do método dinâmico requer quaisquer permissões exigidas pelos métodos que o método dinâmico usa.

O assembly do sistema que funciona como hospedeiro de métodos dinâmicos anonimamente hospedados utiliza o modelo de transparência SecurityRuleSet.Level1, que é o modelo de transparência usado no .NET Framework antes do .NET Framework 4.

Para obter mais informações, consulte a classe DynamicMethod.

Gerando métodos dinâmicos hospedados anonimamente a partir de código parcialmente confiável

Considere as condições nas quais um assembly com permissões da Internet pode gerar um método dinâmico hospedado anonimamente e executá-lo:

  • O método dinâmico usa apenas tipos públicos e membros. Se seu conjunto de concessões incluir ReflectionPermissionFlag.RestrictedMemberAccess, ele pode usar tipos não públicos e membros de qualquer assembleia cujo conjunto de concessões seja igual a, ou um subconjunto de, o conjunto de concessões do conjunto emissor.

  • As permissões exigidas por todos os tipos e membros utilizados pelo método dinâmico estão incluídas no conjunto de permissões do assembly com confiança parcial.

Observação

Os métodos dinâmicos não suportam símbolos de depuração.

Métodos dinâmicos associados a assemblies existentes

Para associar um método dinâmico a um tipo ou módulo em um assembly existente, use qualquer um dos DynamicMethod construtores que especificam o tipo ou módulo associado. As permissões necessárias para chamar esses construtores variam, porque associar um método dinâmico a um tipo ou módulo existente dá ao método dinâmico acesso a tipos e membros não públicos:

  • Um método dinâmico associado a um tipo tem acesso a todos os membros desse tipo, incluindo membros privados, bem como a todos os tipos e membros internos na assemblagem que contém o tipo associado.

  • Um método dinâmico associado a um módulo tem acesso a todos os tipos internal e membros (Friend no Visual Basic, assembly em metadados de tempo de execução de linguagem comum) do módulo.

Além disso, você pode usar um construtor que especifica a capacidade de ignorar as verificações de visibilidade do compilador JIT. Isso dá ao seu método dinâmico acesso a todos os tipos e membros em todos os assemblies, independentemente do nível de acesso.

As permissões exigidas pelo construtor dependem de quanto acesso você decide dar ao seu método dinâmico:

Embora os itens nesta lista sejam descritos em termos do conjunto de permissões do assembly emissor, lembre-se de que as exigências são feitas em relação à pilha de chamadas completa, incluindo o limite do domínio da aplicação.

Para obter mais informações, consulte a classe DynamicMethod.

Gerando métodos dinâmicos a partir de código parcialmente confiável

Observação

A maneira recomendada de gerar métodos dinâmicos a partir de código parcialmente confiável é usar métodos dinâmicos hospedados anonimamente.

Considere as condições em que um assembly com permissões da Internet pode gerar um método dinâmico e executá-lo:

  • O método dinâmico está associado ao módulo ou tipo que o emite, ou seu conjunto de concessão inclui ReflectionPermissionFlag.RestrictedMemberAccess e está associado a um módulo em um conjunto cujo conjunto de concessão é igual a, ou um subconjunto de, o conjunto de concessão do conjunto emissor.

  • O método dinâmico usa apenas tipos públicos e membros. Se seu conjunto de concessões incluir ReflectionPermissionFlag.RestrictedMemberAccess e estiver associado a um módulo em um assembly cujo conjunto de concessões é igual a, ou um subconjunto de, o conjunto de concessões do assembly emissor, ele poderá usar tipos e membros marcados internal (Friend no Visual Basic, assembly em metadados de common language runtime) no módulo associado.

  • As permissões requisitadas por todos os tipos e membros utilizados pelo método dinâmico estão incluídas no conjunto de permissões da assemblagem parcialmente confiável.

  • O método dinâmico não ignora as verificações de visibilidade no JIT.

Observação

Os métodos dinâmicos não suportam símbolos de depuração.

Informações sobre a versão

A partir do .NET Framework 4, a política de segurança em toda a máquina é eliminada e a transparência de segurança torna-se o mecanismo de imposição padrão.

A partir do .NET Framework 2.0 Service Pack 1, ReflectionPermission com a flag ReflectionPermissionFlag.ReflectionEmit já não é necessária ao gerar assemblies dinâmicos e métodos dinâmicos. Esse sinalizador é necessário em todas as versões anteriores do .NET Framework.

Observação

ReflectionPermission com o flag ReflectionPermissionFlag.ReflectionEmit é incluído por defeito nos conjuntos de permissões FullTrust e LocalIntranet nomeados, mas não no conjunto de permissões Internet. Portanto, em versões anteriores do .NET Framework, uma biblioteca pode ser usada com permissões da Internet somente se executar um Assert for ReflectionEmit. Essas bibliotecas exigem uma revisão de segurança cuidadosa porque erros de codificação podem resultar em falhas de segurança. O .NET Framework 2.0 SP1 permite que o código seja emitido em cenários de confiança parcial sem emitir nenhuma demanda de segurança, porque a geração de código não é inerentemente uma operação privilegiada. Ou seja, o código gerado não tem mais permissões do que o assembly que o emite. Isso permite que as bibliotecas que emitem código sejam transparentes em termos de segurança e elimina a necessidade de afirmar ReflectionEmit, o que simplifica a tarefa de escrever uma biblioteca segura.

Além disso, o .NET Framework 2.0 SP1 introduz o sinalizador ReflectionPermissionFlag.RestrictedMemberAccess para acessar tipos e membros não públicos a partir de métodos dinâmicos parcialmente confiáveis. Versões anteriores do .NET Framework exigem o ReflectionPermissionFlag.MemberAccess sinalizador para métodos dinâmicos que acessam tipos e membros não públicos, essa é uma permissão que nunca deve ser concedida a código parcialmente confiável.

Finalmente, o .NET Framework 2.0 SP1 apresenta métodos hospedados anonimamente.

Obtenção de informações sobre tipos e membros

A partir do .NET Framework 2.0, nenhuma permissão é necessária para obter informações sobre tipos e membros não públicos. A reflexão é usada para obter informações necessárias para emitir métodos dinâmicos. Por exemplo, MethodInfo objetos são usados para emitir chamadas de método. Versões anteriores do .NET Framework requerem ReflectionPermission com o "flag" ReflectionPermissionFlag.TypeInformation. Para obter mais informações, consulte Considerações de segurança para reflexão.

Ver também