Insulet OmniPod Insulin Management System vulnerability

Content:

Summary

The Insulet OmniPod Insulin Management System, also commonly known as OmniPod Eros, suffers from a protocol design vulnerability. During normal use of the insulin pump, a potential attacker can utilize replay-like techniques to obtain a nonce-word. With this, it is possible to send several Programming Commands of their choice to the OmniPod. Some of the worst uses for this would be:

After obtaining the nonce-word the attacker can send any of these commands without the consent of the user and without any alerts displaying on the user’s devices.

This exploit has been tested possible with a LimeSDR from up to 6m away. However, no specific effort has been made to try and extend this range as the goal of this project is proof-of-concept not weaponizing. The exploit is written by people who are NOT professionals within the field of signal processing with minimal equipment. Therefore there is no guarantee that this exploit is only limited to 6m and much longer distances could likely be achieved by other groups.

A custom controller often referred to as a “loop”, is also vulnerable. This is because any piece of hardware communicating with the pump need to follow the protocol and its vulnerabilities. The “loop” hardware also offers longer distances during normal usage, so it is very likely that “loop”'ers are exploitable over longer distances with this exact exploit.

Technical Writeup

The first part of this section contains a description of the communication protocol used between the insulin pump itself and the controller, from here on referred to as POD and PDM respectively. This is a minimal description of the protocol and just contains the needed information for understanding the vulnerability.

The second part contains an explanation of the vulnerability itself, how it can be exploited for silent access and what dangerous malicious usage this enables.

Protocol Layers

The OmniPod vulnerability is a protocol design vulnerability. This section will therefore cover the parts of the protocol relevant for understanding the vulnerability. Nearly all information used in this section was initially found on the OpenOmni Github. This has been an invaluable resource to us and the amount of work put into their project is quite amazing, we highly encourage anybody interested to go and read more. However, we have also confirmed all information presented in this section through testing on real equipment bought from Insulet.

The POD and PDM communicate over 433MHz radio. Three packaging layers exist on top of the 433MHz radio communication. In order of abstraction (high to low) the layers are command (and response), message and packet.

Command Layer

All communication between POD and PDM originates from the PDM sending a Command and POD responding. Commands and Responses are very similar in structure so we will not distinguish the two.

The first byte of a command specifies the command type, 0x03 = “Setup pod”, 0x11 = “Insulin Schedule” etc. The second byte denotes the length of the command. All following bytes are command-specific parameters packed in as ordered bytes. An accumulated list of all Commands can be found on the OpenOmni Github message types page.

“Important” commands, such as scheduling insulin, immediate insulin, cancelling deliveries, deactivating pump etc. are called Programming Commands. All Programming Commands requires a 4-byte nonce as the first parameter. Upon setup of a pump, the PDM and POD exchange the LOT and the serial number of the POD which is used to seed a pseudo-random generator within both the PDM and POD. After pairing, these generators should stay in sync for the lifetime of the POD. In case they get out of sync a process of re-syncing is initiated but the new seed will still depend on the serial number transmitted during pump setup. So unless one has intercepted the initial setup phase one cannot know nonce ahead of time[1].

Message Layer

As shown in the figure below, commands are packed into messages. The message header consists mainly of the POD ID, message nr and message length. At the end of a message, following all message data (including header) is a CRC16 checksum.







Fig 1


cluster M

Message



CRC16

CRC16



...

...



Command 2

Command 2



Command 1

Command 1



Message Header

Message Header



A message to the Pod can consist of one or more commands. In general Programming Commands can be combined into a single message (using the same nonce value for all) along with any non-nonce commands. The “Insulin Schedule” is the only exception and must always occur alone followed by its specific follow up commands without any additional commands[2].

Packet Layer

As the last layer before data is pushed over the wire a message is split into packets. Packets first consist of a POD ID identifying both POD and PDM and a message type. The same POD ID is used in both data directions, from POD to PDM and PDM to POD.







Fig 2


cluster M

Packet



CRC8

CRC8



data bytes...

data bytes...



Sequence number

Sequence number



Packet type

Packet type



POD id

POD id



Packets have 4 different types:

The packet header contains a sequence number which is just a number counting up on every ACK and CON packet resetting on POD and PDM. There is no easy way to determine the size of a packet, based solely on the packet header except that is an upper bound on 31 data bytes. One can start parsing the first few data bytes making up the message header and extract the message length to determine if this is the last packet and from this determine the length of the packet.

Radio Layer

The last step of data handling happens just before transmission. Here we append a 2-byte sync word to every packet which indicates the start of data. All data, including the sync word, is then Manchester encoded and send over radio.

