Este artigo foi traduzido por máquina.

Execução de teste

Sistemas Artificiais de Imunidade para Detecção de Invasão

James McCaffrey

Baixar o código de exemplo

Um sistema imunológico artificial (AIS) para a deteção de intrusão é um sistema de software que modela a algumas partes do comportamento do sistema imunológico humano para proteger redes de computadores contra vírus e semelhantes ataques cibernéticos. A idéia essencial é que o sistema imunológico humano — que é um sistema complexo, constituído por linfócitos (glóbulos brancos), anticorpos e muitos outros componentes — tem evoluído ao longo do tempo para fornecer proteção poderosa contra toxinas prejudiciais e outros patógenos. Assim, modelando o comportamento do sistema imunológico humano pode fornecer uma arquitetura eficaz contra ataques cibernéticos.

Neste artigo, descrever alguns dos princípios dos sistemas imunológico artificiais e apresentar um programa para demonstrar esses princípios. Trabalho sobre proteção de AIS ainda é relativamente novo e, na minha opinião, nenhuma implementações comerciais estão prontas para o horário nobre. O código apresentado neste artigo não diretamente permite-lhe criar um sistema realista de intrusão de rede, mas há pelo menos quatro razões por que você pode encontrar este artigo vale a pena ler. Primeiro, o código lhe dará um ponto de partida para a experimentação de hands-on com um simples sistema de AIS. Em segundo lugar, os princípios explicados vão superar o obstáculo inicial bastante difícil para esta área e permitem compreender os trabalhos de pesquisa sobre AIS. Em terceiro lugar, várias das técnicas de programação usadas neste artigo, em particulares de pedaços de r bits correspondentes e seleção negativa, podem ser útil em outros cenários de programação. E em quarto lugar, você pode apenas encontrar a idéia de modelagem de um sistema de software com base no comportamento do sistema imunológico humano interessante em sua própria direita.

A melhor maneira de ter uma idéia de onde eu estou indo dar uma olhada no screenshot de um demo executar, é mostrado em Figura 1. O programa de demonstração começa criando um conjunto de seis padrões normais (padrões que são conhecidos não deve ser parte de algum ataque de hackers) que representam TCP/IP no formato binário de pacotes de rede. Isto é chamado a auto-definir em terminologia de AIS. Naturalmente, em um sistema real de AIS, o auto-definir provavelmente conteria dezenas ou centenas de milhares de padrões, e cada padrão seria muito maior (normalmente 48-256 bits) do que os 12 bits usados aqui. Em seguida, o programa de demonstração cria três linfócitos artificiais. Cada linfócito tem um anticorpo simulado que tem quatro bits (novamente, artificialmente pequeno), uma idade e um campo de estimulação. O campo de anticorpo é essencialmente um detector. Como você verá em breve, os linfócitos são criados para que nenhum deles detectar qualquer um dos padrões na auto-definir. Por enquanto, observe que cada linfócito tem três consecutivos 0s ou 1s, mas nenhum dos padrões a auto-definir tem três valores de bits iguais consecutivos.


Figura 1 sistema imunológico Artificial Demo

Após o sistema ter sido inicializado, o programa de demonstração começa uma pequena simulação com seis padrões de entrada. A primeira entrada é detectada pelo linfócitos 1, mas porque cada linfócito possui um limiar de ativação, os linfócitos não aciona um alarme. No instante t = 3, linfócito 1 detecta a entrada de outro suspeita mas, novamente, ainda não está acima do limite. Mas no tempo t = 5, linfócito 1 detecta um terceiro pacote suspeito de entrada e uma simulado alerta é disparado.

As seções a seguir, primeiro vou explicar os conceitos-chave do sistema imunológico humano que são usados para modelar um AIS. Em seguida, vou orientá-lo através do código que produziu a captura de tela em Figura 1. Concluirei, dando-lhe algumas opiniões sobre AIS e algumas referências adicionais. Este artigo pressupõe que você tenha pelo menos nível intermediário conhecimento de programação com uma linguagem de programação moderna. Eu uso o c# para o programa de demonstração, mas vou explicar onde você precisará faz alterações para refatorar o meu código em outra linguagem como Visual Basic .NET ou Python. Apresento todo o código que gerou a imagem no Figura 1; o código também está disponível em archive.msdn.microsoft.com/mag201301TestRun.

