Exploring Networks with ESP32 WIFI.

Higor Diego
8 min readNov 26, 2023

--

Recently, I experienced a peculiar situation at a bank during a bag check. It was observed that the entry of laptops was not allowed in the specific area, leading the security guard to remove my laptop in accordance with established rules.

However, what caught my attention was that other peripheral devices, such as a battery, cables, and an ESP32, remained in the bag, allowing me access to the restricted area. After entering, I was directed to a room to wait for the manager. During this time, I took the opportunity to analyze the environment and, to my surprise, found a paper on the table containing the login and password information for the internal Wi-Fi network.

This situation prompted a reflection: if the restriction on laptops aims at security, could the ESP32 be used to perform network attacks? Based on this consideration, I chose to write this article with the intention of exploring a study on networks, seeking to understand them without using laptops or advanced tools like nmap, focusing solely on the ESP32.

It is essential to emphasize that the purpose of this article is to provide relevant information about security, strictly as a theoretical study.

What is Arduino?

Arduino is an open-source prototyping platform that consists of hardware and software designed to facilitate the development of electronic projects. Arduino hardware is based on integrated circuit boards with microcontrollers and a programming interface. The software consists of an Integrated Development Environment (IDE) that allows programming these boards.

Key features of Arduino:

  • Microcontroller: Arduino boards are equipped with microcontrollers that run programs written in a programming language derived from C/C++.
  • Arduino IDE: The Arduino IDE provides a simple and intuitive programming environment, facilitating code development for device control and interaction with sensors.
  • Various Boards: There are various Arduino boards with different specifications and sizes, from basic boards for simple projects to more advanced models with greater processing power and additional features.
  • Inputs and Outputs (I/O): Arduino boards have input/output (I/O) pins that allow connection to different electronic components, such as sensors, LEDs, motors, and others.
  • Communication: Arduino boards support different communication methods, such as USB, UART, I2C, and SPI, allowing interaction with other devices and modules.
  • Active Community: Arduino has a globally active community that shares projects, code, and provides support, facilitating learning and problem-solving.

What is ESP32?

ESP32 is a low-cost, low-power, and highly integrated microcontroller belonging to the ESP8266 family. Developed by Espressif Systems, a Chinese company, this microcontroller is widely used in Internet of Things (IoT) projects due to its Wi-Fi and Bluetooth connectivity capabilities.

Recognized for its versatility and performance, the ESP32 offers a wide range of features, including a dual-core processor, wireless connectivity, General Purpose Input/Output (GPIO) pins, the ability to interface with sensors and peripherals, and support for various communication protocols. These features make it a popular choice for applications in IoT, home automation, electronics projects, and prototype development.

Necessary Configuration

Below are some essential items for the case study.

Network Connection

With ESP32, we can connect to Wi-Fi, and we will analyze the simple code that enables this connection.

Here’s the code:

#include <WiFi.h>
const char *ssid = "YOUR_SSID";
const char *password = "YOUR_PASSWORD";
void setup() {
Serial.begin(115200);
delay(10);
// Connect to the Wi-Fi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("Connected to WiFi");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
}
void loop() {
// Your code here
}

Regarding the above example, let’s proceed with a detailed explanation based on the presented code.

  • Including the WiFi Library:
#include <WiFi.h>

This includes the WiFi library, necessary to handle the ESP32’s Wi-Fi connection features.

  • Defining Wi-Fi Network Credentials:
const char *ssid = "YOUR_SSID";
const char *password = "YOUR_PASSWORD";

Replace “YOUR_SSID” and “YOUR_PASSWORD” with your Wi-Fi network’s SSID and password.

  • Setting up the Environment in the setup() Method:
void setup() {
Serial.begin(115200);
delay(10);

Initializes serial communication with a baud rate of 115200 bps and waits for 10 milliseconds.

  • Connecting to the Wi-Fi Network in the setup() Method:
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

The program prints on the serial console that it is trying to connect to the specified network.

WiFi.begin(ssid, password) initiates the Wi-Fi connection using the provided credentials.

The while (WiFi.status() != WL_CONNECTED) loop waits until the connection is established.

  • Displaying Information After Successful Connection in the setup() Method:
Serial.println("");
Serial.println("Connected to WiFi");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());

Once connected, the program prints that it is connected successfully and displays the IP address assigned to the ESP32.

  • loop() Method:
void loop() {
// Your code here
}

The loop() method is empty in this example. This is where you would place the code that should run continuously after initialization.

What Will We Do?

Now that we have knowledge of how to establish a connection with the device, we can consider the following aspects:

  1. I have a peripheral capable of integrating into the network.
  2. This peripheral has processing capability.
  3. It operates using a programming language.

Based on these considerations, the question arises: why not develop something to explore the network?

From this premise, we will explore the IP addresses of the network to identify open ports.

Below is the corresponding code:

