Sysadmin Conexões TCP Entendendo e evitando ataques ao protocolo TCP É bastante simples derrubar uma conexão TCP bombardeando-a com pacotes TCP/RST. O risco aumenta nos serviços que precisam de conexões de longa duração, como as VPNs, as transferências de zona DNS ou o Border Gateway Protocol (BGP). Descreveremos como um ataque TCP pode ser perpetrado, bem como técnicas simples para proteger sua rede deles. por Christoph Wegener e Wilhelm Dolle D esde 1985 os especialistas vão a público execrar o protocolo Transmission Control Protocol (protocolo de controle de transmissão), o conhecido TCP. Derrubar serviços, corromper ou mesmo seqüestrar conexões TCP já existentes é brincadeira de criança. As informações necessárias para isso podem ser obtidas com o mais simples dos sniffers : os endereços IP de origem e destino e um número seqüencial TCP válido. Se o agressor puder farejar a conexão em qualquer ponto do trajeto, a batalha já estará perdida antes de começar. É fato que para isso o invasor precisa necessariamente controlar uma máquina que esteja no caminho entre o cliente e o servidor – se não tiver, as coisas ficam bem complicadas para ele. Entretanto, as pessoas superestimam o esforço necessário para “invadir” uma conexão. Truques como a previsibilidade da janela TCP tornam as coisas ainda mais fáceis. Um dos problemas mais difíceis de resolver, para o agressor, é determinar (ou antes, “chutar”) a seqüencia correta de números. Só informando o número seqüencial exato esperado pela máquina destino é que conseguiremos convencê-la de que os datagramas 66 outubro 2005 IP que estamos injetando na conexão realmente pertencem à conexão. Se o agressor possuir os valores corretos, não há nada que o impeça de injetar dados numa conexão já estabelecida. Com isso ele pode, por exemplo, ganhar acesso não autorizado a informações ou simplesmente derrubar a conexão – basta enviar um único pacote TCP com a flag de Reset (RST) ativada. Em muitos casos, uma conexão interrompida é apenas irritante, mas não desastrosa. Um exemplo: se você estiver navegando na web, quando a conexão cair basta atualizar a página. Mas em outras situações, os problemas são bem maiores: repetidas interrupções numa conexão BGP (Border Gateway Protocol ou protocolo de roteamento de fronteira) entre dois roteadores no núcleo da Internet podem ser deveras caras. Um ataque de negação de serviço (também chamado DoS – Denial of Service) pode ser potencialmente prejudicial também para pequenas empresas. Imagine, por exemplo, que crackers impiedosos repetidamente derrubem uma loja virtual por longos períodos. Os prejuízos resultantes seriam consideráveis [1]. edição 13 www.linuxmagazine.com.br Começando pelo começo Precisamos entender o funcionamento básico do protocolo TCP para compreender o que é a tal vulnerabilidade e como pode ser explorada. O protocolo TCP teve suas especificações defi nidas no documento Request for Comments (RFC) de número 793 [2] , publicado em 1981. O nome Request for Comments é intraduzível – ou, antes, impossível de ser grafado numa forma sucinta como no inglês – mas pode ser entendido como um documento primário, que defi ne as especificações de alguma coisa e pede que a comunidade científica emita comentários a respeito. O peculiar desse processo é que o documento, depois de terminado, não muda de nome nem se torna algo “defi nitivo”: continua a se chamar Request for Comments. De qualquer forma, o documento RFC 793 defi ne as especificações do protocolo TCP. Conforme descrito, cada datagrama TCP começa com um cabeçalho (figura 1), que contém as portas de origem e destino da conexão – ambas são valores de 16 bits, portanto variam, em decimal, entre 0 e 65.535. Mais adiante, no mesmo cabeçalho, temos alguns parâmetros credits of the images Esquadrão anti-seqüestro Conexões TCP Sysadmin Histórico de Vulnerabilidades importantes: o número seqüencial, que MP3 de 4 MB tivesse que ser identifica o pacote de forma única na baixado em um único pacotão 1981: O Transmission Control Protocol (TCP) é especificado conexão, e o número de reconhecimento, com esse tamanho. Além de um num documento Request for Comment, a RFC793 [2]. que serve para informar à outra máquina único pacote monopolizar a rede 1985: Bob Morris aponta vulnerabilidades no TCP [15]. que o pacote que ela enviou anterior- por muito tempo, o hardware 1994: Mesmo já ocorrendo há anos, a manipulação maldosa mente foi recebido sem erros. Ambos os para tratar esse pacote não seria das vulnerabilidades do protocolo TCP só ganha as manchetes quando Kevin Mitnick usa uma técnica chamada Christmas números são de 32 bits. Temos, ainda, nem simples nem confiável. Para Day (Dia de Natal) para invadir o especialista em segurança algumas flags de controle da conexão resolver o problema, o protocolo Tsutumo Shimomura [19]. (SYN, ACK, PSH, URG, RST e FIN – fala- TCP baseia-se na fragmentação 1995: Paul Watson publica um documento que discorre sobre remos delas mais adiante) e o tamanho dos pacotes: os dados são divias vulnerabilidades do TCP ligadas à Usenet. Esse documento da janela de recepção. Esse último é o didos em pequenos segmentos recebe atenção geral. Várias pesquisas são iniciadas, espeponto crítico em que se baseia o ataque e cada um deles é transmitido cialmente no que concerne aos geradores de numeração seqüencial TCP. que discutiremos. num pacote TCP. 1995: Laurent Joncheray apresenta seu artigo científico Uma conexão estabelecida é unicaÉ fácil perceber o perigo que isso acarreta. Qualquer "Simple Active Attack against TCP" (um ataque simples contra o mente identificada por uma quádrupla TCP) na conferência Usenix [15]. que consiste das duplas endereço IP/porta um que possa determinar os 2001: O Cert descreve uma vulnerabilidade comum em vários de origem e endereço IP/porta de destino. detalhes da quádrupla e inferir geradores de números seqüenciais TCP/IP e menciona o proNuma conexão podem passar inúmeros um número seqüencial válido blema do tamanho da janela TCP. [16]. pacotes em ambos os sentidos (do clien- tem tudo o que é preciso para 2003: Paul Watson mostra que os ataques são bastante fáceis te para o servidor e do servidor para o “entrar de penetra” em uma de levar a cabo mesmo com simples conexões DSL. conexão. Não importa a pocliente). Cada pacote possui um número 2004: O IETF (Internet Engineering Task Force ou força-tarefa que o identifica e diferencia dos demais: o sição em que o invasor esteja de engenharia da Internet) publica uma versão inicial do número seqüencial. Pense nele como um na rede: basta criar um pacote documento "Improving TCP's Robustness to Blind In-Window Attacks" (aprimorando a robustez do TCP contra ataques “crachá” com um número escrito pelo nó adulterado (“spoofado” – neolo“cegos” a seu tamanho de janela) [10]. de rede que o enviou. Todo pacote indivi- gismo derivado do inglês spoodual tem o seu “crachá” com um número fed –, no jargão dos canalhas) e enviá-lo ao destino. exclusivo. O nó da rede que recebe os certo. Entretanto, essa dificuldade fica própacotes sabe, por esse número, em qual xima de zero caso os sistemas operacionais ordem reorganizá-los (já que, graças ao dos nós de origem e destino não iniciem a “desorganizado” IP, eles podem chegar A princípio, um número seqüencial pode re- contagem de números seqüenciais – esse fora de ordem) e percebe, também, se ceber um valor entre zero e 232. Isso, em te- valor é chamado de Initial Sequence Number algum deles está faltando. oria, deveria criar uma dificuldade enorme (ISN) – com um valor aleatório quando a Tudo isso é necessário porque seria im- para um agressor inferir um número válido, conexão é estabelecida. praticável transmitir os dados do usuário criar um pacote TCP com esse número e Explicando melhor: quando uma cotodos de uma vez. Imagine se um arquivo injetar esse pacote na conexão no momento nexão TCP é estabelecida (usando o chamado 3-way handshake), ambos os 0 7 8 15 16 23 24 31 participantes da conexão estabelecem Source Port Destination Port seu número seqüencial inicial (ISN) com Sequence Number um número aleatório. Esse número vale Acknowledgement Number para o primeiro pacote que um dos nós manda para o outro. A partir daí, os núData Offset Reserved Window meros seqüenciais de ambos os lados são Checksum Urgent Pointer incrementados, a cada pacote, com um Options número que representa a quantidade de ... Padding bytes transmitida. Figura 1: Todo datagrama TCP começa com esse cabeçalho. Os dados do usuário são inseridos depois. Enquanto o número de porta do serEm conjunto com o endereço IP, os números de porta identificam de forma única a conexão. O número vidor é, normalmente, um valor padrão, seqüencial, por sua vez, identifica qual a posição desse pacote TCP no fluxo de dados. que depende do serviço que “escuta” naFIN RST SYN PSH ACK URG Números aleatórios outubro 2005 www.linuxmagazine.com.br edição 13 67 Sysadmin quela porta (por exemplo, um servidor FTP normalmente está na porta 21), a porta do cliente é um valor que pode assumir qualquer número, entre 0 e 65.535. O fato de que as portas abaixo de 1024 são reservadas para acesso privilegiado no Unix não é importante, no momento. Acontece que, multiplicando o número de valores possíveis do número seqüencial (232) pelos números possíveis de porta (216), obtemos um número assombroso de tentativas que um agressor teria de fazer para atacar remotamente uma conexão TCP sem “farejá-la”. Muitas pessoas acham que, só por isso, a dificuldade do agressor seria bastante alta. Eu poderia dizer que muitos sistemas operacionais não selecionam portas aleatoriamente, o que deixaria as estatísticas mais amigáveis para o invasor – mas não levaremos isso em consideração. Ainda… O maior problema do TCP é o seu sistema de janela de conexão. Como já dissemos, os pacotes podem tomar caminhos diversos na Internet para chegar a um mesmo destino. Assim, um pacote que saiu depois pode tomar um atalho e chegar antes de seu irmão mais velho, que decidiu dar uma passeada pelos roteadores do Uzbequistão. A janela de conexão permite que o nó que está recebendo os pacotes possa colocar todos eles na ordem correta e confirmar sua recepção para a máquina emissora. O glossário da RFC 793 explica o mecanismo de janelas da seguinte maneira: “[O mecanismo de janelas] é uma lista com os números seqüenciais que o sis- Tabela 1: Tamanho inicial da janela Sistema operacional Linux Kernel 2.4 Linux Kernel 2.6 OpenBSD 3.6 Windows 2000 SP1 e SP2 Windows 2000 SP3 e SP4 Windows 2000 MS05-019 Windows XP Professional SP2 68 outubro 2005 Tamanho 5.840 Bytes 5.840 Bytes 16.384 Byte 17.520 Bytes 65.535 Bytes 17.520 Bytes 65.535 Bytes Conexões TCP tema local (o que recebe os pacotes TCP) está esperando. Assim, a pilha TCP local considera que segmentos que se sobreponham à faixa que vai de RCV.NXT até RCV. NXT + RCV.WND-1 trazem informações de controle ou dados do usuário que podem ser aceitos. O segmento que contém números seqüenciais inteiramente fora dessa faixa são considerados duplicatas e descartados”. Fechando a janela Se o número seqüencial de um pacote estiver dentro da janela de recepção, o subsistema TCP do sistema operacional (normalmente apelidado de “pilha TCP”) irá aceitar e processar esse pacote. Isso reduz consideravelmente o número de tentativas que um agressor teria de fazer para se infiltrar na conexão. No caso dos números seqüenciais, o número de tentativas cai de astronômicos 232 para 232 /tamanho da janela. Dependendo do sistema operacional, o tamanho da janela pode variar. Por exemplo, o Windows XP Professional com o SP2 aplicado possui um tamanho de janela de 65.535 bytes. Já o kernel do Linux (tanto o 2.4 quanto o 2.6) possui uma janela de 5.840 bytes. A tabela 1 mostra alguns valores de sistemas operacionais populares. O tamanho da janela também varia de acordo com o aplicativo. O Telnet de roteadores Cisco usa um tamanho de janela de 4.192 bytes, mas o protocolo BGP no mesmo roteador abre uma janela de 16.384 bytes. Não importa como encaremos a situação. Independente de nossas opiniões, a janela de conexão vai reduzir drasticamente a quantidade de números seqüenciais que um agressor precisa experimentar. Se tomarmos um sistema com o Windows XP, a quantidade de tentativas ficará abaixo de 65 mil. Em outras palavras, um agressor precisaria gerar (e injetar na conexão) míseros 65 mil pacotes com a flag RST ligada para derrubá- edição 13 www.linuxmagazine.com.br la. Esse é um número assustadoramente baixo. Sistemas de detecção de invasões (IDS – Intrusion Detection System) vão obviamente fazer estardalhaço caso um ataque desses ocorra. Entretanto, redes cujo tráfego é pesado e que não possuam essa ferramenta não vão nem notar esses pacotes extras. Altamente escalável As coisas ficam ainda piores se os participantes da conexão puderem trabalhar com o chamado redimensionamento de janela (window scaling). Essa extensão do TCP (RFC 1323, [3]) aumenta a dificuldade do agressor para encontrar um número seqüencial válido em um período curto de tempo. O redimensionamento de janelas foi projetado para conexões que precisem de uma janela maior do que o tamanho padrão – normalmente para situações de alto tráfego ou latência. Para que todos possam transmitir sem interrupções (e sem esperar pelo reconhecimento), essa técnica aumenta a janela de conexão em até 14 bits, ou seja, multiplica tudo por um fator de 16.384 (no Microsoft Windows). Resultado: a antiga restrição imposta pela RFC 793 de que a janela não pode ser maior que 65.535 bytes só vale caso nenhum dos participantes da conexão use o redimensionamento de janelas. O agressor também precisa transpor outro obstáculo: a quádrupla de endereço/porta de origem e destino. Os endereços IP não são problema – os agressores normalmente sabem em quem estão atirando – e a porta do servidor também não é lá muito difícil de inferir. É, entretanto, ligeiramente mais difícil determinar a porta de origem da conexão (a do cliente), que pode ser um número qualquer entre 0 e 65.535 – em teoria. Na prática, o número é um milhar mais baixo, já que as portas abaixo de 1024 e acima de um determinado valor (definido pelo sistema operacional) são reservadas para tarefas especiais. Conexões TCP Figura 2a: O comando netstat -nt lista as conexões TCP. A distribuição dos números de porta segue um esquema simples – o kernel simplesmente soma 1 ao número para cada nova conexão. Um sistema Linux (com kernel 2.4 ou 2.6, indiferentemente) e com pelo menos 128MB de RAM usa portas de origem entre 32.768 e 61.000. Com menos de 128 MB, a faixa se reduz mais ainda. O kernel usa as portas acima de 61.000 para mascaramento de IP. Esses valores podem ser conferidos no arquivo /proc/sys/net/ipv4/ip_local_range. É possível alterá-los usando o subsistema sysctl. Por exemplo, com o comando: sysctl -w net.ipv4.ip_local_range="32768 61000". “Chutar” pra quê? Para deleite dos agressores, as 28.232 opções restantes não são distribuídas aleatoriamente. Para falar a verdade, o kernel as distribui baseado em um esquema bastante específico. Essa é uma das mais chocantes revelações no documento divulgado por Paul Watson [4]. Os agressores não têm nenhum problema para prever as portas de origem. Uma das honrosas exceções é o OpenBSD, que realmente as escolhe de forma aleatória. O Windows XP, por exemplo, começa com a porta 1050 na primeira conexão e aumenta esse número para cada conexão consecutiva. O Linux (testamos em um Fedora Core 3 com kernel 2.6.9) não faz menos feio: começa na porta 32.768 e, também, incrementa o número para cada conexão posterior. A figura 2a mostra um sistema Linux com kernel 2.6 (que distribuiu portas entre 32.771 e 32.777). Compare-a com a figura 2b, que mostra como o OpenBSD 3.6 distribuiu suas portas: completamente aleatório! Os sistemas Cisco incrementam o número de porta em 512 a cada nova conexão – mas isso não torna o mecanismo mais seguro. Nem de longe. Os agressores não precisam “chutar” uma porta de origem caso já saibam o número atual usado na máquina da vítima. Tudo o que um agressor precisa fazer é começar com um valor inicial e tentar no máximo 50 portas. Com perseverança, hackers fuçadores não terão nenhum problema para mapear o sistema operacional da vítima. Portanto, prever a porta de origem não é, de forma alguma, um obstáculo. Técnicas de ataque Muitos ataques em conexões TCP baseiamse nas vulnerabilidades discutidas até aqui. Um dos mais simples requer apenas a injeção de um único pacote TCP com o bit RST ativado. De acordo com a RFC 793, essa flag diz ao outro participante da conexão que esta deve ser derrubada imediatamente, sem que haja interação posterior. O nó que recebe esse pacote avalia o número seqüencial e, possivel- Sysadmin mente, o número de reconhecimento para decidir se deve honrar ou ignorar o pedido de reset. Pela RFC, o sistema de destino está proibido de enviar um RST em resposta ao que recebeu. O ponto importante aqui é o fato de que o destino precisa necessariamente decidir se aceita ou ignora o RST baseado na validade do número seqüencial. O nó de destino só encerra a conexão se e somente se o número seqüencial estiver dentro da janela de conexão. Embora o nó receptor possa levar em consideração também o número de reconhecimento, ele não é obrigado a fazê-lo. O especialista em segurança Paul Watson (ver quadro Histórico) investigou um grande número de pilhas TCP e descobriu que a maioria delas simplesmente ignora o número de reconhecimento [4]. Um pacote RST recebido dentro da janela permitida, com dados que combinem com a conexão, sempre derrubará a conexão. Conexões que precisam estar sempre estabelecidas – como as usadas pelo protocolo BGP entre roteadores – são particularmente vulneráveis a ataques RST. Primeiro porque, como a conexão é semi-permanente, o agressor tem todo o tempo do mundo para criar e injetar um pacote cuidadosamente esculpido. Em segundo lugar, os danos que uma negação de serviço causa a essas conexões são inomináveis. Cada vez que a conexão é restabelecida, os roteadores precisam reconfigurar suas tabelas de vizinhança, processo que pode demorar alguns minutos em condições de trabalho reais. ➟ Figura 2b: O OpenBSD realmente toma alguma atitude para tornar a vida dos invasores mais difícil. Entre outras coisas, os números de porta de origem que o kernel atribui a cada conexão são, realmente aleatórios – os agressores terão que “chutar” o número, pois não há como prever nada. outubro 2005 www.linuxmagazine.com.br edição 13 69 Sysadmin Morte síncrona O que pouca gente sabe é que também é possível derrubar uma conexão com um pacote TCP/SYN. A RFC 793 especifica que quando uma flag SYN for ativada no início da conexão, o campo de número seqüencial deve conter um número que será usado como base para os posteriores. Se um pacote SYN chega depois que a conexão estiver iniciada, a RFC 793 considera isso um erro na conexão. Como conseqüência, o receptor é forçado a cancelar a conexão transmitindo um datagrama TCP/RST. O protocolo TCP foi projetado dessa maneira para evitar que a mesma conexão seja iniciada duas vezes – quando o sis- Glossário Assinatura MD5: MD5 é uma técnica de criptografia que calcula uma seqüencia alfanumérica única (chamada de hash, termo normalmente não traduzido) que identifica um conjunto de dados arbitrário. O hash é calculado tomando como base o próprio conjunto de dados. Se usarmos uma senha para calcular o hash, o MD5 pode gerar uma assinatura (hash assinado). BGP: O Border Gateway Protocol (ou protocolo de roteamento de fronteira) descreve como os roteadores avisam seus vizinhos a respeito das rotas de dados disponíveis. O grande trunfo do protocolo BGP é o fato de que ele pode reunir inúmeras opções de rota em uma única tabela de roteamento. Bits de controle: Flags presentes no cabeçalho do datagrama TCP. São informações de um único bit, que informam o estado de alguma coisa ou controlam o comportamento da conexão. Há seis desses controles: P SYN (SYNncronization): Pedido de sincronização no início da conexão; P ACK (ACKnowledgement): Um pacote com o bit ACK ligado indica que quem o enviou está confirmando o recebimento de todos os pacotes cujo número seqüencial é menor do que o valor presente no campo número de reconhecimento do datagrama; P FIN (FINish): Todos os dados foram enviados, encerrar a conexão; P RST (ReSeT): Cancelar a conexão imediatamente (“botão de pânico”); P PSH (PuSH): Um pacote com o bit PSH ligado ordena ao sistema operacional que o recebe 70 outubro 2005 Conexões TCP tema operacional de um dos lados trava e o sistema é reiniciado, por exemplo. Com isso, um pacote SYN causa quase o mesmo transtorno que um pacote RST: derruba a conexão – desde que, obviamente, o número seqüencial seja válido. Mas, ao contrário do pacote RST, que impede qualquer ação por parte do receptor (a não ser, é claro, encerrar a conexão), um pacote SYN fora de hora faz com que o receptor responda com um pacote RST. Há um termo técnico para esse comportamento: dizemos que o receptor reflete o pacote. E isso abre uma nova maneira de ter sucesso em ataques de negação de serviço. O agressor pode se aproveitar da conexão de um “laranja” para que transmita qualquer dado pendente imediatamente, ou que repasse os dados em buffer para o aplicativo apropriado; P URG (URGent): Se esse bit estiver ativado, há um outro campo no cabeçalho TCP chamado Ponteiro de Urgência que indica para o sistema operacional receptor qual porção dos dados transportados no pacote é mais urgente e deve ser processada primeiro. ICMP: Acrônimo para o Internet Control Message Protocol (protocolo de mensagens de controle para redes interconectadas). Esse protocolo foi definido na RFC 792 e é usado basicamente para troca de informações e diagnose de redes – o conhecido utilitário ping usa o protocolo ICMP. Looking Glass: Em português, “espelho”. Esse serviço permite que os usuários determinem se um servidor está disponível e quão boa é a conexão [6]. Para isso, perguntam aos roteadores BGP envolvidos na conexão. Os utilitários ping e traceroute podem ajudar a obter mais informações sobre os sistemas intermediários. O nome do serviço veio da obra de Lewis Carrol, “Through the looking glass”, cujo título em português é “Através do espelho e o que Alice encontrou por lá”. Número de reconhecimento: Um dos campos do cabeçalho de um datagrama TCP. possui um comprimento de 32 bits. Imagine uma conexão entre a máquina X e a máquina Y. Em um dado momento, X mandou um pacote para Y. O número de reconhecimento é o número seqüencial que X espera receber de Y quando for a vez de Y responder a X. Em resumo: quem manda o pacote põe, no número de reconhecimento, o próximo número seqüencial que espera receber. edição 13 www.linuxmagazine.com.br atacar terceiros. Esta técnica é especialmente eficiente em conexões ADSL que, como o nome (Assymetric Digital Subscriber Line) já diz, é assimétrica, ou seja, a vítima recebe os dados a uma velocidade muito maior do que pode transmitir as respostas. Enquanto os ataques RST e SYN não usam a área de dados (payload ou carga útil, nome oriundo do transporte ferroviário) do pacote, uma terceira técnica injeta dados nos datagramas de uma conexão existente. Esses dados podem ser puro lixo, servindo unicamente para corromper a conexão, ou podem ser manipulados cuidadosamente para provocar uma condição de erro. A vítima talvez nem perceba a manipulação. Número seqüencial: Campo do cabeçalho TCP que especifica a posição do primeiro byte de dados do datagrama em relação ao início da conexão. O receptor usa esse número para verificar a ordem e a validade dos datagramas que recebe. Isso protege contra ataques por injeção ou reprodução de pacotes. Entretanto, essa proteção é eficaz apenas contra erros e tentativas grosseiras de ataque. Se os pacotes recebidos forem especialmente manipulados na origem, o número seqüencial não protegerá nada. Redimensionamento de janela: Uma tentativa de otimizar o desempenho em conexões com alto tráfego ou com latência excessivamente longa. O redimensionamento de janela permite que, ao aumentar absurdamente o tamanho da janela de conexão, se possa processar pacotes que cheguem muitíssimo atrasados e transmitir muito mais dados sem precisar esperar por números de reconhecimento que desloquem a janela mais para a frente. Tamanho da janela: Um campo numérico do datagrama TCP que informa ao receptor quantos bytes o emissor do pacote aceitará como válidos, quando for a vez dele receber datagramas. O tamanho da janela é um número de 16 bits, variando, portanto, de zero a 65.535. TCP: O Transmission Control Protocol (protocolo de controle de transmissão), definido na RFC 793, controla a transferência de dados entre o emissor e o receptor. Ao contrário do protocolo UDP (User Datagram Protocol, definido na in RFC 768), o TCP é o que chamamos de orientado à conexão e assegura que todos os dados cheguem sem erros e na ordem correta. Conexões TCP Aplicações práticas Para testar suas teorias sob condições reais [4], Paul Watson desenvolveu a ferramenta reset_tcp.c, tornada pública em maio de 2004 [12]. Em seus testes, Paul observou que uma conexão DSL básica era tudo de que precisava para determinar com bastante precisão os números seqüenciais que poderiam levar ao encerramento da conexão. Foram precisos apenas onze minutos, com uma janela de 65.535 bytes e usando apenas 50 portas. Com uma janela de 16.384, o processo levou 45 minutos. O programa requer a Libnet Packet Construction Library (biblioteca de construção de pacotes de rede) [13] de Mike D. Schiffman. Basta especificar o endereço MAC de sua própria máquina e o da máquina sob ataque – ou de seu gateway para a Internet – antes de compilar o programa. Quando executado, o programa pede uns poucos parâmetros: reset_tcp interface IP_de_origem U sas, podemos facilmente determinar quanto tempo levaremos – no máximo – para derrubar a conexão: o valor máximo do número seqüencial, multiplicado pelo tamanho do pacote, dividido pela taxa de transferência. Em números: 4.294.967.296/5.840*320 bits/128.000 bps, o que nos dá 1.840 segundos ou, aproximadamente, 30 minutos e 40 segundos. Se considerarmos ainda que todos os pacotes, indistintamente, têm 50% de chance de terem sucesso na empreitada, o agressor levará somente metade desse tempo para derrubar a conexão – mais ou menos 15 minutos e 20 segundos. Nossos testes práticos confirmam nosso empirismo: o valor médio medido em uma série de 20 testes foi de 932 segundos – ou 15 minutos e 32 segundos. Mas isso foi para uma única porta, que já conhecíamos. Se precisarmos testar as 50 portas de que falamos anteriormente (em um computador com umas poucas conexões estabelecidas) o tempo para concluir esse ataque seria de interminá- Sysadmin veis 13 horas – um bocado de trabalho, mesmo para uma conexão de longa duração como uma sessão de SSH. Janelas elásticas Muitos sistemas operacionais modificam o tamanho da janela em uma conexão ativa para se adequar ao volume do tráfego. Por exemplo, o Linux aumenta o tamanho da janela em uma conexão SSH para um valor maior que 16.000. Detalhe: tudo o que essa conexão está transmitindo é o resultado do comando top – nada demais, portanto. Imagine o quanto a janela “esticaria” com tráfego mais pesado. Se o agressor souber que a vítima usa a conexão para transferir grandes quantidades de dados, pode se aproveitar do tamanho descomunal da janela para perpetrar suas maldades. Repetimos o mesmo teste – ou seja, considerando que o agressor já conhece a porta de origem – usando essa conexão SSH na qual rodamos o comando top. O tempo para a conexão cair foi de apenas 5 minutos e 45 segundos para essa janela de 16.000 bytes. ➟ porta_de_origem IP_de_destino U porta_de_destino tamanho_da_janela A interface é a placa de rede pela qual os pacotes RST sairão da máquina agressora. O primeiro teste prático foi fazer o programinha derrubar uma conexão SSH entre dois computadores com Linux (figura 3). Ambas as máquinas usam uma linha ADSL T-DSL 1000 da Deutsch Telekom para se conectar à Internet (velocidade de upload: 128kbit/s). Para este teste simples, vamos considerar que o agressor já conhece a porta de origem. O tamanho do pacote RST é de 40 bytes (somando o cabeçalho TCP com o do seu “envelope”, o cabeçalho IP) – ou, se preferir, 320 bits. Vamos arbitrar que o tamanho da janela é de 5.840 bytes em ambas as direções. Baseados nessas premis- Figura 3: Monitoramos um ataque de TCP/RST em uma conexão SSH com o Ethereal. O agressor transmite um número bastante grande de datagramas TCP com números seqüenciais crescentes (topo da janela, perto do fim da linha: Seq=…). O detalhamento de tráfego (ao centro) mostra claramente que a flag RST foi ativada. outubro 2005 www.linuxmagazine.com.br edição 13 71 Sysadmin Conexões TCP Fizemos outros experimentos basea- menor os valores, mais difícil fica sados no exemplo de Watson: uma conexão botar o sistema. Se possível, desabilite o redimensionamento da janela. Como BGP. Colocamos um computador com Linux (kernel 2.4, tamanho inicial da resultado, poucos números seqüenciais janela 5.840 bytes) falando por BGP com “cabem” na janela, forçando o agressor a um roteador Cisco (tamanho inicial da ser mais preciso, o que demanda mais tempo, esforço e largura de banda. janela 16.384 bytes). Como esperado, as janelas em ambos os sentidos “esticaram” Entretanto, há limites para esse tipo de durante a troca de dados. No início da sintonia fina. Se os valores selecionados foconexão, o BGP precisa transmitir quan- rem muito pequenos, o desempenho da rede tidades razoavelmente grandes de dados. vai cair. O protocolo TCP fica mais “preso” Em nosso experimento, a janela cresceu porque a pilha de rede tem que esperar por para 16.616 em apenas alguns minutos mais ACKs antes de transmitir. Além disso, e se estabilizou nesse patamar. O tempo terá também que transmitir mais ACKs – o teórico de ataque nessa situação seria desperdício de banda com cabeçalhos TCP de 4.294.967.296/16.616*320 bits/128.000 vai ser bem maior. Vejamos um exemplo bps/2 = 5 minutos e 23 segundos. extremo: se ajustarmos a janela para 10, Na prática, cravamos uma média de 5 precisaremos mandar um pacote ACK de 40 minutos e 39 segundos – confirmando a bytes (20 bytes para o cabeçalho IP, mais 20 para o TCP) para cada pacote TCP que teoria. As conexões BGP ficam ativas por carregue 10 bytes de dados úteis. semanas ou mesmo meses. Leva mais de um minuto para restabelecer uma conexão depois de uma queda e os roteadores BGP não abrem muitas conexões de rede Regras de filtragem dão uma proteção depois de estabilizados. Isso faz deles mais granular contra ataques RST em alvos fáceis para agressores: muito tempo, roteadores limítrofes. Tais gateways poucas portas para testar… Para malfeito- devem aceitar tráfego – seja saindo ou res, deve realmente parecer irresistível. entrando – caso o endereço IP de origem realmente exista na interface pela qual está entrando. Isso reduz o risco Como o nível de exposição é altíssimo de IP spoofing e deve ser o procedimene o risco, para o agressor, é quase nulo, to padrão de configuração para todo e a prevenção torna-se obrigatória. Apre- qualquer roteador. sentamos algumas abordagens para diOs filtros de ingresso e egresso protegem minuir os efeitos desse problemas todos. a rede interna contra ataques de impostuComo regra geral, evite dar “colher de ra (spoofing). Muitos crackers “espertos” chá” para os crackers, não divulgando travestem seus pacotes com endereços da informações desnecessárias sobre suas rede interna, mesmo que estejam entrando redes e conexões. Dispositivos dotados nessa rede pela Internet. Se o roteador do serviço Looking Glass, por exemplo, bloquear pacotes que não deveriam estar entrando por aquela interface, vai matar são acintosamente promíscuos (ver [6] e dois coelhos com uma cajadada: o quadro Glossário). Servidores de DNS mal configurados também podem dar P 1) Vai bloquear pacotes vindos da Interdores de cabeça. net que alegam ter endereços de origem Muitos sistemas operacionais facultam pertencentes à rede interna; a seus administradores ajustar o tama- P 2) Vai bloquear pacotes vindos da rede nho da janela de conexão (veja o quadro interna que alegam ser de máquinas Alterando o tamanho da janela). Quanto pertencentes à Internet. Porteiros atentos Proteção pró-ativa 72 outubro 2005 edição 13 www.linuxmagazine.com.br Alterando o tamanho da janela O tamanho da janela de conexão do protocolo TCP não é fixo. Os administradores podem modificar os tamanhos padrão e máximo em quase todos os sistemas operacionais. Cisco IOS: no modo enable, digite: ip tcp window-size tamanho da janela. Linux (kernel 2.4 e 2.6) com Ipv4: Modifique os valores de /proc/sys/net/ipv4/tcp_rmem e /proc/sys/net/ipv4/wmem ou informe esses valores nas variáveis tcp_rmem e tcp_wmem do arquivo /etc/sysctl.conf. Depois, rode o comando sysclt -p. Consulte [18] para um tutorial detalhado. Sun Solaris: Em sistemas Solaris o comando ndd dá conta do recado: ndd -set /dev/tcp tcp_xmit_hiwat tamanho_ da_janela e ndd -set /dev/tcp tcp_recv_hiwat tamanho_da_janela. Windows 2000 e XP: Modifique os valores das variáveis GlobalMaxTcpWindowSize (REG_DWORD) e TcpWindowSize (REG_ DWORD) na chave HKEY_LOCAL_MACHINE\ SYSTEM\CurrentControlSet\ Services\Tcpip\Parameters do regis- tro. Consulte [18] para um tutorial detalhado. Com esse último “coelho”, esse roteador estará dando uma inestimável contribuição à comunidade da Internet ao bloquear malfeitores que possivelmente estejam dentro de sua própria rede privada. Administradores cônscios de suas responsabilidades de segurança irão mais longe, criando regras que permitam tráfego BGP somente entre roteadores conhecidos. Isso torna ataques contra as conexões BGP quase impossíveis. Se levarmos em conta o perigo representado pela vulnerabilidade descrita neste artigo, é uma ajuda e tanto! Outra forma de proteção foi introduzida já em 1998: a RFC 2385 descreve assinaturas baseadas em MD5 para conexões TCP [7]. Por essa técnica, criam-se hashes MD5 que combinam os campos críticos do cabeçalho TCP com uma senha. Com isso, o receptor pode detectar pacotes impostores. Obviamente, as senhas precisam necessariamente ser robustas para que sejam difíceis de quebrar com o bgpcrack Conexões TCP TCP-Stack Data TCP connection exists Sequence numbers are synced RST Packet Sequence number not an exact match but in receive window Connection stays up ACK Packet RST Packet Connection terminated Sequence number exact match Figura 4: A pilha de rede baseada em [10] requer que o número seqüencial do datagrama TCP/RST seja idêntico ao que o receptor espera. [8] em um ataque de dicionário. Há uma descrição dessa vulnerabilidade do BGP, bem como as possíveis soluções, em [9]. Resposta cuidadosa Em abril de 2004, o IETF (Internet Engineering Task Force) publicou um documento preliminar [10] sugerindo mudanças no comportamento de resposta do protocolo TCP, para que a pilha de rede só reagisse imediatamente a um pacote RST se o número seqüencial fosse exatamente o que o receptor espera. Se o número seqüencial do pacote RST simplesmente caísse dentro da janela de conexão mas não fosse o número exato, a pilha de rede do receptor responderia com um pacote ACK e descartaria sumariamente o datagrama que acabara de receber. Assim, quando recebesse esse ACK de resposta,a máquina que mandou o primeiro RST mandaria um segundo RST (figura 4). A idéia por trás disso é que um impostor não veria o pacote ACK e, portanto, novas tentativas seriam tão nulas quanto a primeira. Se o primeiro RST, por outro lado, tiver sido enviado pelo participante legítimo da conexão, ao receber o ACK mencionado imediatamente responderá com um segundo RST que possuirá o número seqüencial correto – e a conexão é, portanto, legitimamente encerrada. Entretanto, esse novo comportamento introduz uma nova vulnerabilidade: nas chamadas “guerras de ACK”, um agres- sor poderia inundar a vítima com pacotes RST. Se a vítima responder a cada RST, a conexão vai ser rapidamente tomada por pacotes de controle e não vai sobrar espaço para os dados reais. Isso poderia afogar em uma conexão ADSL comum num piscar de olhos. Para evitar o problema, sugerese que cada nó da rede tenha permissão para responder a, no máximo, 10 pacotes TCP/RST a cada 5 segundos. O documento recomenda que se verifique a validade de pacotes SYN enviando um ACK em resposta. Esse comportamento é compatível com o original, determinado pela RFC 793. Trocando em miúdos: o documento proposto em [10] procura combater as vulnerabilidades do TCP usando as definições e recursos do próprio TCP. O perigo de um ataque DoS por inundação de pacotes ainda é real, entretanto – mesmo com todas essas medidas. O Linux possui ainda uma técnica para se esquivar desses ataques: um patch da GR Security [11] assegura que os kernels 2.4 e 2.6 atribuam portas aleatórias a cada nova conexão. Esse recurso foi “chupado” do OpenBSD, assim como a maioria dos outros implementados no patch. Nossos experimentos confirmam que o patch realmente funciona: depois de aplicado, todos as tentativas de derrubar uma conexão usando os testes descritos fracassaram. Prevenir é melhor que remediar Os ataques baseados nos pacotes TCP/RST e TCP/SYN são perigosíssimos e não devem ser subestimados. Inúmeros exploits já foram desenvolvidos para se valer dessas vulnerabilidades; uma simples conexão ADSL é só o que um agressor precisa para detonar conexões semipermanentes. Ao se referir a esse tipo de ataque, Theo de Raadt, o líder do projeto OpenBSD, disse em certa feita: “muitos dizem que esse é um problema imaginário, mas tenho certeza de que, num futuro não muito distante, veremos algum worm se aproveitando dele”. ■ Sysadmin Informações [1] Computer Security Institute: www.gocsi.com [2] RFC 793, "Transmission Control Protocol": rfc.net/rfc793.html [3] RFC 1323, "TCP Extensions for High Performance": rfc.net/rfc1323.html [4] Open Source Vulnerability Database, Paul (Tony) Watson, "Slipping in the Window: TCP Reset Attacks": www.osvdb.org/reference/ SlippingInTheWindow_v1.0.ppt [5] Open Source Vulnerability Database, Paul (Tony) Watson, "TCP Reset Spoofing": www.osvdb.org/4030 [6] Nós BGP dotados do recurso Looking Glass: www.bgp4.net/lg [7] RFC 2385, "Protection of BGP Sessions via the TCP MD5 Signature Option": rfc.net/rfc2385.html [8] Quebrador de senhas no protocolo BGP: www.cisco.com/security_services/ ciag/tools/bgpcrack-2.1.tar.gz [9] Sean Convery e Matthew Franz, "BGP Vulnerability Testing: Separating Fact from FUD v1.1": www.blackhat.com/presentations/bhusa-03/bh-us-03-convery-franz-v3.pdf [10] Documento preliminar, "Improving TCP's Robustness to Blind In-Window Attacks": ietfreport.isoc.org/idref/draftietf-tcpm-tcpsecure [11] GR Security: www.grsecurity.net [12] TCP Connection Reset Remote Exploit: www.frsirt.com/exploits/04232004. tcp-exploit.php [13] Libnet: www.packetfactory.net/projects/libnet [14] Robert T. Morris, "A Weakness in the 4.2 BSD Unix TCP/IP Software: pdos.csail.mit.edu/~rtm/papers/117.pdf [15] Laurent Joncheray, "Simple Active Attack Against TCP": www.usenix.org/ publications/library/proceedings/ security95/full_papers/joncheray.ps [16] Cert Advisory CA-2001-09, "Statistical Weaknesses in TCP/IP Initial Sequence Numbers": www.cert.org/advisories/CA-2001-09.html [17] Dave MacDonald e Warren Barkley, "Microsoft Windows 2000 TCP/IP Implementation Details": www.microsoft.com/technet/itsolutions/ network/deploy/depovg/tcpip2k.mspx [18] Oskar Andreasson, "Ipsysctl tutorial -- Chapter 3, IPv4 variable reference": ipsysctl-tutorial.frozentux.net/ chunkyhtml/tcpvariables.html [19] Cert Advisory CA-1995-01, "IP Spoofing Attacks and Hijacked Terminal Connections": www.cert.org/advisories/CA-1995-01.html outubro 2005 www.linuxmagazine.com.br edição 13 73