A Peek Inside the GTalkService Connection

Monday, June 28, 2010

This posts aims to peek inside the Android GTalkService connection and observe its protocol. In particular, we're interested in the INSTALL_ASSET message and whether or not it is protected by any additional cryptographic signatures beyond the intended guarantees provided by the SSL transport.

A Brief Introduction to the GTalkService

If you haven't read the previous post on the GTalkService and INSTALL_ASSET/REMOVE_ASSET, do so first.

In short, the GTalkService is a persistent connection maintained from your Android phone to Google's servers at all time. It allows Google to push down messages to your phone in order to perform particular actions. For example, when you click to install an app through the Android Market, Google pushes down an INSTALL_ASSET to your phone which causes it to fetch and install that application. When Google wants to remote kill an application from your phone, it pushes down a REMOVE_ASSET message to your phone which causes it to remove the particular application.

The GTalkService is a SSL connection which is intended to provide confidentiality and integrity of the messages exchanged between your phone and Google's servers. However, as we've seen in the past, SSL does not always hold up those guarantees.

So the question we're trying to answer in this post is: If an attacker is able to compromise the integrity of the GTalkService SSL connection in any way, will they be able to forge INSTALL_ASSET messages to install arbitrary applications on the target device? Or, is there any additional layer of integrity (eg. INSTALL_ASSET messages being signed by Google) to prevent it?

Experimental Setup

To snoop on the GTalkService connection, we need to man-in-the-middle the SSL connection. There's three steps to doing this:

  1. Obtain an Android emulator image with market capabilities.
  2. Add your own CA certificate to /system/etc/security/cacerts.bks using keytools.
  3. MITM the connection using a tool such as Moxie's sslsniff with your CA cert.

Now, when we fire up the emulator and the GTalkService attempts to connect, it will be successfully MITM'ed since it trusts the CA certificate we created.

The GTalkService Protocol

We can now snoop on the GTalkService connection. Here's a brief dump of several of the message types used when your phone communicates with Google's servers over the GTalkService.

Login Messages

The initial login exchange passes your Jabber ID (JID) to Google's servers along with (I believe) the authentication token associated with your Google account after obtaining it from Google's ClientLogin service.

Client -> Server
00000000 03 |.|
00000001

Server -> Client
00000000 03 |.|
00000001

Client -> Server
00000000 02 c1 02 0a 07 41 32 49 36 44 2d 30 12 09 67 6d |.....A2I6D-0..gm|
00000010 61 69 6c 2e 63 6f 6d 1a 11 6a 6f 6e 6f 61 6e 64 |ail.com..jonoand|
00000020 72 6f 69 64 6d 61 72 6b 65 74 22 13 61 6e 64 72 |roidmarket".andr|
00000030 6f 69 64 77 43 78 77 58 70 68 59 6a 33 4a 4d 2a |oidwCxwXphYj3JM*|
00000040 e0 01 44 51 41 41 41 4a 30 41 41 41 44 39 4f 4c |..DQAAAJ0AAAD9OL|
00000050 6a 43 6a 48 71 34 49 62 36 7a 77 6d 6d 44 32 33 |jCjHq4Ib6zwmmD23|
00000060 39 52 56 78 5f 73 77 5f 56 63 77 43 6e 45 70 4c |9RVx_sw_VcwCnEpL|
00000070 38 70 56 56 6f 79 4f 70 36 6b 49 4a 63 31 38 70 |8pVVoyOp6kIJc18p|
00000080 72 52 66 71 77 34 76 59 34 50 74 78 70 43 5a 67 |rRfqw4vY4PtxpCZg|
00000090 4e 54 30 35 50 77 5a 59 65 72 59 32 43 4e 58 45 |NT05PwZYerY2CNXE|
000000a0 54 49 37 73 62 72 63 4c 70 6a 4b 30 7a 50 4c 45 |TI7sbrcLpjK0zPLE|
000000b0 51 65 6f 38 50 4b 66 67 38 51 4e 41 34 66 34 69 |Qeo8PKfg8QNA4f4i|
000000c0 31 7a 43 48 5a 73 43 62 68 41 32 50 39 59 6c 59 |1zCHZsCbhA2P9YlY|
000000d0 58 6f 55 65 65 68 79 4d 77 70 66 6a 51 39 35 68 |XoUeehyMwpfjQ95h|
000000e0 31 30 46 4c 45 79 79 6b 67 78 4c 30 6a 76 42 4e |10FLEyykgxL0jvBN|
000000f0 68 4a 42 4c 6d 5a 6a 4d 50 46 33 2d 71 33 41 48 |hJBLmZjMPF3-q3AH|
00000100 63 70 74 4d 78 5a 35 59 56 4f 30 6b 32 73 58 56 |cptMxZ5YVO0k2sXV|
00000110 30 2d 44 4b 63 66 66 7a 31 34 51 49 31 7a 33 33 |0-DKcffz14QI1z33|
00000120 57 38 32 17 61 6e 64 72 6f 69 64 2d 66 32 66 31 |W82.android-f2f1|
00000130 35 63 63 64 31 37 66 62 33 30 35 38 d6 e1 d9 c4 |5ccd17fb3058....|
00000140 c5 c1 a2 02 |....|
00000144

