Engineering java byte code to detect exception information flow / Detecção do fluxo de informações no contexto de exceções através da engenharia de byte code Java

AUTOR(ES)
DATA DE PUBLICAÇÃO

2010

RESUMO

Segurança de dados é um tópico muito importante em ciência da computação. Sistemas e sites da Internet retém cada dia mais informações pessoais sobre seus usuários. Muitos dos dados inseridos pelos usuários são confidenciais, e, ao inserí-los em um determinado sistema, eles esperam que estas informações estejam seguras, ou seja, algum mecanismo de controle de acesso deve ser aplicado nos dados. Para ilustrar a situação, considere o cenário do sistema de um hospital: o segurança não deve poder acessar nenhuma informação sobre os pacientes no sistema; o recepcionista, por outro lado, poderia ter acesso a informações básicas do paciente, como nome, endereço, data da última consulta. Enfim, dados sobre o histórico médico do paciente, só podem ser acessados por um médico. Esse tipo de controle é muito importante para a segurança de informações, e uma maneira de recuperar dados confidenciais sem permissão, é através da análise do fluxo de informações no programa. Uma vez inserido ou carregado em um sistema, um valor sensível fica armazenado em uma variável, e essa variável deve ser protegida para que somente usuários com permissão de acesso à mesma, consigam obter seu valor. Entretanto, um valor não fica retido apenas na variável a qual foi atribuído, mas é repassado integralmente ou parcialmente para outras variáveis durante o ciclo de vida do programa. Um indivíduo com intenções de acessar informações confidenciais, pode então analisar o fluxo de informações do sistema, e descobrir o conteúdo de uma variável protegida, através da análise do conteúdo de uma variável não protegida. Para evitar esse tipo de ataque, uma solução é analisar o fluxo de informações em um programa, e marcar todas as instruções e variáveis que de alguma forma são influenciadas por um dado confidencial, para que sejam também protegidas de maneira que não haja vazamentos de dados. Informações podem fluir explicita ou implicitamente em um programa. O fluxo explícito de informações é definido por instruções de atribuição no código. Por exemplo, na instrução a=b, o valor de b é explicitamente atribuído na variável a. No caso do fluxo implícito de informações, valores vazam não por serem diretamente atribuídos a outras variáveis, mas são inferidos após a análise de qual caminho o programa seguiu após um determinado ponto de ramificação. Ilustrando o exemplo, após testar se o valor de uma variável sensível é maior ou menor que 1000, o programa irá tomar um dos dois caminhamentos possíveis. Se em um dos caminhamentos uma flag(não sensível) é setada como verdadeira, e no outro caminhamento ela é definida como falsa, podese descobrir se o valor confidencial é maior ou menor que 1000, apenas checando se a flag terminou a execução como verdadeira ou falsa. Da mesma forma, informações podem ser adquiridas analizando se exceções ocorreram ou não em determinados pontos do programa. O objetivo deste trabalho então é fazer uma análise estática do byte code de programas Java, definindo pontos onde informações podem vazar devido à ocorrência ou não de exceções. Análises estáticas são caracterizadas por ocorrerem antes da execução do código, e a análise proposta insere código instrumentado no programa analisado, de forma que uma futura análise em tempo de execução tenha informações sobre os trechos de código onde exceções podem ocorrer, e possa então fazer a propagação das marcas de variáveis sensíveis. Stefan Willenbrock, em seu trabalho de graduação(WILLENBROCK, 2009), realizou um framework capaz de detectar fluxo implícito(e explícito) de informações estaticamente, e propagar marcas em tempo de execução, a partir das informações coletadas antes. Porém ele não considerou a ocorrência de exceções nos programas analisados, o que é muito importante, pois a grande maioria dos programas Java tem ibfluência no seu fluxo devido à ocorrência(ou não) de exceções durante sua execução. Este trabalho diferese do trabalho de Stefan, pois considera o contexto de exceções, e não faz a propagação de marcas a partir das influências definidas na análise estática, e sim sinaliza os pontos onde a propagação de marcas deve iniciar e terminar, devido à possibilidade de um fluxo excepcional de informações. Exceções em Java podem ser checadas ou não-checadas. As exceções não-checadas são aquelas que podem ocorrer em qualquer ponto do programa, e não precisam ser explicitamente lançadas ou capturadas. Exceções checadas, por outro lado, precisam ser explicitamente lançadas com o uso da instrução throw, e têm que ser capturadas por um block catch em algum ponto do programa. Este último tipo citado, é o tipo de exceções tratado neste trabalho. Considerando então o escopo de exceções checadas, elas podem ocorrer dentro de um bloco try, ou dentro de um método capaz de propagar exceções para o método que o chamou. Neste contexto então, diz-se que o fluxo de informações a partir de instruções dentro de um bloco try ou dentro de um método capaz de propagar exceções pode ter dois possívei destinos: o fluxo excepcional, que é o bloco catch ou a propagação pro método chamador; e o fluxo normal, que é a execução da próxima instrução do programa. Trechos de código onde exceções podem ocorrer, podem ser considerados trechos com fluxo de informações implícitas, pois são instruções que lançam ou não exceções, ou seja, são pontos de ramificação no código, podendo ter 2 destinos: excepcional ou não. Devido a este motivo, a análise feita neste trabalho lembra a análise feita para detectar fluxo implícito de informações, porém difere no fato que o ponto de ramificação e o ponto de junção de uma ramificação têm que ser descobertos, e então sinalizados de alguma forma. À primeira vista, para sinalizar trechos de código onde existe fluxo de informações devido a ocorrência de exceções, poderiamos marcar como ponto de início a entrada de um bloco try ou o começo de um método com propagação de exceções; e como ponto final o fim do último block catch correspondente ao try, ou o final do método. Entretanto, este método não funciona, pois instruções que ocorrem antes de um bloco try, podem ser afetadas pelo mesmo. Por exemplo, se um bloco try está dentro de um bloco if, informações do bloco else podem ser descobertas devido à ocorrência de uma exceção no outro ramo do fluxo(bloco if ). Outro fator importante a ser levado em conta, é que nem todas instruções dentro de um bloco try são influenciadas pelo lançamento de uma exceção, e deseja-se então fazer uma análise de forma a delimitar somente os trechos de código realmente afetados pelo fluxo excepcional, ou seja, somente as instruções que podem vazar alguma informação sensível devido à uma exceção lançada. Ilustrando como foi feita a implementação do programa, pode-se ver abaixo um algoritmo super simplificado da solução. 1 Encontrar a instrução throw 2 Detectar o escopo (bloco try, ou método capaz de propagar exceções) 3 Encontrar instrução de inicio das influências por exceções através de uma análise da s instruções anteriores 4 Encontrar instrução de fim das influências por exceções 5 Instruentar código, delimitando os pontos de início e fim de propagação das influências Listing 1: Algoritmo super simplificado. Para definir os pontos de início e fim de influências, foi utilizado o conceito de pós dominante imediato de uma instrução. Uma instrução x pós dominante imediata de y, é aquela instrução que sempre ocorre após x, ou seja, se x é um ponto de ramificação, a instrução que se pode ter certeza que sempre ocorrerá após x é o ponto de junção da ramificação. Dessa forma, foram encontrados os pontos de junção de caminhos excepcionais e não excepcionais, portanto, o ponto onde influências devem parar a propagação. Para concluir, alguns resultados de código instrumentado após a análise são apresentados no caítulo de resultados, e sugere-se ainda que este trabalho seja extendido para uma análise considerando também a ocorrência de exceções não checadas. O grande problema dessas exceções é que elas podem ocorrer em grande parte do programa, e a primeira vista, a grande maioria das instruções seriam afetadas por essas exceções, espalhando as influências de exceções por toda a análise. Portanto uma idéia inicial seria considerar primeiramente apenas algumas exceções não checadas, e analisar os resultados.

ASSUNTO(S)

seguranca : computadores information flow java byte code java exception flow static analysis usage control

Documentos Relacionados