PoC or GTFO, Volume 2
Page 25
We are unable to provide a fixed memory address of the network key, as it varies among device types. Even so, because the memory is so empty (>99% zeros), the key is always easy to find. In all three of Billy’s Z-Wave devices, the key is within the only string of at least 16 bytes in memory. The region of the EEPROM memory of Billy’s PIR sensor containing the same network key follows, with the key itself starting at address 0x60A0.
Figure 12.3: EEPROM on an Aeotec Multisensor 4
For reference, the segment of memory in Billy’s door lock containing the network key follows. The network key starts at address 0x012D.
Each device contains a network key, an authentication key, and an encryption key. The network key is common throughout the network and is shared with the devices by using default authentication and encryption keys that are the same for all third and fifth generation Z-Wave devices in the world. The authentication and the encryption key on the device are derived from the network key and the nonces of all 5s and all As respectively.
Do You Hear What I Hear? A Frame, a Frame, Encapsulated in a Frame, Is Encrypted
Even armed with the keys, the patient reader still needs to know how to use them. The Z-Wave security service provides immutable encryption and authentication through the use of an encapsulation frame. The encapsulation security frame is identified in the first two bytes of the application layer payload. The first byte specifies the command class, and the second provides the command, where an encapsulated security frame has byte values of 0x98 and 0x81, respectively. The remainder of the frame contains the eight upper bytes of the IV, used for both encryption and signing, the variable length encapsulated and encrypted pay-load, the nonce ID, and an 8-byte CM AC (cipher-based message authentication code).
At a minimum, the frame encapsulated in the security frame is three bytes. The first byte is used for fragmentation; however, we have yet to observe a value other than 0x00 in this field. The second byte provides the command class and, like the application layer, is followed by a single command byte and zero or more bytes of arguments.
The application payload is encrypted using the encryption key and an AES cipher in OFB mode with a 16-byte block size. OFB mode requires a 16-byte IV, which is established cooperatively between the source and destination. The lower 8 bytes of the IV are generated on request by the destination, which OpenZwave calls a nonce, and are reported to the requestor before the encapsulation frame is sent. The first byte of this 8-byte nonce is what we referred to as the nonce ID. The upper eight bytes of the IV are generated by the sender and included in the encapsulation security frame. When the destination receives the encapsulated frame, it decrypts the frame using the same cipher setting and key. It is able to reconstruct the IV using the IV field of the encapsulated frame and by using the nonce ID field to search its cache of generated nonces.
Joy to the Home, Encrypted Traffic is Revealed
Some cautious readers may become anxious when two automations are having a private conversation within their dwelling. This is especially true when one of them is a sensor, and the other is connected to the Internet. Fear not! Armed with knowledge of the encapsulation security frame and possession of the network or encryption key, the triumphant reader can readily decrypt frames formerly hidden from them. They will hopefully discover, as we have, that Z-Wave messages are devoid of sensitive user information. However, may the vigilant reader be a sentry to warn us if any future transgressions do occur in the name of commercialism and Orwellianism.
To aid the holy sentry, we provide the PoC decryptPCAPNG tool to decrypt Z-Wave encapsulated Z-Wave frames. The user provides the network or encryption key. The tool assumes the user is capturing Z-Wave frames using either Scapy-radio or EZ-Wave with an SDR, which sends observed frames to Wireshark for capture and saving to PCAPNG files.
What Frame Is This, Who Laid to Rest, upon Receiver’s Antenna, Did Originate?
Secure Z-Wave devices do not act upon a command issued in an encapsulation frame unless its CMAC is validated. Thus, the active reader wishing to do more than observe encrypted messages requires further discourse. Certainly, the gremlin wishing to open Billy’s front door desires the ability to generate an authenticated unlock-door command.
The Z-Wave CMAC is derived using the CBC-MAC algorithm, which encrypts a message using an AES cipher in CBC mode using a block size of 16 bytes. It uses the same IV as the encryption cipher, and only the first eight bytes of the resulting 16-byte digest are sent in the encapsulation frame to be used for authentication. Instead of creating the digest from the entire security encapsulation frame, a subset of fields are composed into a variable-length message. The first four bytes of this message are always the security command class ID, source ID, destination ID, and length of the message. The remaining portion of the message is the variable length encapsulated frame (e.g., an unlock-door command, including the fragmentation byte) after it has been encrypted.
The recipient of the encapsulation security frame validates the integrity of the frame using the included 8-byte CM AC. It is able to generate its own CMAC by reconstructing the message to generate the digest using the available fields in the frame, the IV, and the authentication key. If the generated CMAC matches the declared value in the frame, then the source ID, destination ID, length, and content of the encapsulated frame are validated. Note that, since the other fields in the frame are not part of the CMAC message, they are not validated. If the generated digest does not match the CMAC in the frame, the frame is silently discarded.
Bring a Heavy Flamer of Sanctified Promethium, Jeanette, Isabella
Knock! Knock! Knock! Open the door for us!
Knock! Knock! Knock! Let’s celebrate!
We wrote OpenBarley as a PoC tool to demonstrate how Z-Wave security works. Its default encapsulated command is to unlock a door lock, but the user may specify other, arbitrary commands. The tool works with the GNURadio Z-Wave transceiver available in Scapy-radio or EZ-Wave to inject authenticated and encrypted frames.
The reader must note that battery operated Z-Wave devices conserve power by minimizing the time the transceiver is active. When in low-power mode, a beam frame is required to bring the remote device into a state where it may receive the application layer frame and transmit an acknowledgment. Scapy-radio and EZ-Wave did not previously support waking devices with beam frames, so we have contributed the necessary GNURadio Z-Wave blocks to EZ-Wave.
It Came!
Somehow or Other, It Came Just the Same!
This Christmas, as we have done, may you, the blessed reader, extract the network key from the EEPROM of a Z-Wave device. May you use our PoCs to send authenticated commands to any other secured device on your network. May you enlighten your friends and neighbors, affording them the opportunity to sanctify by fire, or with lesser, more legal means, home automation lacking physical security in the name of Manion Butler and his holy mother. May you use our PoCs to watch the automation for privacy breaches and data mining in the time to come, and may you brew in peace.
12:4 Content Sniffing with Comma Chameleon
by Krzysztof Kotowicz and Gábor Molnár
The nineties. The age of Prince of Bel Air, leggings and boot sector viruses. Boy George left Culture Beat to start a solo career, NCSA Mosaic was created, and SQL injection became a thing. Everyone in the industry was busy blowing the dot-com bubble with this whole new e-commerce movement — and then the first browser war started. Browsers rendered broken HTML pages like crazy to be considered “better” in the eyes of the users. Web servers didn’t care enough to specify the MIME types of resources, and user agents decided that the best way to keep up with this mess is to start sniffing. MIME type sniffing, that is.6 In short, they relied on heuristics to recognize the file type of the downloaded resource, often ignoring what the server said. If it quacks like an HTML, it must be HTML, you silly Apache. Such were the 90s.
This MIME type sniffing or content sniffing has obviously led to a new class of web security pr
oblems closely related to polyglots: if one partially controls the server response in, e.g., an API call response or a returned document and convinces the browser to treat this response as HTML, then it’s straightforward XSS. The attacker would be able to impersonate the user in the context of the given domain: if it is hosting a web application, an exploit would be able to read user data and perform arbitrary actions in the name of the user in the given web application. In other cases, user content might be interpreted as other (non-HTML) types, and then, instead of XSS, content-sniffing vulnerabilities would be permitted for the exfiltration of cross-domain data—just as bad.
Here we focus on PDF-based content-sniffing attacks. Our goal is to construct a payload that turns a harmless content injection into passive file formats (e.g., JSON or CSV) into an XSS-equivalent content sniffing vulnerability. But first, we’ll give an overview of the field and describe previous research on content sniffing.
Content Sniffing of Non-plugin File Types
To exploit a content sniffing vulnerability, the attacker injects the payload into one of the HTTP responses from the vulnerable origin. In practice, that origin must serve partially user controlled content. This is common for online file hosting applications to which an attacker might upload a malicious file, and also in APIs like JSONP that might reflect a payload from the URL. (An attacker then prepares the URL that would reflect the content in the response.)
The first generation of content sniffing exploits tried to convince the browser that a given piece of non-HTML content was in fact HTML, causing a simple XSS.
In other cases, content sniffing can lead to cross-origin information leakage. A good example of this is mentioned in Chris Evans’ research7 and a recent variation on it from Filedescriptor,8 which are based on the fact that browsers can be tricked into interpreting a cross-origin HTML resource as CSS, and then observe the effects of applying that CSS stylesheet to the attacker’s HTML document, in order to derive information about the HTML content.
Current browsers implement more secure content-type detection algorithms or deploy other protection mechanisms, such as the trust zones in IE. Web servers also have become much better at properly specifying the MIME type of resources. Additionally, secure HTTP response headers9 are often used to instruct the user-agent not to perform MIME sniffing on a resource. It’s now a de facto standard to use Content-Type-Disposition: attachment, X-Content-Type-Options: nosniff and a benign Content-Type whenever the response is totally user controlled (e.g., in file hosting applications).
That has improved the situation quite a bit, but there were still some leftovers from the nineties that allowed for MIME sniffing exploitation: namely, the browser plugins.
Plugin Content Sniffing
When an HTML page embeds plugin content, it must explicitly specify the file type (SWF, PDF, etc.), then the browser must instantiate the given plugin type regardless of the MIME type returned by the server for the given resource.10
Some of those plugins ignore the response headers received when fetching the file and render the content inline despite Content-Disposition: attachment and X-Content-Type-Options: nosniff. For plugins that render active content (e.g, Flash, Silverlight, PDF, etc.) this makes it possible to read and exfiltrate the content from the hosting domain over HTTP. If the plugin’s content is controlled by an attacker and runs in the context of a domain it was served from, this is essentially equivalent to XSS, as sensitive content like CSRF tokens can be retrieved in a session-riding fashion.
This has led to another class of content sniffing attacks based on plugins. Rosetta Flash11 12 was a great example of this: making a JSONP API response look like a Flash file, so that the attacker-controlled Flash file can run with the target domain’s privileges.
To demonstrate this, let’s see an example attack site for a vulnerable JSONP API that embeds the given query string parameter in the response body without modification:
type="application/x-shockwave-flash"
data="http://example.com/jsonp_api?callback=CWS[flash file
contents]">
In this case, the API response would look as below and would be interpreted as Flash content if the response doesn’t match some constraints introduced as a mitigation for the Rosetta Flash vulnerability (we won’t discuss those in detail here):
CWS[flash file contents] ({"some":"JSON", "returned":"by",
"the":"API"})
Since Flash usually ignores any trailing junk bytes after the Flash file body, this would be run as a valid SWF file hosted on the example.com domain. The payload SWF file would be able to issue HTTP requests to example.com, read the response (for example, the actual data returned by the very same HTTP API, potentially containing some sensitive user data), and then exfiltrate it to some attacker-controlled server.
Instead of Flash, our research focuses on PDF files and methods to make various types of web content look like valid PDF content. PDF files, when opened in the browser with the Adobe Reader plugin, are able to issue HTTP requests just like Flash. The plugin also ignores the response headers when rendering the PDF; the main challenge is how to prepare a PDF payload that is immune to leading and trailing junk bytes, and minimal in file size and character set size.
We must mention that our research is specific to Adobe Reader: other PDF plugins usually display PDFs as passive content without the ability to send HTTP requests and execute JavaScript in them.
Comma Chameleon
The existing PoC payloads for PDF-based content sniffing13 14 used a FormCalc technique to read and exfiltrate the content. Although they worked, we quickly noticed that their practicability is limited. They were long (e.g. @irsdl uses > 11 kilobytes)15 and used large character sets. Servers often rejected, trimmed, or transformed the PDF by escaping some of the characters, destroying the chain at the PDF parser level. Additionally, those PoCs would not work when some data was prepended or appended to the injected PDF. We wanted a small payload, with a limited character set and arbitrary prefix and suffix.
These are important aspects because most injection contexts where the attack is useful are very limiting. For example, when injecting into a string in a JSON file, junk bytes surround the injection point, as well as the JSON format limitations on the character set (e.g., encoding quotes and newlines).
Additionally, we wanted to come up with a universal payload—one that does not need to be altered for a given endpoint and can be injected in a fire-and-forget manner—thus no hardcoded URLs, etc.
And thus, the quest for the Comma Chameleon has started! Why such a name? Read on!
Minimizing the Payload
To keep the PDF as small as possible, we made it contain only the bootstrap code and injected all the rest of the content in an external HTML page from the attacker’s origin. Size of the final code then doesn’t matter, and we could focus only on minimizing the dropper PDF. This required altering the PDF structure at various layers. Let’s look at them one by one.
The PDF layer It turns out that for the working scriptable FormCalc PDF we only need two objects.
A document catalog, pointing to the pages (/Pages) and the interactive form (/AcroForm) with its XFA (XML Forms Architecture). There needs to be an OpenAction dictionary containing the bootstrapping JavaScript code. The /Pages element may be empty if the document’s first page will not be displayed.
A stream with the XDP document with the event scripts.
Here’s an example:
Additionally, a valid PDF trailer is needed, specifying object offsets in an xref section and a pointer to the /Root element.
Further on, the PDF header can be shortened and modified to avoid detection; e.g., instead of %PDF-1.1
obj<>/OpenAction<
JavaScript/JS (code;)>>>>endobj
The xref section needs to contain entries for each of the objects and is rather large (the overhead is 20 bytes per object); fortunately, non-stream objects can be inlined and moved to the trailer. The final example of a minimized PDF looks like this:
%PDF-Q 1 0 obj<>stream
{xdp here} endstream endobj xref 0 2 0000000000 65535f
0000000007 00000 n trailer<
>>/Pages<<>>/OpenAction<>>>>>
startxref {xref offset here} %%EOF
The JavaScript bootstrap code As JavaScript-based vectors to read HTTP responses from the PDF’s origin without user confirmation were patched by Adobe, FormCalc currently remains the most convenient way to achieve this. Unfortunately it cannot be called directly from the embedding HTML document, and a JavaScript bridge is necessary. In order to script the PDF to enable data exfiltration, we then need these two bridges:
HTML → PDF JavaScript
PDF JavaScript → FormCalc
The first bridge is widely known and documented.16
This works, but it’s huge. Fortunately, it is possible to shorten it a lot. For example this.disclosed = true is not needed, and neither are most of the properties of the messageHandler. Neither is this necessary, as hostContainer is visible in the default scope. In the end we only need a messageHandler.on-Message function to process messages from the HTML document and a messageHandler.onDisclose function.