O sistema imunológico humano

Os principais elementos do sistema imunológico altamente simplificado são ilustrados em Figura 2. Itens prejudiciais são proteínas chamadas antígenos. Em Figura 2 os antígenos são de cor vermelha e tem cantos afiados. O corpo humano também contém muitos antígenos não nocivos chamados auto-antígenos, ou self-items. Estas são proteínas naturais e em Figura 2 são de cor verde e ter arredondado lados.


Figura 2 elementos fundamentais de um sistema imunológico simplificado

Antígenos são detectados por linfócitos. Cada linfócito tem vários anticorpos, o que podem ser considerados como detectores. Cada anticorpo é específico para um antígeno particular. Normalmente, porque o anticorpo-antígeno correspondência é apenas aproximada, um linfócito não irá disparar uma reação quando um único anticorpo detecta um antígeno único. Somente após vários anticorpos detectar seus antígenos correspondentes será um linfócito tornam-se estimulada e desencadear algum tipo de reação defensiva.

Observe que nenhum linfócito possui anticorpos que detectam um self-item. Anticorpos reais são gerados pelo sistema imune no timo, mas todos os anticorpos que detectam self-items são destruídos antes de ser lançado na corrente sanguínea, um processo chamado apoptose.

Em termos de um sistema de detecção de intrusões, antigénios correspondem aos pacotes de rede TCP/IP cujo conteúdo contêm algum tipo de dados nocivos, como um vírus de computador. Auto-antígenos correspondem aos pacotes de rede normal, não-prejudiciais. Um anticorpo corresponde a um padrão de bits que corresponde aproximadamente a um pacote de rede desconhecido, potencialmente prejudicial. Um linfócito representa dois ou mais anti­/detectores de corpos. Apoptose é modelado usando uma técnica chamada seleção negativa.

Estrutura geral do programa

O programa de demonstração mostrado na Figura 1 é um único console aplicativo c# chamado ArtificialImmuneSystem. Eu usei o Visual Studio 2010, mas deve funcionar qualquer versão do Visual Studio que tem o Microsoft .NET Framework 2.0 ou posterior. Eu renomeou o arquivo gerado pelo modelo do Visual Studio chamado Program. cs para o ArtificialImmuneSystemProgram.cs mais descritivo e renomeado de classe correspondente. A estrutura geral do programa está listada em Figura 3.

Figura 3 estrutura Artificial do programa do sistema imunológico

 