The POD and PDM communicate over 2 channels of frequency-modulated 433MHz radio. The baud rate is 40625 bits per second (before Manchester encoding). More details can be found on the OpenOmni Github.

Communication Flow

Here we have illustrated the way both PDM and POD receives messages based on observations.

Created with Raphaël 2.3.0Start reciving messageRecv PacketCheck crc and seq nris data valid?Append packet data to messageSend ack packetwas last packet?Parse message and validate crc16yesnoyesno

After a complete message has been received all commands are processed and the nonce is checked (if applicable) with the currently expected nonce. The commands are then executed and the nonce is progressed (if used).

The sending process is very similar and not illustrated. In the sending process if no ACK is received within a time frame the previous packet is repeated until an ACK is received or timeout is reached. In between each retry, there is a small pause where the PDM tries to receive a packet.

The Vulnerability

The actual vulnerability lies in the fact that the protocol explained above makes it possible for a potential attacker to interrupt, for instance through jamming, messages after the nonce has been transmitted without any device invalidating the nonce. Since the nonce is not tied to the command itself it can now be used for any desired command. Furthermore, as explained below, it is possible to return both devices to the expected immediate program flow, while still sending or scheduling malicious behaviour.

Exploitation

In this section, we will explain how one can obtain an unsued nonce using replay-like techniques and forge and send multiple Programming Commands in one message. We have used a LimeSDR for all experiments done in the following sections.

Aquiring POD ID, Message Number and Sequence Number

To send any packet the POD ID, message and sequence number is needed. As no encryption is employed in the system any communication will expose this information in the message and packet headers. A passive observer could for instance parse the data from a pump status[3] ahead of time (a pump status message is sent on PDM wakeup, i.e. when you push any button to turn on the screen on the PDM to use it[3:1]) progressing the numbers from this message according to the protocol. They could also extract them directly from the headers in the Programming Command, we are trying to exploit. However, without a valid nonce, we are not able to send any Programming Commands.

Aquiring Nonce

Assuming that a potential attacker has not acquired the LOT and serial number during setup it is impossible, per protocol, to know the nonce ahead of time. One can instead await any command requiring nonce (this can be seen in the command header). During transmission of this packet, they can jam the signal after having acquired the nonce. This will invalidate the CRC8 check of the packet and the nonce generator will not be progressed. The received nonce will therefore be valid and can now be used for other commands.

Exploitation

Even though a potential attacker has acquired the nonce, there is still a problem. The PDM will keep trying to resend the packet until it sees an appropriate response from the POD.

The simple solution is to just keep jamming the signal until the PDM times out. Afterwards, an attacker can send a new message/command with the acquired nonce. However, if this happens an error will show on the screen of the PDM informing the user that communication has failed. This would give the user some indication that something has gone wrong.

Another solution is to use the small pauses between packet retries to inject their packets and let the process continue as normal. As above jamming begins after receiving the nonce in the first packet. Jamming is then halted at the start of the first pause after the command is sent (and failed). During this pause, the first malicious packet is sent using the just acquired nonce. This will prompt the POD to respond with an ACK, and as jamming is halted, the PDM will receive this. This process is repeated; jamming while the PDM is sending, injecting malicious continuation packets in pauses and letting the POD ACK normally to the PDM. This is done until the PDM is done transmitting, prompting the POD to respond with the appropriate status response. Using this method, the malicious message and the original message has to be equal in length, otherwise, the POD will send either ACK’s when the PDM expects a status response or status response when the PDM expects ACKs.

The last solution is to also jam the ACKs from POD to PDM and send the expected amount of ACKs in between retry pauses from POD to PDM. This essentially creates two “communication” channels utilizing the retry pauses. One “channel” responding to the PDM and one responding to the POD. This way the PDMs message is resolved “correctly” while a completely different message is sent to the POD. Furthermore, after both communications have been completed both POD and PDM will have advanced their nonce generators and still be in sync. This is essentially a complete man-in-the-middle attack as the entire message can be exchanged without either device finding out.

Harmful Commands

Most users we have talked to have informed us that the most normal command used out and about is to ask for insulin to be delivered immidiately[4]. The intuition here is that a malicious attacker could simply change the amount of insulin that is to be delivered immediately. However, the user might notice this as for every 0.05U insulin delivered the pump motor will make a small ticking sound. The number of ticks would naturally not match up with the expected amount if the dosage is changed. This sound is noticeable in quiet environments but very hard to pick up in even moderately noisy environments, such as in a car, on a plane, or even in malls or alike. Some users have also informed us that wearing clothes over the POD can make it nearly impossible to hear the clicks even in silence.

