
Proof-of-concept exploiting DJI drone Bluetooth DUML command injection, sending unauthenticated commands to read credentials, alter Wi-Fi config, and control aircraft systems.
DJI drones expose a Bluetooth interface used to establish a connection to the drone's Wi-Fi interface and exchange Wi-Fi credentials.
The Bluetooth interface checks the device's trusted UUID for three commands:
The remaining commands do not require the same authentication check. As a result, a remote attacker within Bluetooth range may be able to send unauthorized DUML commands to the drone.
Depending on the command, an attacker may be able to modify the drone's configuration, including changing the Wi-Fi password and potentially gaining access to the drone's internal network, enabling or disabling radio interfaces, restarting or powering off the aircraft, resetting configuration, and performing other actions.
The POC provides a command registry that allows the available commands to be tested without modifying the Python source code. The command registry, including the command, receiver, authentication requirements, and description of each command, is defined in commands.json.
| Product | Affected Version |
|---|---|
| DJI Neo | 0 – 01.00.0400 |
| DJI Neo 2 | 0 – 01.00.0500 |
| DJI Flip | 0 – 01.00.1200 |
| DJI Air 3 | 0 – 01.00.1600 |
| DJI Air 3S | 0 – 01.00.1400 |
| DJI Avata 2 | 0 – 01.00.0400 |
| DJI Avata 360 | 0 – 01.00.0300 |
| DJI Mavic 3 | 0 – 01.00.1400 |
| DJI Mavic 3 Classic | 0 – 01.00.0800 |
| DJI Mavic 3 Pro | 0 – 01.01.0700 |
| DJI Mavic 4 Pro | 0 – 01.00.0500 |
| DJI Mini 2 | 0 – 01.07.0200 |
| DJI Mini 3 | 0 – 01.00.0500 |
| DJI Mini 3 Pro | 0 – 01.00.0900 |
| DJI Mini 4 Pro | 0 – 01.00.1100 |
| DJI Mini 5 Pro | 0 – 01.00.0600 |
https://github.com/user-attachments/assets/57f51df2-5160-404c-9fd3-2a3a8b700008
# Clone the repository
git clone https://github.com/Wh02m1/CVE-2026-78306-POC.git
cd CVE-2026-78306-POC
# Create and activate a Python virtual environment
python3 -m venv venv
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
python3 ble_console.py
The following commands are registered in commands.json. The POC separates commands into read, configuration, radio-control, reset, system, and parameter operations.
These operations are classified as danger in the POC and therefore require explicit confirmation before being sent.
The radio-control commands are implemented through the corresponding dji_network handlers.
| Command | What it does |
|---|---|
| Factory Reset WIFI | Restores the Wi-Fi configuration to its default state. |
| Factory Restore Params | Restores the network configuration parameter table to factory defaults. |
The POC marks both operations as dangerous because they modify persistent configuration.
| Command | What it does |
|---|---|
| Change a parameter | Changes a drone configuration parameter using its 32-bit name hash. |
| Reset a parameter | Resets a configuration parameter to its firmware default. |
The POC obtains parameter names from flyc_parameters.txt and provides interactive parameter selection. To add a known parameter that you want to modify or reset, add its name to flyc_parameters.txt. The parameter will then be available for selection when the POC is started.
commands.json, Not the CodeThe menu is generated from commands.json at startup. To add a command, add a new object to a section's commands list. The command will appear the next time the POC is started.
Example:
{
"label": "GET Channel",
"cmd_set": "0x07",
"cmd_id": "0x2c",
"receiver": "0x07",
"payload": "",
"tier": "read",
"bt_reply": true,
"note": "wms_evt_get_chan -> wifi_mgmt_get_chan."
}
The default receiver is 0x07 (network:0) and the default sender is 0x02 (mobile:0).
Interactive payload builders are defined in payload_builders.py.
Available builders include:
ssidpskcountrymacchannelbss_typepower_levelrawTo add a new builder, implement the function, register it in BUILDERS, and reference its name from commands.json.
Commands classified as danger require explicit confirmation before transmission.
The confirmation screen displays information such as:
──────────────────────────────────────────────────────────────────────
!!! DANGEROUS COMMAND !!!
──────────────────────────────────────────────────────────────────────
COMMAND device_reset L1 config
ROUTE 00/de -> ve_air:1
PAYLOAD 11 01 00 00 00 00
DOES system / FC / gimbal / camera / wifi / sdr config reset
WARNING The FC configuration reset can restart the motors.
──────────────────────────────────────────────────────────────────────
Type YES to send:
The DOES information is taken from the command's note, while additional warnings are taken from the warn field in commands.json.
The Change a parameter function provides access to the known configuration parameters listed in flyc_parameters.txt.
A parameter can be selected by name, supplied with a value, converted to the selected little-endian width, and sent using set_cfg_item (0x03/0xf9).
Reset a parameter uses reset_cfg_item (0x03/0xfa) to restore the selected parameter to its firmware default.
The POC also provides several predefined macros:
| Macro | Description |
|---|---|
| Restart Wifi | Stops and starts Wi-Fi (0x42 followed by 0x41). |
| SET NEW PSK + Restart wifi | Changes the PSK and then restarts Wi-Fi. |
| Probe read commands | Sends the registered read commands and reports which commands respond. |
The macros are defined separately from the individual command entries.
⚠️ WARNING: This proof of concept is intended strictly for educational, security-research, and authorized penetration-testing purposes.
This POC demonstrates security issues in the DJI Bluetooth/DUML command-handling interface. Some commands can modify device configuration, disable radio interfaces, interrupt connectivity, reboot or power off the aircraft, reset configuration, or delete stored data.
⚠️ Do NOT use this POC against any aircraft, device, network, or system that you do not own or do not have explicit authorization to test.
Some commands may cause data loss, configuration changes, loss of connectivity, device disruption, or other unintended consequences. Testing should only be performed in a controlled environment where the aircraft and surrounding people and property are not at risk.
The authors are not responsible for any damage, data loss, service interruption, aircraft operation, or other consequences resulting from the use or misuse of this POC.
⚠️ By using this POC, you accept responsibility for ensuring that your testing is authorized and complies with all applicable laws, regulations, and responsible-disclosure requirements.
| Command | What it does |
|---|
| GET SSID | Retrieves the configured Wi-Fi SSID. |
| GET PSK | Retrieves the Wi-Fi WPA2 pre-shared key. |
| GET MAC | Retrieves the Wi-Fi AP MAC address. |
| GET Country Code | Retrieves the two-letter regulatory country code. |
| GET Channel | Retrieves the currently active Wi-Fi channel. |
| GET Band | Retrieves the configured 2.4/5 GHz band selection. |
| GET RSSI | Queries the RSSI handler; this firmware build contains a stub implementation. |
| GET WiFi/BT status | Retrieves the Wi-Fi and Bluetooth radio state. |
| GET Device Info/Model | Retrieves device and model information. |
| GET Version | Retrieves the daemon version. |
| GET Bluetooth Name | Retrieves the Bluetooth device name. |
| Command | What it does |
|---|
| SET SSID | Changes the configured Wi-Fi SSID. |
| SET PSK | Changes the configured Wi-Fi password. |
| SET MAC Address | Changes the runtime Wi-Fi BSSID configuration. |
| SET Country Code | Changes the configured regulatory country code. |
| SET Country Code Ext | Handles extended country-code configuration. |
| SET Channel | Changes the Wi-Fi channel and causes the AP to restart. |
| Command | What it does |
|---|
| Start WIFI | Starts the Wi-Fi interface and associated services. |
| Stop WIFI | Stops the Wi-Fi interface. |
| Restart WIFI + BT | Restarts the Wi-Fi and Bluetooth subsystems. |
| Start Bluetooth | Starts the Bluetooth subsystem. |
| Stop Bluetooth | Stops the Bluetooth subsystem and terminates the current session. |
| Sysmode power control | Controls the Wi-Fi/Bluetooth power state. |
| Command | What it does |
|---|
ftpd_start | Starts the dji_ftpd service. |
storage_export_enable | Enables the storage-export configuration. |
storage_export_disable | Disables the storage-export configuration. |
play_sound | Triggers an aircraft sound. |
mute | Mutes the aircraft speaker. |
unmute | Unmutes the aircraft speaker. |
reboot_plain | Reboots the aircraft. |
reboot_poweroff | Powers off the aircraft. |
reboot_powersave | Places the aircraft into power-save mode. |
device_reset L1 config | Resets system, flight-controller, gimbal, camera, Wi-Fi, and SDR configuration. |
device_reset L2 +MEDIA | Performs the L1 reset and formats media/storage. |
device_reset L3 +log | Performs the L2 reset and additionally clears the system log. |
| Field | Required | Meaning |
|---|
label | Yes | Text displayed in the menu. |
cmd_set | Yes | DUML command-set identifier. |
cmd_id | Yes | DUML command identifier. |
receiver | Yes | Wire receiver byte, (index << 5) | type. |
payload | No | Hex payload. |
tier | No | read, write, or danger. |
builder | No | Interactive payload builder. |
auth | No | Indicates that a trusted UUID is required. |
bt_reply | No | Controls whether the POC waits for a Bluetooth response. |
sender | No | Sender byte; defaults to 0x02. |
after | No | Optional follow-up action. |
note | No | Reverse-engineering description shown by the POC. |
warn | No | Additional warning text displayed for dangerous commands. |
| File | Role |
|---|
ble_console.py | Main entry point, menu and command execution. |
commands.json | Command registry and command descriptions. |
ble_transport.py | Bluetooth GATT scanning, connection and response handling. |
duml_protocol.py | DUML v1 packet construction and CRC handling. |
duml_decoders.py | Response decoding and return-code handling. |
payload_builders.py | Interactive payload generation. |
parameters.py | Configuration parameter hashing and operations. |
terminal.py | Terminal UI, prompts and output handling. |
flyc_parameters.txt | Known configuration parameter names. |
requirements.txt | Python dependencies. |