Esse assunto é muito discutido e existe muita literatura a respeito. A própria Microsoft, nas últimas semanas, fez e ainda está fazendo um RoadShow sobre o assunto. Mas com tudo isso à disposição, muita gente ainda não tira proveito e nem sabe que existe toda uma infra-estrutura de segurança por trás do .NET Framework. O objetivo desse e dos próximos artigos, é demonstrar as mais diversas maneiras que você dispõe para desenvolver de forma segura, bem como mostrar os aspectos que englobam um código seguro.
Eu sei que muitos não gostam de teoria, mas realmente é necessário se falar um pouco sobre alguns pontos chaves. Então vamos lá.
Duas tecnologias chaves para segurança e que andam de mãos dadas, são conhecidas como: Evidence-Based Security e Code Access Security.
Evidence-Based Security
Tecnologia que determina quais permissões são garantidas para determinado código. Evidência é a informação que é disponibilizada sobre determinado Assembly, e que é usada como entrada para o mecanismo de Security Police (Falarei mais adiante). Os tipos de evidências podem ser os mais diversos, podendo inclusive ser estendido com novos tipos definidos por você. As evidências definidas inicialmente pelo .NET são:
- Hash: Valor Hash
do Assembly, gerado com algum algoritmo Hash, como o SHA1
- Publisher: AuthentiCode Signer
- StrongName: StrongName do Assembly
- Site: Web Site original do Assembly
- URL: URL original do Assembly
- Zone: Zona do Internet Explorer
- Application Directory: Diretório
de onde o código foi carregado
Podemos então, concluir dizendo que a evidência de um assembly nada mais é que uma informação que nos ajuda a definir uma política de segurança para determinado código ou grupo de código, por exemplo: “Todo código que se originar da url: www.imasters.com.br será seguro”. Logo, precisamos da evidência, que nesse caso é a url e também precisamos dizer ao mecanismo de segurança que conceda os privilégios necessários para o referido código rodar.
Como fazer isso? É simples, utilizamos o .NET Framework Configuration Tool (Mscorcfg.msc). Veremos na próxima parte.
Como curiosidade, vamos ver como verificar as evidências de um assembly, programaticamente.
Dim t as Type = Type.Gettype(“System.String”)
Dim asb as Assembly = Assembly.GetAssembly(t)
Dim e as Evidence = asb.Evidence
Dim i as IEnumerator = e.GetEnumerator
Do While i.MoveNext
Console.Write i.Current
Loop
Rode o código acima e veja a saída.
Code Access Security
É a tecnologia que se encarrega de verificar as permissões concedidas para um assembly. O mecanismo de segurança verifica se o código que está sendo executado tem permissão para executar a ação que ele deseja, vasculhando não só as permissões concedidas a ele, bem como as permissões dos seus “chamadores” no Stack. Vamos dar um exemplo: Digamos que tenha uma aplicação que acesso o File System, com permissões para ler e gravar.
Por padrão, se você está usando essa aplicação na sua máquina ou já concedeu as permissões necessárias na máquina de produção, a sua aplicação funcionará sem problemas. Contudo, se um código mal intencionado que não tenha permissão para tais ações, faça uso do seu assembly para acessar o File System, a verificação de segurança irá causar uma Security Exception. Garantindo assim, um nível de segurança muito poderoso, evitando os chamados “Luring Attacks”.
Uma última consideração: devemos ter em mente é em que cenário precisamos explicitamente definir permissões ou verificações de permissões. Aconselho a ficar de orelha em pé quando nos depararmos com as seguintes situações:
. Blocos
de códigos reutilizáveis, ou componentes de uma
aplicação que podem ser utilizados por outra;
. Códigos
que aceitem entrada de dados onde a fonte é desconhecida,
como um componente usado por uma aplicação ASP.NET;
. Managed
Wrapper para implementação de código nativo.
Portanto, só requisite as permissões necessárias para seu código rodar e assegure-se que seu código receba apenas as permissões necessárias no momento. Por exemplo:
<Assembly:FileIOPermissionAttribute(SecurityAction.RequestMinimum, Write=”C:Clientes.xml”>
O exemplo acima significa que o código não será executado, a menos que seja lhe dado permissão para escrever no arquivo Clientes.xml. Caso o código não encontre uma política de segurança que lhe garanta essa permissão, uma PolicyException será disparada.
Finalmente vamos falar agora sobre Políticas de Segurança, e como implementá-la.
Como já foi falado, o Security Police mapeia a evidência do assembly a um conjunto de permissões e quem implementa essa funcionalidade é a classe SecurityManager, do Namespace System.Security. Existem quatro níveis de políticas de segurança que o Security Manager reconhece:
. Enterprise
Policy
. Machine
Policy
. User
Policy
O quarto nível, chamado Application Domain Policy, é configurado programaticamente.
Quando o Security Manager precisa determinar quais permissões são garantidas para um assembly, ele inicia pelo nível mais alto, ou seja, o Enterprise level. Ao passar a evidência do assembly como parâmetro para o dado nível, o retorno será as permissões garantidas para esse nível. Então, o Security Manager continua a verificar nos outros Code Groups. Ao finalizar a pesquisa nos grupos do primeiro nível, continua a verificação nos níveis abaixo. Depois a intercessão de todas as permissões é realizada e é gerado o conjunto de permissões para o assembly (Permission Set).
Lembrando que se, logo no primeiro nível, não for garantida nenhuma permissão para o assembly, o mesmo não poderá ser executado e uma exceção será disparada.
Cada nível possui três itens, que em conjunto expressam o estado de configuração do nível específico. São eles: Code Groups, Named Permissions e Policy Assemblies.
Code Groups: Contém uma condição (Evidência) e um conjunto de permissões. Caso o assembly satisfaça a condição, o conjunto de permissões é garantido.
Named Permissions: Um nível de segurança contém uma lista de permission sets. Cada permissão contém as configurações de acesso para os mais diversos recursos protegidos. As Named Permission são referenciadas pelo Code Group pelo nome. Se a condição de um Code Group é satisfeita, então a Named Permission é garantida para o assembly.
Acabamos de ver alguns conceitos importantes, como: Evidence-Based Security, Code Access Security e Políticas de Segurança. Com isso já temos condições de visualizar as possibilidades para uma implementação de segurança no nosso código.
A partir da próxima matéria, veremos como configurar as políticas de segurança, definir de forma declarativa e imperativa as permissões de bloco de código e por último veremos um assunto muito interessante são os recursos disponibilizados pelo .NET para Criptografia.
Vou ficando por aqui, espero que tenham gostado e entendido o conceito de segurança que está por trás do .NET Framework. Caso tenham alguma dúvida, crítica ou sugestão, estarei a disposição de todos vocês através do email: lblima_net@hotmail.com.
Até a próxima.
Os textos publicados neste espaço são de responsabilidade única de seus autores (colunistas e leitores) e podem não expressar necessariamente a opinião do iMasters.
Leonardo Lima é MCP, trabalha com desenvolvimento de aplicações .NET desde 2001. Ministra cursos na plataforma .NET e é consultor de tecnologia e desenvolvedor de sistemas na RR Consultoria e Sistemas. Atualmente está dedicado ao desenvolvimento de um sistema ERP utilizando a plataforma .NET.
2001 - iMasters FFPA Informática Ltda - Todos os direitos reservados.