Another strategy would be to let the PDM get ahead of the POD during jamming, finding out how much insulin the user is expecting to be delivered now. The immediate injection command also allows for the configuration of an extended insulin schedule[4:1]. Therefore it is possible to send an immediate injection command with the correct injection amount now but schedule insulin to be injected later when the user is less attentive, for instance when they are sleeping. It is possible to schedule up to 45U of insulin every half hour[5]. Naturally, the same strategy can be employed, even easier, if intercepting a user scheduling future insulin injections[6].

It is important to point out that no requests have been documented where the POD sends information about scheduled insulin. We, therefore, assume that if any device displays this information, it is under the assumption that this device is the only one communicating with the POD and would therefore not display the changes maliciously injected. We have not been able to find anywhere in our PDM that displays this information. This however also means that if a new schedule is set by the user from their PDM before the malicious one can be executed, the malicious changes would be overwritten.

Testing

We have successfully tested all the methods using a LimeSDR in combination with LiquidSDR for modulation. It should be noted that we have been focusing on doing a proof-of-concept, to bring awareness to the problem and not to try and weaponize the exploit. We have therefore not focussed on increasing exploit distance and therefore none of our tests has been able to go beyond 6 meters. We will make no further attempts to increase this range as reasoned above. We however suspect that one could get the range much higher with professional equipment, active gain on input RF, finetuning of the modulation scheme or other signal processing methods not known to two security focussed software engineers.

It is also important to talk about the system some people use, called a “loop”. This is a custom piece of hardware that is attached to a smartphone enabling it to communicate with the POD, acting as the PDM instead. As this “loop” has to adhere to the protocol is also vulnerable. However, as the main limitation for communication distance lies in the PDMs signal strength, "loop"s could be vulnerable over much larger distances even without any of the “improvements” mentioned above. This is also indicated by the fact that normal usage of the “loop” is possible over much longer distances, with users reporting several times distance improvement.

The source code for the exploit will come later when the community has had time to implement the mitigation strategies. However, as stated in the following section waiting with the source code for too long could have a detrimental effect as existing research articles may suggest that other groups, whom we naturally have no control over, could already have this information. Furthermore, if we decide to not release code entirely, other, more malicious, parties could develop this exploit themselves. For now, you can find an initial demo video of the exploit Here.

Other Research

First of all, we want to credit OpenOmni[7] and RileyLink/OrangeLink[8] for their extensive research into the protocol. Nearly all information regarding the operations of both PDM and POD presented here has been researched by these projects. The amount of work gone into those projects is very impressive. We highly encourage anybody interested in this topic to go and read on their websites.

ICSMA-20-079-01

A potentially very similar vulnerability was released in march of 2020 as ICSMA-20-079-01[9][10]. Unfortunately, no technical details were released talking about the vulnerability. Most of the article itself is dedicated to explaining the impact, risk and mitigation, not the actual vulnerability itself. The most detailed description is: “This wireless RF communication protocol does not properly implement authentication or authorization”. This could have the potential to describe the same vulnerability. However, directions given from Insulet to the doctors and health organisations we have spoken with indicate otherwise. Here Insulet warns that people can exploit the system if they manage to snoop during the setup process, getting the seed, enabling them to generate nonce themselves. This is not needed for the vulnerability described in this article. It is however impossible to verify without more technical details.

As we were not able to find any technical details and since the article itself seems to link to a wrong CVE number (or if not, this very much not the same vulnerability), we have decided that our research can stand on its own.

In any case, the mitigation strategies released for ICSMA-20-079-01, are not sufficient for the vulnerability stated here and this follow up research was no doubt needed.

Potential Fixes

The intuitive answer to the problem is encryption, as it is the tried and true method, and one could rely on existing solutions reducing the risk of implementation or design errors. This solution is not trivial though due to possible hardware limitations, such as battery life, CPU power or memory. However, this would not be the first time encryption was used in an embedded device. It also helps that the devices already have a shared secret so synchronous encryption could be used.

If battery life is a really big problem one could also employ a solution that is only used during Programming Commands. Here one would hash (using an SHA algorithm) the command together with the nonce instead, and only send hash and the command. For an attacker to not be able to brute-force the nonce, it probably needs to be increased to 128 bits or 256 bits. It would probably also be considerably easier to find an SHA algorithm that requires significantly fewer resources than actual encryption. Even more, this solution would mean that extra resources would only be expended during Programming Commands.

Metigations

First of all, any security fixes to the protocol have to be implemented on both sides. Since the POD is very hard to open up and tinker with (even for professionals[11]) any firmware updates or similar mitigating strategies for the system is practically impossible to implement for anybody other than Insulet during production. Even “loop”'ers have to adhere to the protocol expected by the POD and can therefore not fix the protocol security vulnerability themselves.

