

Ripping OAuth tokens out of Twitter apps - sferik
http://timetobleed.com/ripping-oauth-tokens-or-other-secrets-out-of-tweetdeck-twitter-app-and-other-apps/

======
metoosorta
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.

~~~
maqr
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...](http://stackoverflow.com/questions/4419915/how-to-keep-the-oauth-
consumer-secret-safe-and-how-to-react-when-its-compromis)

~~~
rmccue
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).

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

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

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

~~~
dpeck
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? ;)

~~~
armooo
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...](https://github.com/mitsuhiko/logbook/blob/master/twitter-secrets.txt).
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>

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

------
wheels
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\}$'

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

~~~
mattgreenrocks
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...

~~~
icefox
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).

~~~
mathrawka
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.

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

~~~
armooo
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.

~~~
eridius
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?

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

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

~~~
JoshTriplett
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.

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

~~~
conradev
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.

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

~~~
DasIch
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.

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

~~~
tvdw
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.

