<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[samblack]]></title><description><![CDATA[Musings on security and stuff.]]></description><link>https://samblack.co</link><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Apr 2026 11:26:34 GMT</lastBuildDate><atom:link href="https://samblack.co/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Christmas drone defence shenanigans]]></title><description><![CDATA[Over Christmas, one of my relatives turned up with a cheap build-a-drone kit they’d bought off AliExpress for their kid. The sort of thing you half expect to work just well enough to impress a child and then fail catastrophically. Instead of flying i...]]></description><link>https://samblack.co/christmas-drone-defence-shenanigans</link><guid isPermaLink="true">https://samblack.co/christmas-drone-defence-shenanigans</guid><category><![CDATA[drones]]></category><category><![CDATA[cybersecurity]]></category><category><![CDATA[cds ]]></category><category><![CDATA[#cross-domain]]></category><dc:creator><![CDATA[Sam Black]]></dc:creator><pubDate>Mon, 05 Jan 2026 16:37:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1767630289742/dd5eeefb-07f6-4a45-9705-291737aa7b15.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Over Christmas, one of my relatives turned up with a cheap build-a-drone kit they’d bought off AliExpress for their kid. The sort of thing you half expect to work just well enough to impress a child and then fail catastrophically. Instead of flying it, I did what I usually do with unfamiliar things: I started taking it apart conceptually. How does it talk? How can I break it? Ultimately, how can i find an excuse to do some work over Christmas..</p>
<p>It didn’t take long to end up staring at the control traffic. Unsurprisingly, it was <a target="_blank" href="https://mavlink.io/en/">MAVLink</a>. Lightweight, chatty, flexible, and largely built around the assumption that everyone on the link is friendly. That isn’t a criticism so much as a design reality. MAVLink is optimised for low bandwidth, low latency links between constrained devices. Authentication, confidentiality, and strong integrity guarantees are explicitly not first-class concerns in most deployments. For a £90 drone flown from a phone app, that’s entirely reasonable.</p>
<p>What made it interesting was the wider context. We now see this exact class of hardware and protocol used in operationally serious environments. Sometimes the ground control station is a ruggedised laptop in the field. Sometimes it’s something far more sensitive, connected to other systems, networks, and data flows that absolutely do matter. In those cases, the threat model changes completely.</p>
<p><a target="_blank" href="https://www.warvector.com/p/11-reasons-fpvs-are-better-than-bombs"><img src="https://substackcdn.com/image/fetch/$s_!baRq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa833391b-8cf1-48f6-b360-6bba935d0975_1280x600.webp" alt="DIY GUIDED ANTI TANK ROUND" /></a></p>
<p>At that point the problem is no longer “what if someone attacks the drone?”. It’s “what if the drone becomes an ingress path into the control system?” or the inverse: “what if a compromised or malfunctioning GCS issues technically valid but operationally dangerous commands?”. MAVLink doesn’t distinguish between sensible and dumb. If the message is well-formed it will be accepted.</p>
<p>That line of thinking led me to my day job (of course). Mavlink Security Gateway. Not a firewall. Not a packet filter. Not “just add encryption” or “ZERO TRUST OVERLAY!!!11”. A Cross Domain Solution, sort of: something that understands the data model of the protocol, is configured according to an information handling model and data taxonomy, enforces explicit policy at a trust boundary, and fails closed. In my initial experiments the boundary is just localhost, but there is nothing about the idea that doesn’t scale to radio links, network segments, or physically separate domains.</p>
<p><img src="https://www.4-secure.com/wp-content/uploads/2025/02/how-a-data-diode-works-44.svg" alt /></p>
<p><em>A high level over view of what a CDS (sort of) does</em></p>
<p>The core idea is a small gateway that sits between two MAVLink endpoints, on a more trusted network segment and mediates everything. It parses messages, tracks state, and makes an explicit allow/deny decision for each message based on policy. That immediately opens up a much richer control surface than most people realise they need.</p>
<p>For example: allow and deny lists for message types are the obvious start, but they’re not sufficient. Many MAVLink messages are overloaded or context-dependent. A <code>PARAM_SET</code> is very different depending on which parameter is being touched and what value is being written. A <code>MISSION_ITEM</code> upload might be acceptable in one phase of operation and completely unacceptable in another. Heartbeats and attitude updates are benign until they’re used as a covert signalling channel.</p>
<p>So the gateway needs to do more. Sanity checking fields and ranges, not just structure. Enforcing replay protection by tracking sequence numbers and timing. Being able to block entire classes of behaviour: parameter enumeration, parameter writes, log downloads, mission uploads, debug and status text. All of these are perfectly valid MAVLink features. All of them are also excellent ways to leak data, influence behaviour, or create side effects across a trust boundary.</p>
<p>I ended up with a simple JSON-based policy schema to describe what “normal” looks like. Which messages are expected, in which direction, at what rate, with what value ranges. Everything else gets dropped by default. It’s deliberately boring and explicit. That’s the point. Implicit trust is replaced with explicit permission.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767632114010/dd03f9e8-d767-41e5-afed-1641c640ad22.png" alt="The concept, kinda." class="image--center mx-auto" /></p>
<p><em>The concept of the security gateway, kinda</em></p>
<h2 id="heading-heres-an-example-of-some-of-the-fun-stuff-you-can-block-or-allow-or-exploit-if-youre-so-inclined">Here's an example of some of the fun stuff you can block, or allow, or exploit if you're so inclined</h2>
<h3 id="heading-common-command-ids">Common Command IDs</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>ID</td><td>Name</td><td>Risk</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td>400</td><td><code>ARM_DISARM</code></td><td>Critical</td><td>Arm or disarm the vehicle (motors on/off)</td></tr>
<tr>
<td>176</td><td><code>DO_SET_MODE</code></td><td>High</td><td>Change flight mode</td></tr>
<tr>
<td>20</td><td><code>NAV_RETURN_TO_LAUNCH</code></td><td>Medium</td><td>Return to launch position</td></tr>
<tr>
<td>21</td><td><code>NAV_LAND</code></td><td>Medium</td><td>Land at current location</td></tr>
<tr>
<td>22</td><td><code>NAV_TAKEOFF</code></td><td>High</td><td>Take off to specified altitude</td></tr>
<tr>
<td>92</td><td><code>NAV_GUIDED_ENABLE</code></td><td>High</td><td>Enable external control</td></tr>
<tr>
<td>183</td><td><code>DO_SET_SERVO</code></td><td>High</td><td>Direct actuator control</td></tr>
<tr>
<td>184</td><td><code>DO_REPEAT_SERVO</code></td><td>High</td><td>Direct actuator control (repeat)</td></tr>
<tr>
<td>185</td><td><code>DO_FLIGHTTERMINATION</code></td><td>Critical</td><td>Kill switch - immediately stop vehicle</td></tr>
<tr>
<td>252</td><td><code>PREFLIGHT_REBOOT</code></td><td>Critical</td><td>Reboot autopilot</td></tr>
<tr>
<td>511</td><td><code>SET_MESSAGE_INTERVAL</code></td><td>Low</td><td>Set message stream rate</td></tr>
<tr>
<td>512</td><td><code>REQUEST_MESSAGE</code></td><td>Low</td><td>Request a specific message stream</td></tr>
<tr>
<td>520</td><td><code>REQUEST_AUTOPILOT_CAPABILITIES</code></td><td>Low</td><td>Request autopilot capabilities</td></tr>
</tbody>
</table>
</div><hr />
<p>Digging into some of the above, <code>ARM_DISARM</code>, Yes obviously critical. But mostly because “arm” and “disarm” are treated as moral opposites when only one of them is actually exciting. Disarm at the wrong time is rude. Arm at the wrong time is a career-limiting move.</p>
<p><code>NAV_RETURN_TO_LAUNCH</code> - Calling this “Medium” assumes your home position is correct, trustworthy, and not set by someone who hates you. If home is wrong, this is just “fly enthusiastically to the wrong place”.</p>
<p><code>DO_FLIGHTTERMINATION</code> - This is a fun one. To borrow an excerpt from <a target="_blank" href="https://docs.px4.io/">PX4</a>'s documentation. “<em>There is no way to recover from flight termination. After triggering you should unplug the battery as soon as possible. You will need to reboot/power cycle the vehicle before it can be used again. When Flight termination is activated, PX4 simultaneously turns off all controllers and sets all PWM outputs to their failsafe values.”.</em> So, it’s the big red button.</p>
<p>As you can see there’s clearly a defensive angle to consider for the airframe as well as keeping the system controlling it safe. If your control system is compromised, misconfigured, or simply buggy, MAVLink will quite happily forward commands that are legal but stupid: extreme parameter values, nonsensical missions, mode changes at the wrong time. A gateway that encodes basic operational expectations can prevent a surprising amount of damage without needing to trust the sender at all. It becomes a safety layer as much as a security one.</p>
<p>None of it feels dangerous in isolation. In aggregate, across a boundary between domains with different trust assumptions, it very much is. The project itself is very much a prototype. It is not production ready, and it is not pretending to be. But it was a useful exercise, and a useful reminder. A lot of cyber-physical systems rely far too heavily on the assumption that the other end of the wire is well-behaved. When that assumption fails, the protocol will not save you.</p>
<p>All of this was kicked off by a cheap Christmas drone, a bit of curiosity, and me looking for an excuse to get my laptop out. “How can I make a CDS for it?” has turned out to be a surprisingly effective way of learning new things.</p>
<p>The project is here if you’re interested and want to go on a deep dive into what the gateway can block, allow and how you can use it. This little overview is super high level and there’s a million little fun details about MAVlink not covered: <a target="_blank" href="https://github.com/samb4secure/mavlink-security-gateway">https://github.com/samb4secure/mavlink-security-gateway</a></p>
]]></content:encoded></item></channel></rss>