Server -> Client
00000000 03 3a 0a 07 41 32 49 36 44 2d 30 12 2f 6a 6f 6e |.:..A2I6D-0./jon|
00000010 6f 61 6e 64 72 6f 69 64 6d 61 72 6b 65 74 40 67 |oandroidmarket@g|
00000020 6d 61 69 6c 2e 63 6f 6d 2f 61 6e 64 72 6f 69 64 |mail.com/android|
00000030 77 43 78 77 58 70 68 59 6a 33 4a 4d |wCxwXphYj3JM|
0000003c

Heartbeat Messages

Heartbeats are initiated by the Android client simply to ping Google's servers and ensure connectivity is active.

Client -> Server
00000000 00 00 |..|
00000002

Server -> Client
00000000 01 00 |..|
00000002

INSTALL_ASSET Messages

The INSTALL_ASSET message is what we're most interested in. During my testing, I installed a random application from the Android Market on my emulator in order to capture an INSTALL_ASSET payload. As you can see below, the message specifies a number of parameters:

Server -> Client
00000000 08 d5 03 08 8a c2 89 fd cb c1 a2 02 1a 0a 67 6f |..............go|
00000010 6f 67 6c 65 2e 63 6f 6d 22 2f 6a 6f 6e 6f 61 6e |ogle.com"/jonoan|
00000020 64 72 6f 69 64 6d 61 72 6b 65 74 40 67 6d 61 69 |droidmarket@gmai|
00000030 6c 2e 63 6f 6d 2f 61 6e 64 72 6f 69 64 77 43 78 |l.com/androidwCx|
00000040 77 58 70 68 59 6a 33 4a 4d 2a 0d 49 4e 53 54 41 |wXphYj3JM*.INSTA|
00000050 4c 4c 5f 41 53 53 45 54 3a 1a 0a 09 74 69 63 6b |LL_ASSET:...tick|
00000060 6c 65 5f 69 64 12 0d 31 32 37 37 36 38 37 32 36 |le_id..127768726|
00000070 36 30 37 34 3a 1e 0a 07 61 73 73 65 74 69 64 12 |6074:...assetid.|
00000080 13 2d 31 35 35 38 36 33 38 33 31 34 37 33 31 32 |.-15586383147312|
00000090 30 35 35 36 3a 1c 0a 0a 61 73 73 65 74 5f 6e 61 |0556:...asset_na|
000000a0 6d 65 12 0e 52 65 70 6c 69 63 61 20 49 73 6c 61 |me..Replica Isla|
000000b0 6e 64 3a 12 0a 0a 61 73 73 65 74 5f 74 79 70 65 |nd:...asset_type|
000000c0 12 04 47 41 4d 45 3a 2a 0a 0d 61 73 73 65 74 5f |..GAME:*..asset_|
000000d0 70 61 63 6b 61 67 65 12 19 63 6f 6d 2e 72 65 70 |package..com.rep|
000000e0 6c 69 63 61 2e 72 65 70 6c 69 63 61 69 73 6c 61 |lica.replicaisla|
000000f0 6e 64 3a 9a 01 0a 0e 61 73 73 65 74 5f 62 6c 6f |nd:....asset_blo|
00000100 62 5f 75 72 6c 12 87 01 68 74 74 70 3a 2f 2f 61 |b_url...http://a|
00000110 6e 64 72 6f 69 64 2e 63 6c 69 65 6e 74 73 2e 67 |ndroid.clients.g|
00000120 6f 6f 67 6c 65 2e 63 6f 6d 2f 6d 61 72 6b 65 74 |oogle.com/market|
00000130 2f 64 6f 77 6e 6c 6f 61 64 2f 44 6f 77 6e 6c 6f |/download/Downlo|
00000140 61 64 3f 61 73 73 65 74 49 64 3d 2d 31 35 35 38 |ad?assetId=-1558|
00000150 36 33 38 33 31 34 37 33 31 32 30 35 35 36 26 75 |63831473120556&u|
00000160 73 65 72 49 64 3d 39 38 36 30 33 32 31 31 38 37 |serId=9860321187|
00000170 37 35 26 64 65 76 69 63 65 49 64 3d 31 30 39 34 |75&deviceId=1094|
00000180 31 31 37 32 30 33 39 30 36 36 33 38 35 39 37 3a |117203906638597:|
00000190 2e 0a 0f 61 73 73 65 74 5f 73 69 67 6e 61 74 75 |...asset_signatu|
000001a0 72 65 12 1b 41 79 6e 32 62 57 44 71 63 6b 51 6b |re..Ayn2bWDqckQk|
000001b0 4b 73 42 59 34 4a 75 72 76 43 46 70 59 4e 30 3a |KsBY4JurvCFpYN0:|
000001c0 15 0a 0a 61 73 73 65 74 5f 73 69 7a 65 12 07 35 |...asset_size..5|
000001d0 31 34 34 34 38 35 40 01 |144485@.|
000001d8

