Security-Transparent Code


Uma das grandes inovações que o .NET trouxe é a capacidade de conceder ou negar acesso à uma determinada aplicação (Assembly), independentemente do usuário que está acessando-a, sendo ou não um “Administrador” da máquina onde a aplicação está sendo executada. Esse novo conceito, presente desde a primeira versão do .NET Framework, é chamada de Code Access Security – CAS.

Esse recurso é extremamente rico em detalhes, onde podemos customizar quais direitos a aplicação terá baseando-se em condições que são avaliadas durante a execução da mesma.  Para compor o CAS, temos vários objetos, tais como: Permissions, Permissions Sets, Security Levels, Membership Conditions, Demands, etc. Ao mesmo tempo que isso é extremamente poderoso, a sua configuração torna-se complexa demais, principalmente quando você não tem um conhecimento intermediário sobre o seu funcionamento.

Um dos principais cenários onde precisamos fazer o uso destas funcionalidades, é quando estamos criando libraries (DLLs) para serem consumidas em ambientes parcialmente confiáveis, ou seja, você cria uma DLL para encapsular o acesso ao banco de dados, sistema de arquivos, etc., e quer consumí-la em uma aplicação que não está sendo executada em “FullTrust” (o que muitas vezes acontece). Nesses casos, se gasta mais tempo testando e configurando as políticas com seus respectivos níveis de segurança, do que na tarefa que a DLL irá executar.

A partir do .NET Framework 2.0, a Microsoft trouxe um recurso chamado de Security-Transparent Code. Essa funcionalidade facilita a escrita e configuração de DLLs que serão consumidas por aplicações que rodam em ambientes parcialmente confiáveis. A ideia desta técnica é você refatorar o código (seja em assemblies, classes ou métodos) em “código transparente” e “código crítico”, com o propósito de separar o código que roda como parte da aplicação do código que roda como parte da infraestrutura, criando uma espécie de barreira entre essas duas seções.

O “código transparente” não fará nada (do ponto de vista da segurança) além do que lhe foi concedido, ou seja, não acessará nenhum tipo de código que exija a elevação dos privilégios atuais. Ao precisar executar uma tarefa que exige um nível de segurança mais elevado, entre em cena o “código crítico”, que rodará em “FullTrust”. Neste caso, o “código transparente” irá invocar algum membro do “código crítico”, que possuirá todos os privilégios necessários, independentemente de quais o cliente possua, evitando elevar os privilégios do “código transparente”.

Os códigos marcados como “transparente” terão algumas restrições, tais como: elevar os privilégios (Asserts) que lhe foram concedidos; efetuar Link Demands (tudo será transformado em “full demand”) e qualquer código unsafe que ele eventualmente execute em “código transparente”, também efetuará uma “full demand”.

Observação: A diferença entre Link Demand e Demand (ou Full Demand) é que a primeira ocorre somente em tempo de compilação (JIT) e apenas irá verificar se o chamador imediato tem a permissão requerida. Já a segunda opção, Demand, executará a stack walk, ou seja, irá percorrer todos os elementos da stack, verificando se todos eles possuem a permissão solicitada.

Depois desta reestruturação (física ou virtual), a CLR irá assegurar (em tempo de execução) que o “código transparente” não poderá efetuar qualquer elevação de privilégios, garantindo que tudo o que o ele tentar executar, exigirá que toda a call stack tenha a respectiva permissão. E, para customizar a comportamento desta funcionalidade, a Microsoft disponibiliza alguns atributos:

  • SecurityTransparentAttribute: Somente permitido em nível de Assembly, diz ao runtime que ele será “transparente”, ou seja, não poderá executar qualquer ação que exija a elevação de privilégios. É importante dizer que “código transparente” não pode invocar “código crítico”.
  • SecurityCriticalAttribute: Quando utilizado em nível de Assembly, indica que ele pode ter “código crítico”. Isso vai depender da opção que você define ao utilizar o enumerador SecurityCriticalScope. A opção Everything indica que todo o código será considerado “código crítico”, enquanto a opção Explicit, determina que somente o membro onde o atributo está sendo aplicado será considerado como “código crítico”.
  • SecurityTreatAsSafeAttribute: Indica que o membro onde este atributo está sendo aplicado, pode ser acessado por outros membros que estão marcados com os atributos SecurityTransparentAttribute ou AllowPartiallyTrustedCallersAttribute. Não há nenhuma validação que evite a compilação quando você aplica este atributo em métodos públicos, e se você fizer isso, estes membros podem ser acessados através do “código transparente” tendo ter possíveis vulnerabilidades.

No exemplo abaixo, estamos definindo o atributo SecurityCriticalAttribute em nível de Assembly, dizendo que ele poderá conter “código crítico”. Com isso, somos obrigados a determinar qual método será “crítico”, utilizando o atributo SecurityCriticalAttribute ou o SecurityTreatAsSafeAttribute. Neste caso, optamos pela segunda opção, pois desejarmos que o método ReadFile possa ser invocado a partir de membro internos bem como externos, e com a configuração abaixo, será considerado “transparente”, e sem este atributo não seria possível.

[assembly: SecurityCritical]

static void Main(string[] args)
{
    Console.WriteLine(ReadFile());
}

[SecurityCritical]
[SecurityTreatAsSafeAttribute] 
private static string ReadFile(string filename)
{
    new FileIOPermission(FileIOPermissionAccess.Read, filename).Assert();
    //Ler o arquivo
}

Anúncios

4 comentários sobre “Security-Transparent Code

  1. Muito bom. Mas não consigo ver uma aplicação prática disso.
    A unica vez usei segurança de assmbly é p/ fazer webControl.
    Algumas coisas quando envolvem o VS ou estrutura do projeto precisa.

    • Boas Dalmiro,

      Quando está em um ambiente em que a configuração do .NET/ASP.NET não foi alterada, então dificilmente precisará trabalhar com isso, já que as aplicações serão executadas em FullTrust.

      A partir do momento que você está em um ambiente parcialmente confiável, e você possui um assembly que se propõe a fazer algo que este nível de segurança não permite, então conhecer e entender como funciona isso, poderá te ajudar, ao menos, a entender o que está acontecendo.

    • Boas,

      Um exemplo prático é a criação de uma DLL para ser acessado em um ambiente parcialmente confiável. Uma DLL que manipula a DB, sistema de arquivos, etc., e que precisa de um nível mais elevado que Medium Trust ou qualquer coisa abaixo disso.

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s