using System; using System.Collections.Generic; using System.Collections; // for BitArray namespace ArtificialImmuneSystem {   class ArtificialImmuneSystemProgram   {     static Random random;     static void Main(string[] args)     {       Console.WriteLine("\nBegin Artificial Immune System for Intrusion" +         " Detection demo\n");       random = new Random(1);       int numPatternBits = 12;       int numAntibodyBits = 4;       int numLymphocytes = 3;       int stimulationThreshold = 3;       Console.WriteLine("Loading self-antigen set ('normal' historical patterns)");       List<BitArray> selfSet = LoadSelfSet(null);       ShowSelfSet(selfSet);       Console.WriteLine("\nCreating lymphocyte set using negative selection" +         " and r-chunks detection");       List<Lymphocyte> lymphocyteSet = CreateLymphocyteSet(selfSet, numAntibodyBits,         numLymphocytes);       ShowLymphocyteSet(lymphocyteSet);       Console.WriteLine("\nBegin AIS intrusion detection simulation\n");       int time = 0;       int maxTime = 6;       while (time < maxTime)       {         Console.WriteLine("============================================");         BitArray incoming = RandomBitArray(numPatternBits);         Console.WriteLine("Incoming pattern = " +           BitArrayAsString(incoming) + "\n");         for (int i = 0; i < lymphocyteSet.Count; ++i)         {           if (lymphocyteSet[i].Detects(incoming) == true)           {             Console.WriteLine("Incoming pattern detected by lymphocyte " + i);             ++lymphocyteSet[i].stimulation;             if (lymphocyteSet[i].stimulation >= stimulationThreshold)               Console.WriteLine("Lymphocyte " + i + " stimulated!" +                 " Check incoming as possible intrusion!");             else               Console.WriteLine("Lymphocyte " + i + " not over stimulation" +                 " threshold");           }           else             Console.WriteLine("Incoming pattern not detected by lymphocyte " + i);         }         ++time;         Console.WriteLine("============================================");       } // Simulation loop         Console.WriteLine("\nEnd AIS IDS demo\n");         Console.ReadLine();     } // Main     public static List<BitArray> LoadSelfSet(string dataSource) {..}     public static void ShowSelfSet(List<BitArray> selfSet) {..}     public static string BitArrayAsString(BitArray ba) {..}     public static List<Lymphocyte> CreateLymphocyteSet(List<BitArray> selfSet,       int numAntibodyBits, int numLymphocytes) {..}     private static bool DetectsAny(List<BitArray>       selfSet, Lymphocyte lymphocyte) {..}     public static void ShowLymphocyteSet(List<Lymphocyte> lymphocyteySet) {..}     public static BitArray RandomBitArray(int numBits) {..}   } // Program   public class Lymphocyte   {     public BitArray antibody;  // detector     public int[] searchTable;  // for fast detection     public int age;            // not used; could determine death     public int stimulation;    // controls triggering     public Lymphocyte(BitArray antibody) {..}     private int[] BuildTable() {..}     public bool Detects(BitArray pattern) {..}     public override int GetHashCode() {..}     public override string ToString() {..}   } } // ns

Eu deletei todos os modelo gerado usando instruções exceto referências ao sistema e System.Collections.Generic namespaces. Eu adicionei uma referência ao namespace System. Collections para que eu pudesse ter acesso à classe BitArray. Após uma mensagem de start-up, eu instanciado um objeto aleatório estático usando um valor arbitrário de semente 1.

Se você comparar o código no método Main no Figura 3 com a captura de tela em Figura 1, você não deve ter muita dificuldade para entender a lógica do programa. A chave para a demonstração de AIS é a definição da classe de linfócitos. Observe que para manter o tamanho do código demo pequeno e limpar as ideias-chave, tirei todas a verificação que você provavelmente incluiria durante a experimentação de erros normais.

A classe de linfócitos

A classe de linfócitos tem quatro campos de dados:

public BitArray antibody;  // Detector public int[] searchTable;  // For fast detection public int age;            // Not used; could determine death public int stimulation;    // Controls triggering

Declaro que todos os campos com escopo público para manter a simplicidade. O campo de anticorpo é um BitArray. Se você não estiver familiarizado com BitArray, a idéia é que usando uma matriz normal de int para representar uma coleção de bits é altamente ineficiente, porque cada int requer 32 bits de armazenamento. Uma matriz de bits condensa 32 bits de informação em um único int de armazenamento, além de alguma sobrecarga para a classe. Linguagens de programação que não tem uma classe BitArray, como exigem-lo fazer a manipulação de bits de baixo nível com a máscara de bits e operações de bit.

O campo searchTable é uma matriz que é usada pelo método detecta para aumentar significativamente o desempenho. O campo de idade não é usado em meu programa de demonstração; muitos sistemas AIS faixa de idade de um linfócito simulado e probabilisticamente matam e geram novos linfócitos com base na idade. O campo de estimulação é um contador que controla quantas vezes um objeto de linfócitos detectou uma ameaça possível. Nesta demo, quando um valor de estimulação de linfócitos excede o valor de stimulationThreshold de 3, um alerta é acionado.

O construtor de linfócitos é:

public Lymphocyte(BitArray antibody) {   this.antibody = new BitArray(antibody);   this.searchTable = BuildTable();   this.age = 0;   this.stimulation = 0; }

O construtor aceita um único parâmetro de BitArray que representa um detector de antígeno. A matriz de searchTable é instanciada usando um método auxiliar privado denominado BuildTable, que apresentarei em breve.

Uma das peças-chave de qualquer sistema de AIS é a rotina que determina se um antígeno detecta um padrão. Exigir uma correspondência exata não é viável (e não imitar o comportamento real do antígeno). Primeiros trabalhos sobre AIS usaram uma técnica chamada r-contíguos bits correspondentes, em que um antígeno e um padrão de entrada tem o mesmo número de bits e deteção ocorre quando o antígeno e o padrão de jogo em bits consecutivos de r. Pesquisas posteriores indicaram que um algoritmo melhor da deteção é r-blocos de bits correspondente. O bit r-pedaços correspondência é semelhante aos bocados r-contíguos, exceto que o detector de antígeno é menor do que o padrão para verificar, e deteção ocorre quando o antígeno corresponde a subconjunto de ny do padrão de correspondência. Por exemplo, se um antígeno é 110 e um padrão é 000110111, o antígeno detecta o padrão começando com índice 3.

Se você pensa sobre r-pedaços de correspondência por um momento, você vai perceber que é quase o mesmo que uma função de subcadeia de caracteres de seqüência de caracteres. A única diferença é que r-blocos combinando jogos bits e subseqüência de caracteres corresponde a caracteres.

No exemplo anterior, uma abordagem simples para r-pedaços de correspondência seria examinar o padrão, começando no índice 0, então no índice 1, depois 2 e assim por diante. No entanto, essa abordagem é muito lenta na maioria das situações. Existem vários algoritmos de subcadeia sofisticado que pré-processar a seqüência de caracteres de detector menor para criar uma matriz (geralmente chamada de uma tabela). Esta tabela de busca pode ser usada para pular quando uma incompatibilidade for encontrada e melhorar consideravelmente o desempenho. Em situações onde a seqüência de caracteres menor do detector é repetidamente usada para verificar padrões diferentes — como na deteção de intrusão de AIS — o tempo e a memória necessária para criar a tabela de busca é um preço pequeno a pagar para o desempenho melhorado dramaticamente.

O método de detecta de classe de linfócitos usa o algoritmo de subcadeia de Knuth-Morris-Pratt aplicado a um BitArray. O método detecta aceita um entrada padrão como 000110111 e retorna true se o antígeno do objeto atual, como 110, corresponde ao padrão. O código para o método detecta é listado em Figura 4.

Figura 4 o método de detectar

public bool Detects(BitArray pattern)  // Adapted KMP algorithm {   int m = 0;   int i = 0;   while (m + i < pattern.Length)   {     if (this.antibody[i] == pattern[m + i])     {       if (i == antibody.Length - 1)         return true;       ++i;     }     else     {       m = m + i - this.searchTable[i];       if (searchTable[i] > -1)         i = searchTable[i];       else         i = 0;     }   }   return false;  // Not found }

O método detecta pressupõe a existência de tabela de pesquisa. Lembre-se de que o construtor de linfócitos chama um método auxiliar BuildTable para criar o campo de searchTable. O código para BuildTable está listado em Figura 5.

Figura 5 o método de BuildTable

private int[] BuildTable() {   int[] result = new int[antibody.Length];   int pos = 2;   int cnd = 0;   result[0] = -1;   result[1] = 0;   while (pos < antibody.Length)   {     if (antibody[pos - 1] == antibody[cnd])     {       ++cnd; result[pos] = cnd; ++pos;     }     else if (cnd > 0)       cnd = result[cnd];     else     {       result[pos] = 0; ++pos;     }   }   return result; }

A classe de linfócitos define substituído merthods GetHashCode e ToString. O método GetHashCode é usado para evitar objetos duplicados do linfócito e é:

