TLStorm - Three Critical Vulnerabilities in Smart-UPS devices

We discussed this vulnerability during Episode 130 on 22 March 2022

Two logic bugs that cause memory corruption in the handling of TLS packets due to unhandled error / return values when using the nanoSSL library, and a higher level design flaw with the firmware update system.

Uninitialized use yielding authentication bypass in TLS handshake First bug is in the TLS handshake process. Under normal circumstances, a client is supposed to send a ClientHello message to the server, which then responds with a ServerHello message. This server response contains the session ID as well as the cipher suite to be used. If the session ID matches the current TLS state’s session ID, the session is “resumed” and the master secret will be copied from the cache. If the session ID is new, the client will validate the cipher suite provided by the server and perform key exchange.

The problem comes if the client sees a cipher suite from the server that it doesn’t support. In this case, the handler returns an error and the TLS connection is supposed to be terminated. Because APC ignores this return value, the connection stays open, and upon subsequent ServerHello messages, it will reuse the previous session information and “resume” the uncompleted session. This results in the master secret in the cache being used uninitialized as zeroes, which allows an attacker to establish a successful session as if they were a trusted server.

Buffer overflow in TLS packet reassembly Second bug is in the TLS packet reassembly process. When TLS records are sent over TCP from peer to peer, they’re sent as a header (which includes the content type and payload length) followed by the payload. The library has to keep track of the “reassembly state” as it receives records. When expecting the payload, the incoming message buffer is reallocated if the length exceeds the previous buffer size. However, if the payload length >= 2389, an error value is returned and the buffer is not reallocated.

Again, this return value is ignored higher up in the call stack, this time by the coap_received_sock_cb() function. If an attacker simply sends a packet with a large length field, the buffer will never get reallocated and it will copy in packet data until that length is reached, without regard to the size of the incoming message buffer.

No code signing for firmware updates While crypto is used for firmware updates, only symmetric encryption is used. No proper code signing is used to authenticate the firmware update data. An attacker can just pull the symmetric key off one UPS and use it to create malicious firmware updates for other devices to backdoor a target device.