The INSTALL_ASSET Signature

Uh-oh, there's an opaque asset_signature attribute in that INSTALL_ASSET message. Is it possible Google is cryptographically signing each message in order to thwart an attacker trying to forge malicious INSTALL_ASSET messages? Let's take a deeper look at the signature and where it is used in the Android system.

The asset_signature attribute is processed in the getDownloadInfo function of the InstallAssetReceiver class in the Vending.apk package. Later, we see that the signature is actually a base64-encoded SHA-1 which is compared to the hash of the fetched APK file specified in the asset_blob_url attribute:

verifyapk

To verify our assumptions that this is a SHA-1 of the APK and not a digital signature over the INSTALL_ASSET message, let's take a peek at the vending package's sqlite database:

# sqlite3 /data/data/com.android.vending/databases/assets.db
sqlite> select * from assets10;
...|com.replica.replicaisland|false|Ayn2bWDqckQkKsBY4JurvCFpYN0#5144485|...

Let's try to verify the signature present in the assets.db against the SHA-1 hash of the application's APK:

>>> print binascii.hexlify(base64.b64decode('Ayn2bWDqckQkKsBY4JurvCFpYN0='))
0329f66d60ea7244242ac058e09babbc216960dd

jono@dionysus ~ $ openssl sha1 com.replica.replicaisland.apk
SHA1(com.replica.replicaisland.apk)= 0329f66d60ea7244242ac058e09babbc216960dd

Indeed, these signatures are identical, indicating that the asset_signature contained in the INSTALL_ASSET message is simply a hash of the target APK, and _not_ a digital signature authenticating the source of the message.

Conclusion

After peeking in to the GTalkService and observing the plaintext INSTALL_ASSET payloads, it is clear that there are no digital signatures attached to the INSTALL_ASSET messages. Therefore, an attacker who is able to intercept the SSL connection used by the GTalkService will be able to push down arbitrary INSTALL_ASSET messages to the victim's phone. Since the phone will install the APK specified in the INSTALL_ASSET message automatically without user intervention, the attacker could remotely install a malicious application requesting arbitrary permissions and containing a malicious payload.

The larger lesson here is that SSL is not an end-all solution for delivering software payloads. A loss in network integrity should not directly lead to a loss of host integrity. Just as used in many desktop application auto-updating components, the update manifest and/or payload should be digitally signed by the distributor in addition to using SSL as a transport. Google should be cryptographically signing the INSTALL_ASSET messages used in the GTalkService to protect against this threat model.

Copyright © 2021 - Jon Oberheide