public override int GetHashCode() {   int[] singleInt = new int[1];   antibody.CopyTo(singleInt, 0);   return singleInt[0]; }

Essa implementação pressupõe que o campo de anticorpo de BitArray tem 32 bits ou menos. Em situações realistas, onde o campo de anticorpo tem mais de 32 bits, lidar com objetos duplicados do linfócito não é tão simples. Uma abordagem seria definir um método de código de hash personalizado que retorna um tipo de BigInteger (disponível no .NET Framework 4 e posterior).

O método ToString de linfócitos usado no programa demo é:

public override string ToString() {   string s = "antibody = ";   for (int i = 0; i < antibody.Length; ++i)     s += (antibody[i] == true) ? "
1 " : "0 ";   s += " age = " + age;   s += "  stimulation = " + stimulation;   return s; }

Criando a auto-definir

Você está certamente familiar com padrão (não-AIS) software de detecção de vírus de computador como o Microsoft Security Essentials. Estes sistemas funcionam armazenando em um banco de dados local de definições de vírus de computador conhecidos. Quando é detectado um padrão de vírus conhecidos, é acionado um alerta imediato. Tais sistemas antivírus têm problemas para lidar com variações de vírus existentes e não inteiramente na maioria das situações, quando confrontado com um vírus completamente novo. Deteção de intrusão AIS funciona da maneira oposta mantendo um conjunto de padrões de entrada que são conhecidos por serem não-prejudiciais e, em seguida, provocando um alerta quando é detectado um padrão desconhecido. Isso permite que os sistemas de detecção de intrusão de AIS — em princípio, pelo menos — para detectar novos vírus. No entanto, lidar com falsos positivos — ou seja, provocando um alerta sobre um padrão de entrada não-prejudicial — é um grande desafio para os sistemas de AIS.

Um sistema de detecção de intrusões de AIS real iria recolher muitos milhares de padrões normais de entrada ao longo de dias ou semanas. Esses padrões de auto-definir normais seriam armazenadas em um host local ou um servidor. Além disso, um verdadeiro sistema de AIS continuamente atualizaria o auto-definir (e o conjunto induzido de linfócitos) dos padrões normais, para dar conta normais alterações no tráfego da rede ao longo do tempo. O programa de demonstração neste artigo cria um artificial, estática self-set usando o método LoadSelfSet:

public static List<BitArray> LoadSelfSet(string dataSource) {   List<BitArray> result = new List<BitArray>();   bool[] self0 = new bool[] { true, false, false, true, false, true,                               true, false, true, false, false, true };   // Etc.
bool[] self5 = new bool[] { false, false, true, false, true, false,                               true, false, false, true, false, false };   result.Add(new BitArray(self0));   // Etc.
result.Add(new BitArray(self5));   return result; }

O método aceita um parâmetro de manequim dataSource não-usado para sugerir que em um cenário realista os auto-definir dados não seria codificado. Construtor BitArray, um pouco surpreendentemente, aceita uma matriz de valores de bool onde true representa um bit 1 e falso representa um bit 0. Observar que gerei os auto-definir dados de tal forma que não self-item tem mais de duas consecutivas 0s ou 1s.

O programa de demonstração usa método utilitário ShowSelfSet, que chama o método auxiliar BitArrayAsString, para exibir a auto-definir:

public static void ShowSelfSet(List<BitArray> selfSet) {   for (int i = 0; i < selfSet.Count; ++i)     Console.WriteLine(i + ": " + BitArrayAsString(selfSet[i])); } public static string BitArrayAsString(BitArray ba) {   string s = "";   for (int i = 0; i < ba.Length; ++i)     s += (ba[i] == true) ? "
1 " : "0 ";   return s; }

Criando o conjunto de linfócitos

Se você consultar novamente a explicação de como funciona o sistema imunológico humano, você vai notar que o conjunto de linfócitos deve conter apenas objetos de linfócitos que não detectam qualquer padrões na auto-definir. Método CreateLymphocyteSet é listado em Figura 6.

Figura 6 o método de CreateLymphocyteSet

public static List<Lymphocyte> CreateLymphocyteSet(List<BitArray> selfSet,   int numAntibodyBits, int numLymphocytes) {   List<Lymphocyte> result = new List<Lymphocyte>();   Dictionary<int, bool> contents = new Dictionary<int, bool>();   while (result.Count < numLymphocytes)   {     BitArray antibody = RandomBitArray(numAntibodyBits);     Lymphocyte lymphocyte = new Lymphocyte(antibody);     int hash = lymphocyte.GetHashCode();     if (DetectsAny(selfSet, lymphocyte) == false &&       contents.ContainsKey(hash) == false)     {       result.Add(lymphocyte);       contents.Add(hash, true);     }   }   return result; }

Na terminologia de AIS, o método CreateLymphocyteSet usa seleção negativa. Um linfócito aleatório objeto é gerado e, em seguida, testado para ver se ele não detectar quaisquer padrões a auto-definir, e também que o linfócito não está já no resultado definido. Esta abordagem é bastante cru, e existem outras abordagens que são mais eficientes. Eu uso uma coleção de dicionário com um valor fictício bool para rastrear objetos existentes de linfócitos; HashSet no .NET Framework 4.5 e mais tarde é uma alternativa mais eficiente.

Um objeto aleatório de linfócitos é criado, gerando um BitArray aleatório:

public static BitArray RandomBitArray(int numBits) {   bool[] bools = new bool[numBits];   for (int i = 0; i < numBits; ++i)   {     int b = random.Next(0, 2);  // between [0,1] inclusive     bools[i] = (b == 0) ?
false : true;   }   return new BitArray(bools); }

Método auxiliar DetectsAny aceita um auto-definir e um linfócito verifica através de um auto-definir e retorna true se qualquer padrão na auto-definir é detectado pelo antígeno no linfócito:

private static bool DetectsAny(List<BitArray> selfSet,   Lymphocyte lymphocyte) {   for (int i = 0; i < selfSet.Count; ++i)     if (lymphocyte.Detects(selfSet[i]) == true) return true;   return false; }

O programa de demonstração usa um método utilitário ShowLymphocyteSet para exibir os objetos gerados de linfócitos:

public static void ShowLymphocyteSet(List<Lymphocyte> lymphocyteySet) {   for (int i = 0; i < lymphocyteySet.Count; ++i)     Console.WriteLine(i + ": " + lymphocyteySet[i].ToString()); }

 

Conclusão

O código e as explicações que apresentei neste artigo devem dar-lhe uma base sólida para a experimentação de hands-on com um AIS.Pesquisadores têm sugerido muitas opções.Por exemplo, o programa de demonstração neste artigo é acionado um alerta quando um único linfócito detecta padrões de entrada desconhecidas mais do que alguns número limite de vezes.A idéia aqui é que o reais patógenos emitem muitos antígenos.Outra possibilidade é para o sistema de AIS acionar um alerta somente após vários linfócitos diferentes detectar o mesmo padrão desconhecido.

É importante salientar que um AIS não pretende ser uma solução única para a deteção de intrusão.Ao contrário, significou ser parte de uma defesa multicamada que inclui o software de antivírus tradicional.Além disso, porque trabalho com um AIS ainda é relativamente jovem, há muitas perguntas sem resposta.Se você deseja examinar algumas das pesquisas em AIS, eu recomendo Pesquisar online para artigos de autores S.Forrest, P.Williams e U.Aickelin.

Dr. James McCaffrey trabalha para a Volt Information Sciences Inc., onde gerencia o treinamento técnico para engenheiros de software trabalham no Microsoft Redmond, Wash., campus. Ele trabalhou em vários produtos da Microsoft, incluindo o Internet Explorer e o MSN Busca e McCaffey é autor do livro “.NET Test Automation Recipes” (Apress, 2006). Ele pode ser contatado em jammc@microsoft.com.

Agradecemos ao seguinte especialista técnico pela revisão deste artigo: Dan Liebling