#include <WiFi.h>
const char *ssid = "YOUR_SSID";
const char *password = "YOUR_PASSWORD";
// List of IPs to be tested
IPAddress ips[255];
int currentIpIndex = 0;
// List of ports to be tested
int ports[] = {80, 443, 22};
void setup() {
Serial.begin(19200);
delay(10);
Serial.println("Connecting to WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
scanner();
// Wait before repeating the test
delay(5000);
}
void scanner() {
if (currentIpIndex >= 255) {
// Reset the index to start over
currentIpIndex = 0;
}
// Extract the first three octets of the IP address
byte firstThreeOctets[3];
IPAddress localIP = WiFi.localIP();
for (int i = 0; i < 3; i++) {
firstThreeOctets[i] = localIP[i];
}
// Create the IPAddress based on the first three octets and the variable last octet
IPAddress ipToTest(firstThreeOctets[0], firstThreeOctets[1], firstThreeOctets[2], currentIpIndex);
for (int j = 0; j < sizeof(ports) / sizeof(ports[0]); j++) {
WiFiClient client;
if (client.connect(ipToTest, ports[j])) {
Serial.printf("Connected to %s on port %d\n", ipToTest.toString().c_str(), ports[j]);
client.stop();
} else {
Serial.printf("Connection failed to %s on port %d\n", ipToTest.toString().c_str(), ports[j]);
}
}
// Increment the index for the next IP in the next call
currentIpIndex++;
}

Including Libraries:

#include <WiFi.h>

This part of the code includes the necessary libraries for communication with the Wi-Fi network.

const char *ssid = "YOUR_SSID";
const char *password = "YOUR_PASSWORD";

Replace “YOUR_SSID” and “YOUR_PASSWORD” with your Wi-Fi network’s SSID and password.

Lists of IPs and Ports:

IPAddress ips[255];
int currentIpIndex = 0;
int ports[] = {80, 443, 22};
  • ips: A list of IP addresses to be tested.
  • currentIpIndex: The current index in the list of IPs.
  • ports: A list of ports to be tested.

Configuration in the setup() Method:

void setup() {
Serial.begin(19200);
delay(10);
Serial.println("Connecting to WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
  • Serial.begin(19200): Initiates serial communication with a baud rate of 19200 bps.
  • WiFi.begin(ssid, password): Initiates Wi-Fi connection using the provided credentials.
  • while (WiFi.status() != WL_CONNECTED): Waits until the connection is established.

After a successful connection, the code prints messages indicating that the Wi-Fi was connected and displays the IP address assigned to the ESP32.

loop() Method:

void loop() {
scanner();
// Wait before repeating the test
delay(5000);
}

The loop() method calls the scanner() function (which is not yet defined in this code) to perform the port test and waits for 5 seconds before repeating.

scanner() Method:

void scanner() {
if (currentIpIndex >= 255) {
// Reset the index to start over
currentIpIndex = 0;
}
  • scanner(): A function that performs the port scan on different IPs.
  • if (currentIpIndex >= 255): When all IPs have been tested, the index is reset to start the process over.

Continuation of the scanner() Method:

// Extract the first three octets of the IP address
byte firstThreeOctets[3];
IPAddress localIP = WiFi.localIP();
for (int i = 0; i < 3; i++) {
firstThreeOctets[i] = localIP[i];
}
// Create the IPAddress based on the first three octets and the variable last octet
IPAddress ipToTest(firstThreeOctets[0], firstThreeOctets[1], firstThreeOctets[2], currentIpIndex);
  • firstThreeOctets: Extracts the first three octets of the device’s local IP address.
  • IPAddress ipToTest: Creates a new IP address using the first three octets and the variable index for the last octet.

Continuation and Completion of the scanner() Method:

for (int j = 0; j < sizeof(portas) / sizeof(portas[0]); j++) {
WiFiClient client;
if (client.connect(ipToTest, portas[j])) {
Serial.printf("Connected to %s on port %d\n", ipToTest.toString().c_str(), portas[j]);
client.stop();
} else {
Serial.printf("Connection failed to %s on port %d\n", ipToTest.toString().c_str(), portas[j]);
}
}
// Increment the index for the next IP on the next call
currentIpIndex++;
}

A loop that iterates through the list of ports and attempts to connect to each combination of IP and port. If the connection is successful, it prints the “Connected” message. Otherwise, it prints “Connection failed.”

Exploration

After compiling and uploading to the ESP32, the result on the serial port is presented as follows:

Based on this result, we identified an IP (192.168.0.1) with port 80 open, allowing enumeration of servers and open ports in the connected environment.

Attack Vectors

Considering the ESP32, it is possible to perform various types of attacks, such as:

  • Sniffer: Intercepting data on a network for analysis.
  • Port Scanning: Identifying open ports on a system.
  • WiFi Scanning: Exploring available wireless networks.
  • Brute Force Attack: Attempting to discover passwords through repeated combinations.

With the proliferation of portable devices in the IoT world, although these devices offer significant innovations, they also open opportunities for more sophisticated attacks, often carried out at costs lower than $5.

How to Protect Yourself?

To protect against these attack vectors, it is crucial to adopt robust security practices, including:

  • Constant Monitoring: Regularly monitor network traffic and suspicious activities.
  • Firewalls: Configure firewalls to restrict unwanted traffic.
  • Disable Unnecessary Services: Turn off services that are not essential to reduce the attack surface.
  • MAC Address Filtering: Enable MAC address filtering on the router to allow only authorized devices. Maintain a whitelist of allowed MAC addresses.
  • Disable SSID Broadcasting: Turn off the transmission of your network’s name (SSID broadcast). This makes your network less visible to scanners but does not provide complete security.

Share Your Support

I am truly committed to creating consistent content, exploring equipment purchases, and tools to bring relevant topics. If you enjoyed this article or others I’ve shared and want to offer your support to help me continue this journey, I would be immensely grateful. Each contribution is a significant step in keeping this passion we share alive.

Here is the link to support: Buy Me a Coffee.

Thank you for your kindness and for being part of this journey! 🌟

Conclusion

In conclusion, we explored WiFi connection with the ESP32, learned about identifying open ports in the network, and discussed measures to protect against unauthorized access. The presented code demonstrated how to perform a simple port scan, emphasizing the importance of secure practices, regular updates, and awareness of potential attack vectors. Protecting your WiFi network is vital to ensure the security of connected devices, and the implementation of preventive measures is crucial to mitigate risks and maintain the integrity of the digital environment.

Referencies

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