Explorando redes com ESP32 WIFI.

Higor Diego
8 min readNov 26, 2023

--

Recentemente, vivenciei uma situação peculiar em um banco durante uma revista em minha bolsa. Foi constatado que a entrada de notebooks não era permitida na área específica, levando o guarda encarregado da revista a retirar meu notebook, em conformidade com as normas estabelecidas.

No entanto, o que despertou minha curiosidade foi o fato de que outros dispositivos periféricos, como bateria, cabos e um ESP32, permaneceram na bolsa, possibilitando minha entrada na área restrita. Após adentrar o recinto, fui conduzido a uma sala para aguardar o gerente. Durante esse período, aproveitei para realizar uma análise do ambiente e, para minha surpresa, deparei-me com um papel sobre a mesa contendo as informações de login e senha da rede Wi-Fi interna.

Essa situação suscitou uma reflexão: se a restrição de entrada com notebooks visa à segurança, será que o ESP32 não poderia ser utilizado para efetuar ataques à rede? Com base nessa ponderação, optei por redigir este artigo com o intuito de explorar um estudo sobre redes, buscando compreendê-las sem a utilização de notebooks ou ferramentas avançadas como o nmap (por exemplo), concentrando-se apenas no ESP32.

É fundamental salientar que o propósito deste artigo é proporcionar informações relevantes sobre segurança, sendo estritamente um estudo teórico.

O que e arduino ?

Arduino é uma plataforma de prototipagem de código aberto que consiste em hardware e software projetados para facilitar o desenvolvimento de projetos eletrônicos. O hardware Arduino é baseado em placas de circuito integradas com microcontroladores e uma interface de programação. Já o software consiste em uma IDE (Ambiente de Desenvolvimento Integrado) que permite a programação dessas placas.

Principais características do Arduino:

  • Microcontrolador: As placas Arduino são equipadas com microcontroladores que executam programas escritos em uma linguagem de programação derivada do C/C++.
  • IDE Arduino: A IDE Arduino fornece um ambiente de programação simples e intuitivo, facilitando o desenvolvimento de código para controle de dispositivos e interação com sensores.
  • Placas Variadas: Existem várias placas Arduino com diferentes especificações e tamanhos, desde placas básicas para projetos simples até modelos mais avançados com maior poder de processamento e recursos adicionais.
  • Entradas e Saídas (I/O): As placas Arduino têm pinos de entrada/saída (I/O) que permitem a conexão a diferentes componentes eletrônicos, como sensores, LEDs, motores, entre outros.
  • Comunicação: As placas Arduino suportam diferentes métodos de comunicação, como USB, UART, I2C e SPI, permitindo a interação com outros dispositivos e módulos.
  • Comunidade Ativa: Arduino possui uma comunidade global ativa que compartilha projetos, códigos e oferece suporte, facilitando o aprendizado e a resolução de problemas.

O que é ESP32?

O ESP32 é um microcontrolador de baixo custo, baixa potência e altamente integrado, pertencente à família ESP8266. Desenvolvido pela Espressif Systems, uma empresa chinesa, este microcontrolador é amplamente utilizado em projetos de Internet das Coisas (IoT) devido às suas capacidades de conectividade Wi-Fi e Bluetooth.

Reconhecido por sua versatilidade e desempenho, o ESP32 oferece uma ampla gama de recursos, incluindo processador dual-core, conectividade sem fio, GPIOs (General Purpose Input/Output), capacidade de interface com sensores e periféricos, além de suporte a diversos protocolos de comunicação. Tais características fazem dele uma escolha popular para aplicações em IoT, automação residencial, projetos de eletrônica e desenvolvimento de protótipos.

Configuração Necessária

A seguir, listamos alguns itens essenciais para a realização do estudo de caso.

Conexao de rede.

No esp32 podemos se conectar na wifi e com isso iremos analisar o codigo simples que nos possibilita a conexao.

Segue abaixo o codigo:

#include <WiFi.h>

const char *ssid = "SEU_SSID";
const char *password = "SUA_SENHA";