It seems for now, that the only mitigation users can take is to not use this product until Insulet addresses the problem or to permanently switch to a different product.

If using another product is not possible, at least not immediately, we recommend employing a strict “no use” policy outside your own home. This first of all means not doing any of the following unless absolutely necessary:

This is because the commands associated with these actions run the risk of exposing nonce to a potential attacker. If possible, we even recommend not using the PDM at all while out as this could expose sensitive information. This is further discussed in the next section “Other Problems”. However, even this strategy only reduces your risks and is NOT completely secure. This is because it may be possible to go beyond the range we have been able to achieve, by anybody more familiar with radio wave signal processing. This could result in a range extension enabling attackers to reach inside peoples homes.

Furthermore, no tests have been done with the “loop” equipment so the range for this hardware could be, and likely is, much longer.

Other Problems

As the observant reader may have already noticed, no information sent back and forth is encrypted. This can come as quite a surprise, as encryption seems like the default for everything online, and especially when it comes to sensitive personal data. It is important to point out that any data transfer is very localized, temporary and less personalized than one could fear. However, being able to snoop on how much insulin people around you are taking and persistently identifying the same user over several days is an obvious problem. It is hard to speculate on why this decision was taken, maybe encryption is not viable with the hardware given, either for storage reasons or due to lack of processing power/battery life. However, this could also indicate that temporary (3 days) pumps that are thrown away after use, with no option for refilling/recharging is not a good solution for an insulin pump.

FAQ

Has this equipment not been outdated by the new OmniPod DASH?

While Insulet is currently stating that they are trying to switch users to the OmniPod DASH, the Eros system is actively being produced and is still the product used by the majority.

Despite Insulets efforts, the Eros system still sees increased usage. For instance, they saw a nearly 10% increase from 2019 to 2020 in Denmark. We only know this because we are ourselves are from Denmark and have been able, through journalists using our country’s legal system, to request our health sector financial purchase statistics regarding Insulet. Insulet has not been willing to cooperate directly in any matter.

Can’t you just take off the POD if anything happens?

While the POD is easily removable it is possible to send malicious commands without the user noticing. It is also possible to schedule commands for later injection, for instance when the user is sleeping, as seen in section “Harmful Commands”.

Would a fix for this vulnerability not also lock out the “loop” system?

No. It is possible to fix the protocol so that it allows any piece of hardware following the protocol to pair with the pump, while still being secure during normal usage, see Potential Solutions. Physical access is required to initiate pairing and the gain can be (and already is) lowered during pairing. Since pairing happens inside peoples homes, this strategy makes it very hard and practically impossible to snoop on the pairing process.

Many embedded devices require physical access to initiate pairing but are then temporarily vulnerable during the pairing process. This is a normal strategy and is usually considered secure (if nothing else is “wrong”) if done in a physically secure environment, like your home.

An update for the system would mean that OpenOmni and RileyLink have to update their software too, however, compared to their existing work, this would be a fairly minor update. Furthermore, since their projects are open-source, anybody (including us) would be able to submit the necessary code change.

What was the XOR solution I read about on Reddit?

We, unfortunately, released this document with a flawed potential solution. It should have been corrected now. Sorry, crypto mistakes are easy to make 😅

Disclosure Timeline


  1. Nonce calculation and information https://github.com/openaps/openomni/wiki/Nonce ↩︎

  2. All commands in a Message can share the same nonce https://github.com/openaps/openomni/wiki/nonce#implementation-notes ↩︎

  3. OpenOmni status request https://github.com/openaps/openomni/wiki/Command-0E-Status-Request ↩︎ ↩︎

  4. OpenOmni documentation for immidiate insulin injection command (bolus command) https://github.com/openaps/openomni/wiki/Command-1A-Table-2 ↩︎ ↩︎

  5. OpenOmni insulin schedule element https://github.com/openaps/openomni/wiki/Command-1A-Insulin-Schedule#insulinscheduleelement ↩︎

  6. OpenOmni schedule insulin commands https://github.com/openaps/openomni/wiki/Command-1A-Insulin-Schedule ↩︎

  7. OpenOmni Github page https://github.com/openaps/openomni ↩︎

  8. Riley link website https://getrileylink.org/ ↩︎

  9. Possibily relevant previously disclosed vulnerability regarding Omnipod security https://us-cert.cisa.gov/ics/advisories/icsma-20-079-01 ↩︎

  10. Insulets own statement regarding ICSMA-20-079-01. https://www.omnipod.com/product-security/security-bulletins/march-18-2020 ↩︎

  11. Deep dip teardown of tubeless insulin pump by Sergei Skorobogatov https://arxiv.org/pdf/1709.06026 ↩︎