PromyLOPh / pandora-apidoc

pandora.com API documentation
https://6xq.net/pandora-apidoc/
Do What The F*ck You Want To Public License
48 stars 19 forks source link

Reverse engineering the auth token format #42

Open hacker1024 opened 3 years ago

hacker1024 commented 3 years ago

It has come to my attention that the REST API authentication token is actually base64 encoded data. When a token expires, Pandora sends the following message back, implying that the token stores some sort of state.

ListenerState in auth token does not match state in radio db

It's possible that this token may include useful information like when the token will expire. I intend to look into this further, and I'll document any findings here before collating anything meaningful into a page in a PR.

An example (expired) authentication token:

BIQ3pFmHssCsDO8nEYuyojSfYKUus0LpEOsueZ3Zk0vQtUNfywnxI4cA==
04 84 37 a4 59 87 b2 c0 ac 0c ef 27 11 8b b2 a2
34 9f 60 a5 2e b3 42 e9 10 eb 2e 79 9d d9 93 4b
d0 b5 43 5f cb 09 f1 23 87 00
H0r53 commented 3 years ago

Could it simply be base-64 encoded binary data that they associate with account data in their database? I would think the token expiration is not included within the token itself, but rather they likely use the token as a UUID to lookup a record on their end.

hacker1024 commented 3 years ago

Could it simply be base-64 encoded binary data that they associate with account data in their database?

Possibly, but the expired error message references a ListenerState in the authentication token. It could be encrypted, though, as the data doesn't seem to be used in the Web or Android apps and is just processed server-side.

Here are six more tokens, retrieved in quick succession. All tokens so far seem to start with an arbitrary byte followed by 0b1000, and end with 0b0000. The last nibble can be changed to any value without invalidating the token. It's also worth noting that the Pandora backend is definitely decoding the data for each request - re-encoded tokens with the URL-safe base64 alphabet also work.

VIG280FHDA0eGu2afiWsF1K1b/N36CkLH6lf9WCTNo/9zdDHokkLK7mQ== VIojC6zfuZse46P1c765ADK3K0HGRSkGTliS1BR7haa7q2zyifhCC9mQ== VIirUwvxHipElkKksjrxnwVKBXgmvu2hA2wWegdHLsDzw8AI3vvWw7pA== VITXTCn1yy656XXzprlDSUMK67sJkvVQxv9DMED8if33TT+7b0dAtR/A== VIX7sGpTWj+WTKMmq38tG5FdAxqoGRd+FiN7gC2GiML8zJnNGHxDPRuA== VIirUwvxHipElkKksjrxnwVMbTTMLo7krVxz7Ljdj1Ak41MyEkZbOAsg==

54 81 b6 f3 41 47 0c 0d 1e 1a ed 9a 7e 25 ac 17 52 b5 6f f3 77 e8 29 0b 1f a9 5f f5 60 93 36 8f fd cd d0 c7 a2 49 0b 2b b9 90
54 8a 23 0b ac df b9 9b 1e e3 a3 f5 73 be b9 00 32 b7 2b 41 c6 45 29 06 4e 58 92 d4 14 7b 85 a6 bb ab 6c f2 89 f8 42 0b d9 90
54 88 ab 53 0b f1 1e 2a 44 96 42 a4 b2 3a f1 9f 05 4a 05 78 26 be ed a1 03 6c 16 7a 07 47 2e c0 f3 c3 c0 08 de fb d6 c3 ba 40
54 84 d7 4c 29 f5 cb 2e b9 e9 75 f3 a6 b9 43 49 43 0a eb bb 09 92 f5 50 c6 ff 43 30 40 fc 89 fd f7 4d 3f bb 6f 47 40 b5 1f c0
54 85 fb b0 6a 53 5a 3f 96 4c a3 26 ab 7f 2d 1b 91 5d 03 1a a8 19 17 7e 16 23 7b 80 2d 86 88 c2 fc cc 99 cd 18 7c 43 3d 1b 80
54 88 ab 53 0b f1 1e 2a 44 96 42 a4 b2 3a f1 9f 05 4c 6d 34 cc 2e 8e e4 ad 5c 73 ec b8 dd 8f 50 24 e3 53 32 12 46 5b 38 0b 20
H0r53 commented 3 years ago

Interesting. Have you considered fuzzing individual bytes until the ListenerState error displays? Also, I would imagine either some sort of session identifier or account identifier is included in the token, unless they are in fact using the token as a UUID that they look up on the backend. Perhaps hybrid, as I'm sure you were using the same user account in your collection of these auth tokens.

hacker1024 commented 3 years ago

Interesting. Have you considered fuzzing individual bytes until the ListenerState error displays?

I haven't tried all that thoroughly, but I did try changing random bytes in different areas. Only the very last nibble seems to be able to be changed without invalidating the token.