void setup() {
Serial.begin(115200);
delay(10);

// Conectar-se à rede WiFi
Serial.println();
Serial.print("Conectando a ");
Serial.println(ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

Serial.println("");
Serial.println("Conectado ao WiFi");
Serial.print("Endereço IP: ");
Serial.println(WiFi.localIP());
}

void loop() {

}

Com referência ao exemplo anterior, procedemos com a explicação detalhada, partindo do código apresentado.

  • Inclusão da Biblioteca WiFi:
#include <WiFi.h>

Isso inclui a biblioteca WiFi, necessária para lidar com as funcionalidades de conexão WiFi do ESP32.

  • Definição das Credenciais da Rede WiFi:
const char *ssid = "SEU_SSID";
const char *password = "SUA_SENHA";

Substitua “SEU_SSID” e “SUA_SENHA” pelos respectivos SSID e senha da sua rede WiFi.

  • Configuração do Ambiente no Método setup():
void setup() {
Serial.begin(115200);
delay(10);

Inicia a comunicação serial com uma taxa de 115200 bps e espera por 10 milissegundos.

  • Conexão à Rede WiFi no Método setup():
Serial.println();
Serial.print("Conectando a ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

O programa imprime no console serial que está tentando se conectar à rede especificada.

WiFi.begin(ssid, password) inicia a conexão à rede WiFi usando as credenciais fornecidas.

O loop while espera até que a conexão seja estabelecida (WL_CONNECTED).

  • Exibição de Informações Após a Conexão Bem-sucedida no Método setup():
Serial.println("");
Serial.println("Conectado ao WiFi");
Serial.print("Endereço IP: ");
Serial.println(WiFi.localIP());

Uma vez conectado, o programa imprime que foi conectado com sucesso e exibe o endereço IP atribuído ao ESP32.

  • Método loop():
void loop() {

}

O método loop() está vazio neste exemplo. Este é o local onde você colocaria o código que deve ser executado continuamente após a inicialização.

O que faremos ?

Agora que adquirimos conhecimento sobre como realizar a conexão com o dispositivo, podemos ponderar sobre os seguintes aspectos:

  1. Possuo um periférico capaz de se integrar à rede.
  2. Esse periférico dispõe de capacidade de processamento.
  3. Ele opera utilizando uma linguagem de programação.

Diante dessas considerações, surge a pergunta: por que não desenvolver algo para explorar a rede?

A partir dessa premissa, exploraremos os endereços IP da rede para identificar portas abertas.

Atualmente, já possuímos:

  1. Conexão estabelecida com a rede WiFi.
  2. Atribuição dinâmica de endereço IP por meio do DHCP da rede.

Com base nessas informações, iniciaremos uma busca por portas abertas em possíveis computadores ou servidores.

A seguir, apresento o código correspondente:

#include <WiFi.h>

const char *ssid = "SEU_SSID";
const char *password = "SUA_SENHA";

// Lista de IPs a serem testados
IPAddress ips[255];
int currentIpIndex = 0;

// Lista de portas a serem testadas
int portas[] = {80, 443, 22};

void setup() {
Serial.begin(19200);
delay(10);

Serial.println("Conectando ao WiFi...");
WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

Serial.println("");
Serial.println("WiFi conectado");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}

void loop() {
scanner();

// Aguardar antes de repetir o teste
delay(5000);
}

void scanner() {
if (currentIpIndex >= 255) {
// Resetar o índice para começar de novo
currentIpIndex = 0;
}

// Extrair os três primeiros octetos do endereço IP
byte firstThreeOctets[3];
IPAddress localIP = WiFi.localIP();
for (int i = 0; i < 3; i++) {
firstThreeOctets[i] = localIP[i];
}

// Criar o IPAddress com base nos três primeiros octetos e no último octeto variável
IPAddress ipToTest(firstThreeOctets[0], firstThreeOctets[1], firstThreeOctets[2], currentIpIndex);

for (int j = 0; j < sizeof(portas) / sizeof(portas[0]); j++) {
WiFiClient client;
if (client.connect(ipToTest, portas[j])) {
Serial.printf("Conectado a %s na porta %d\n", ipToTest.toString().c_str(), portas[j]);
client.stop();
} else {
Serial.printf("Falha na conexão a %s na porta %d\n", ipToTest.toString().c_str(), portas[j]);
}
}

// Incrementar o índice para o próximo IP na próxima chamada
currentIpIndex++;
}

Inclusão de Bibliotecas:

#include <WiFi.h>

Essa parte do código inclui as bibliotecas necessárias para a comunicação com a rede WiFI.

const char *ssid = "SEU_SSID";
const char *password = "SUA_SENHA";

Substitua “SEU_SSID” e “SUA_SENHA” pelo nome e senha da sua rede WiFi.
Listas de IPs e Portas:

IPAddress ips[255];
int currentIpIndex = 0;
int portas[] = {80, 443, 22};
  • ips: Uma lista de endereços IP a serem testados.
  • currentIpIndex: Índice atual na lista de IPs.
  • portas: Uma lista de portas a serem testadas.

Configuração no Método setup():

void setup() {
Serial.begin(19200);
delay(10);
Serial.println("Conectando ao WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi conectado");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
  • Serial.begin(19200): Inicia a comunicação serial com uma taxa de 19200 bps.
  • WiFi.begin(ssid, password): Inicia a conexão WiFi usando as credenciais fornecidas.
  • while (WiFi.status() != WL_CONNECTED): Aguarda até que a conexão seja estabelecida.

Após a conexão bem-sucedida, o código imprime mensagens indicando que o WiFi foi conectado e exibe o endereço IP atribuído ao dispositivo.

Método loop():

void loop() {
scanner();
// Aguardar antes de repetir o teste
delay(5000);
}

O método loop() chama a função scanner() (que ainda não está definida neste código) para realizar o teste de porta e aguarda 5 segundos antes de repetir.

Método scanner():

void scanner() {
if (currentIpIndex >= 255) {
// Resetar o índice para começar de novo
currentIpIndex = 0;
}
  • scanner(): Uma função que realiza a verificação de portas em diferentes IPs.
  • if (currentIpIndex >= 255): Quando todos os IPs foram testados, o índice é resetado para reiniciar o processo.

Continuação do Método scanner():

// Extrair os três primeiros octetos do endereço IP
byte firstThreeOctets[3];
IPAddress localIP = WiFi.localIP();
for (int i = 0; i < 3; i++) {
firstThreeOctets[i] = localIP[i];
}
// Criar o IPAddress com base nos três primeiros octetos e no último octeto variável
IPAddress ipToTest(firstThreeOctets[0], firstThreeOctets[1], firstThreeOctets[2], currentIpIndex);
  • firstThreeOctets: Extrai os três primeiros octetos do endereço IP local do dispositivo.
  • IPAddress ipToTest: Cria um novo endereço IP usando os três primeiros octetos e o índice variável para o último octeto.

Continuação e Finalização do Método scanner():

for (int j = 0; j < sizeof(portas) / sizeof(portas[0]); j++) {
WiFiClient client;
if (client.connect(ipToTest, portas[j])) {
Serial.printf("Conectado a %s na porta %d\n", ipToTest.toString().c_str(), portas[j]);
client.stop();
} else {
Serial.printf("Falha na conexão a %s na porta %d\n", ipToTest.toString().c_str(), portas[j]);
}
}
// Incrementar o índice para o próximo IP na próxima chamada
currentIpIndex++;
}

Um loop que percorre a lista de portas e tenta conectar-se a cada combinação de IP e porta. Se a conexão for bem-sucedida, imprime a mensagem “Conectado”. Caso contrário, imprime “Falha na conexão”.

Exploração

Após a compilação e o upload no ESP32, o resultado na porta serial é apresentado da seguinte forma:

Com base nesse resultado, identificamos um IP (192.168.0.1) com a porta 80 aberta, possibilitando a enumeração de servidores e portas abertas no ambiente ao qual estamos conectados.

Vetores de Ataque

Considerando o ESP32, é possível realizar diversos tipos de ataques, tais como:

  • Sniffer: Interceptação de dados em uma rede para análise.
  • Scan de Portas: Identificação de portas abertas em um sistema.
  • Scan de WiFi: Exploração de redes sem fio disponíveis.
  • Ataque de Força Bruta: Tentativa de descobrir senhas por meio de repetidas combinações.

Com a proliferação de dispositivos portáteis no mundo da IoT, embora esses dispositivos ofereçam inovações significativas, também abrem oportunidades para ataques mais sofisticados, muitas vezes realizados com custos inferiores a 5 dólares.

Como se Proteger?

Para proteger-se contra esses vetores de ataques, é fundamental adotar práticas de segurança robustas, incluindo:

  • Monitoramento Constante: Monitorar regularmente o tráfego e as atividades suspeitas na rede.
  • Firewalls: Configurar firewalls para restringir o tráfego indesejado.
  • Desabilitar Serviços Não Necessários: Desativar serviços que não são essenciais para reduzir a superfície de ataque.
  • Filtro de Endereço MAC: Habilite o filtro de endereço MAC no roteador para permitir apenas dispositivos autorizados.Mantenha uma lista branca de endereços MAC permitidos.
  • Desative o SSID Broadcasting: Desative a transmissão do nome da sua rede (SSID broadcast).Isso torna sua rede menos visível para scanners, mas não fornece segurança total.

Compartilhe seu carinho:

Estou verdadeiramente empenhado em criar conteúdo constante, explorando compras de equipamentos e ferramentas para trazer temas relevantes. Se você gostou deste artigo, ou de outros que compartilhei, e deseja oferecer seu apoio para me ajudar a continuar nessa jornada, ficaria imensamente grato. Cada contribuição é um passo significativo para manter viva essa paixão que compartilhamos.

Aqui está o link para apoiar: Buy Me a Coffee.

Obrigado pelo seu carinho e por fazer parte desta jornada! 🌟

Conclusão

Em conclusão, exploramos a conexão WiFi com o ESP32, aprendemos sobre a identificação de portas abertas na rede e discutimos medidas de segurança contra acessos não autorizados. O código apresentado mostrou como realizar um scanner de portas simples, ressaltando a importância de práticas seguras, atualizações regulares e consciência sobre potenciais vetores de ataques. Proteger sua rede WiFi é vital para garantir a segurança dos dispositivos conectados, e a implementação de medidas preventivas é fundamental para mitigar riscos e manter a integridade do ambiente digital.

Referências

https://www.espressif.com/en/products/socs/esp32
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html

--

--

Higor Diego
Higor Diego

Written by Higor Diego

Software Architect | Software Engineer | DevOps https://higordiego.com.br

No responses yet