Hacker News new | past | comments | ask | show | jobs | submit login
Ripping OAuth tokens out of Twitter apps (timetobleed.com)
78 points by sferik on Aug 20, 2012 | hide | past | favorite | 30 comments



Oauth tokens, consumer keys, nonces, and timestamps are not something you don't already have access to as a user. The token is your authentication proof / API access key, the consumer key is a bit misleadingly named but just identifies the 3rd party, it is public knowledge. The nonce and timestamps are artifacts of authentication and less sensitive than the token.

The real meat is the 3rd party's consumer secret (the secret key that goes with their consumer key.) If you're finding those then someone needs to make a South Park ski instructor meme.


This should be the top comment. This blog post just shows URLs, which are the result of being signed with the 'consumer secret'. You can see the same thing with wireshark, charles, or any other sniffer or debugging proxy.

The more important thing is the consumer secret itself, which is discussed here: http://stackoverflow.com/questions/4419915/how-to-keep-the-o...


You shouldn't be able to see it with Wireshark, given that it's HTTPS, but you should be able to MITM it (assuming you can make yourself a CA, that's trivial).


agreed, this post doesn't show any information you don't have permission to know being the authorised user of the application...


I'm surprised he went to the trouble of using `DYLD_INSERT_LIBRARIES` - DTrace makes this sort of thing trivial.... something like:

    #!/usr/sbin/dtrace
    pid$1:$2:free:entry
    {
        printf("%s: %x\n", probefunc, arg0);
    }
would do the trick, I think.


Nope, that'll just get you the addresses being freed. This, on the other hand, seems to do what I expected:

    dtrace -n 'pid$target::free:entry { printf("%s: %s", probefunc, copyinstr(arg0)); }' -p <pid>


I pulled the keys out of the android client this weekend. Not as good of a write up, but I used apktool to convert the APK back to xml resource files and smali dalvik assembler. Greped for Hmac and added some logging. Did the same thing for oauth_consumer_key. Rebuilt it as an APK with apktool. Signed it with jarsigner. Watched the logs and logged in. I think the best part is this key can use xauth so other clients can have the nicer UX of the official client.

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v0

    invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v0

    // Added logging
    const-string v1, "PrivateKey"
    invoke-static {v1, v0}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

    const-string v1, "UTF8"

    invoke-virtual {v0, v1}, Ljava/lang/String;->getBytes(Ljava/lang/String;)[B

    move-result-object v0

    new-instance v1, Ljavax/crypto/spec/SecretKeySpec;

    const-string v2, "HmacSHA1"

    invoke-direct {v1, v0, v2}, Ljavax/crypto/spec/SecretKeySpec;-><init>([BLjava/lang/String;)V


  D/PrivateKey(18590): XXXXXX
  D/Auth Header(18590): OAuth realm="http://api.twitter.com/", oauth_version="1.0", oauth_nonce="2404904914329321765488437936138011", oauth_timestamp="1345512606", oauth_signature="gEvQOcGWO7aPCYTemRy%2BkYH3oFM%3D", oauth_consumer_key="3nVuSoBZnx6U4vzUxf5w", oauth_signature_method="HMAC-SHA1"


are you intentionally neglecting the additional steps to make this work, or did you not test your assumptions against the requests that the app actually sends? ;)


I tested this on the with the twitter api. This key was already leaked in 2010 at https://github.com/mitsuhiko/logbook/blob/master/twitter-sec.... So I will just post it here. https://twitter.com/armooo/status/237729837157060609 take a look at the name of the client.

    >>> key = 'Bcs59EFbbsdF6Sl9Ng71smgStWEGwXXKSjYvPVt7qys'
    >>> oauth_consumer_key = '3nVuSoBZnx6U4vzUxf5w'
    >>> import tweepy
    >>> auth = tweepy.OAuthHandler(oauth_consumer_key, key)
    >>> auth.get_xauth_access_token('armooo', <password>)
    <tweepy.oauth.OAuthToken object at 0x110985810>
    >>> api = tweepy.API(auth)
    >>> api.update_status('This is an update %s:%s' % (oauth_consumer_key, key))
    <tweepy.models.Status object at 0x110985c90>


ah, yes, you're right, was thinking of another api endpoint.



Reading this http://nelenkov.blogspot.com/2012/07/using-app-encryption-in... it looks like if you have root on your phone you can still access the APKs. Sounds like it is using the same encryption system as the apps on SD. But have have not had a chance to look at it.


You can often find things even more simply if they're just embedded in the binary and you know what format you're looking for.

This, for example, goes fishing for MD5 hashes:

  /Applications> find *.app/Contents/MacOS -maxdepth 1 -perm 755 -type f -print0 | \
    xargs -0 strings | grep '^[0-9a-f]\{32\}$'


This operation is awesome and it does a great job of showing how twitter is going to have a hard time having blessed clients. If twitter wants to rate limit API calls for apps in an effort to reduce abuse then abusers are going to impersonate the official twitter client.


This is AOL Instant Messenger all over again: a closed source client with a secret (proprietary protocol) that is blessed, and vague threats of legal action against unauthorized clients. Except in this case, Twitter's probably more serious about the whole thing.

Which is ridiculous, this being Twitter and all...


At least for me the vague threads of legal action during the aim time where not very vague, but trademark infringement for naming my application Kaim. Unlike the Gaim guys I simply switched my application name Kinkatta (Kinkatta is not Kaim anymore thanks to AOL).


I never dealt with any legal issues, but one day I noticed that licq.net was registered by AOL. I had the licq.org and licq.com (sold the .com years ago though), but always thought it was funny how they did a passive-aggressive move like that.


The printed output strings look like HTTPS requests. Wouldn't it have just been simpler to use Charles to run an SSL MitM attack? I highly doubt these twitter clients check what certificate they're using beyond whether it's trusted.


OAuth was designed to not require SSL. So only the oauth_consumer_key, which works as an client id, is sent over the wire. HMAC-SHA1 is then used with a shared secret key to sign all the requests. This key is what the maloc shim is finding, along with the oauth_consumer_key, but it was simpler at this point then looking at the http connection.


Ok, then why did the OP only show HTTP requests as the captured output? If he's capturing something else, shouldn't he show that?


Good point, I am not sure why the OP did not show the key.


OAuth on the client side is not about restricting access to people hacking up their own clients, its about restricting access to the network for things that don't fit the api owners wishes, in this case involving revenue. Just like content owners dont tend to worry too much when a hard to use and essentially impossible to scale bypass tool is released, but it behind a nice gui and toss it in an appstore and you've brought all sorts of hell upon yourself.

Thinking of oauth on the client as any kind of security measure on the client side is absurd anyways, at best it keeps honest people honest and maybe cuts down on signal/noise for the lowest of the low budget spammers.


You can use OAuth without requiring blessed per-application API keys; it primarily exists so that services can let an application access a user's account without actually having the username and password of that account, and without necessarily having the full permissions of that user.


Cross-pasted from the previous submission of this article:

By its nature, the only way to combat this class of attack is security by obscurity - hence, it should be assumed that OAuth client tokens and client secrets do not provide true protection against unauthorized client applications.

Of course the tokens can be obfuscated, but at some point the tokens must be used in plain-text to sign the OAuth request, and on a device like an iPhone where complete control of execution flow and full address space access is possible (via kernel exploits / jailbreak and a debugger), it's literally impossible to prevent this attack.

Issuing unique per-device device tokens would be an interesting approach, but then a trusted side-band would be necessary to issue the tokens to the device, and a lot of the point of OAuth is moot.

OAuth is still quite useful for user authentication (as to steal per-user tokens requires access to the user's device anyway). Plus, in the other common OAuth use-case (backend to backend), if the consumer token is stolen, your client probably has a larger security issue on their hands that would have allowed the attacker to pose as them anyway.

This is interesting in that it may allow unscrupulous app developers to evade Twitter's new API limits by posing as the Twitter for iOS or Android applications, but I suspect these uses will not be widespread as Twitter can quite probably send a Cease and Desist to Apple or Google and have the offending app removed from the market.


How about an Twitter client that allows you to specify your own consumer key and secret? It's really easy to go and create an application on Twitter's developer dashboard. Hell, the client could even walk you through the process.

The developer dashboard also makes it really easy to generate an OAuth token for your account, for the application you have created. So just inputting the OAuth token is also an option.

Even if these options are not opened up by an existing Twitter client of choice, one could just use code injection to force this behavior customization.

Twitter can't really filter new applications based on the number of users, either, because I'm sure that there are a number of blogs that use a custom Twitter application to tweet new posts, with the sole user being the website.

Twitter really doesn't have a good way of enforcing its new Display Requirements, or any such policy.


I was thinking about this quite a few times: doesn't it mean that all this OAuth things are broken from the start, since once you give the binary to the people, the could just get the secret out and reuse it another way?

The TOS of all these APIs all say that "you have to keep your Secret secret, or else!", but fundamentally there's no way to really do that, is there?


It just compromises the application identity, it still does not give you access to anything useful and it will probably be noticed if you use it on any significant scale.

However, OAuth is indeed a bad way to authenticate for applications that run on devices in the possession of third parties.


Fun Fact: You can get the API secret key out of twitter's official client. Which will allow you to use their xauth system (no browser oauth required - only enter username/password).

Also great for spambots: Twitter can't ban the app because then they had to ban their official Twitter clients.

/edit: have fun

    'key': 'Fpl5UUVwvaczUzzpVJ8Rlw'
    'secret': 'z73HF21zCz5CaxzDM6M0OPeaCBYGfHUG3FYBgcMB2Y'

    'key':  '3rJOl1ODzm9yZy63FACdg'
    'secret': '5jPoQ5kQvMJFDYRNE8bQ4rHuds4xJqhvgNJM4awaE8'
One is for tweetie 1.0 and the other is for the official twitter client.


You should try to extract the ones from iOS 5. They're hardcoded in Twitter.framework (simulator versions as well) and can be extracted with the simple "strings" tool. I'm not going to post them here though.


I guess you should take great care to use the exact same HTTP headers (user-agent, accept, encoding etc) and pattern of API access as the corresponding apps, or they'll surely be able to detect anomalies and ban your account :)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: