Abusing Twitter Api
Abusing Twitter Api
Home
Home Made Maps ABUSING TWITTER API
Hello Mach-O This article is an up-to-date version of a research I first presented at App Sec Forum Western Switzerland
A Tiny NTP Client 2012 and then at Hack in the Box 2013 (Amsterdam).
Abusing Twitter API This article is not intended to be formal, but more to be used as a technical reference for details that were
not explained in the slides.
Parsing JSON
Data Visualization [2013-04-11] PCWorld
1 of 16 5/1/20, 10:49 PM
seriot.ch - Abusing Twitter API
Anyone could download the tweets, or post a tweet providing a username and a password.
Early Twitter users somehow invented or at least made @reply and #hashtags popular.
Gradually, Twitter decided it was getting a grown-up company and should start monetizing its user base.
Instead of selling premium subscriptions to users, Twitter chose to sell ads to advertisers.
To implement these measures, Twitter has recently added strong constraints on the users of their API, eg:
third-party clients must display the ads and strictly apply the Twitter layout guidelines
all API requests must be authenticated by both the user and the application he uses
Twitter can block access to specific applications if these guidelines are not applied.
Moreover, the rules are quite impossible to comply with and change all the time.
"Developers ask us if they should build client apps that mimic or reproduce the mainstream
Twitter consumer client experience. The answer is no." "We need to move to a less
fragmented world, where every user can experience Twitter in a consistent way."
Of course, these moves are poorly accepted by long-time Twitter users and applications developers:
"Twitter obviously wants to make money by advertising in the stream. This will be impossible if
all of the mechanisms aren't implemented to spec within a client. They need full control of how
the information is presented, and do not have the bandwidth to micromanage ads with third
parties to prevent fraud, poor presentation, etc,"
Several companies simply stopped developing for Twitter clients while some of them are trying to play the
game.
Some power users are already leaving Twitter for other micro-blogging platforms such as app.net. In
september this year, Twitter removing the RSS feeds only accelerated this move.
The purpose of this article is to explain how Twitter uses OAuth to identify the client application, show how to
impersonate other client applications and discuss this situation from an application security standpoint.
So, we first need to study in detail the way Twitter requests are built up.
Historically, Twitter API did use HTTP Basic Authentication. In December 2009, Twitter introduced OAuth
authentication and deprecated Basic Authentication. OAuth has been mandatory since September 2010.
OAuth is an standard authentication protocol over HTTP which allows users to approve or refuse
applications to act on their behalf, without sharing their password.
OAuth 1.0 is described in RFC 5849. Although OAuth 2.0 is ready, Twitter uses version 1.0a.
So how does it all work? Well, instead of sending a username and password, OAuth uses "access tokens",
two values which will be used to build every API request.
Let's take a sample query. This query posts the message "hello #asfws":
POST https://api.twitter.com/1.1/statuses/update.json
2 of 16 5/1/20, 10:49 PM
seriot.ch - Abusing Twitter API
HEADERS
Authorization = OAuth oauth_consumer_key="7YBPrscvh0RIThrWYVeGg",
oauth_nonce="B916DA1D-5163-404E-BBFD-6B23610A",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1350986996",
oauth_version="1.0",
oauth_token="15111995-MYAoxeiGNxwYbckY76v6JBgH8qVdEdKsFf5MXkfFX",
oauth_signature="569AfY3o2hh%2B7aNC%2FuI7rx%2FZ73c%3D"
POST DATA
status = hello%20%23asfws
signing_key is consumer_secret&access_secret
Every time, a "key" token will be sent over the network, and a "secret" token won't be sent, but will be used
to sign the request instead.
maintain a session
authenticate the user
authenticate the client application
ensure the request integrity
It is to be noted that OAuth does not ensure request confidentiality, since it is not required to use SSL.
Before setting up a user account, a client application only has consumer tokens, which are part of the
application.
When the users sets up a user account in its Twitter client, the application will start a process which will end
up with the reception of access tokens.
These access tokens will enable the user to use Twitter with his client application, as seen with the sample
query.
1) The application asks Twitter for request tokens and gets, as a response, a URL that contains the request
tokens.
<- https://api.twitter.com/oauth/authorize
? oauth_token = 5mLVRwABK47EwuX3vCsEqW9QEGdgIP4qL75UPYpdcc
& oauth_token_secret = hmeCdVB48lpC35q8fTUJ3SIegVB9uSPdWxL6WbLvgY
& oauth_callback_confirmed = true
2) The application then asks the user to authorize the request tokens on Twitter website, and receives a
PIN.
<- 5728738
3 of 16 5/1/20, 10:49 PM
seriot.ch - Abusing Twitter API
3) The application sends Twitter the PIN and receives the access tokens.
The first digits of oauth_token stand for the Twitter user ID.
It also has generated and returned access tokens valid for the application and the user.
All subsequent API requests are signed with OAuth as seen before, the signing key being
consumer_secret&access_token_secret, eg. when retrieving the timeline:
Access tokens can be revoked by the user at anytime by revoking the client application. Note that changing
the password of a Twitter account does not revoke access tokens.
This PIN-based authentication process is quite complicated. It needs opening a browser, takes time and can
be confusing for the user.
Fortunately, not all Twitter clients have to go through it. For instance, the official iOS Twitter client doesn't
need a PIN. It can retrieve OAuth tokens directly from a username and password. This happens through a
xAuth request.
Compared to the PIN-based authentication, xAuth skips the first two steps and directly goes to the "access
token" step. The exchange of request tokenS for access tokens is modified to provide the username and
password instead of the PIN.
Not all consumer tokens are xAuth enabled. Developers can have their application be aAuth enabled by
writing to [email protected] and explaining why their application needs this xAuth capability.
In March 2013, Twitter introduced Application Only authentication which can use the API without user
context. Hence, there is no need to authenticate the user, but only the application. API endpoints such as
POST statuses/update will return an error, whereas GET /1.1/statuses/user_timeline.json
will work as expected.
These requests follow the Client Credentials Grant flow of the OAuth 2 specification. The requests don't
have to be signed with OAuth, they simply have to send a bearer token in the HTTP Authorization
header:
In order to receive a bearer token, the application sends a POST request using
consumer_key:consumer_secret encoded in base64 as a Basic authorization value:
grant_type=client_credentials
4 of 16 5/1/20, 10:49 PM
seriot.ch - Abusing Twitter API
<- {"token_type":"bearer","access_token":"XXXXXXXX"}
When requested multiple times with the same consumer key and secret, the same bearer token in returned.
access_token=XXXXXXXX
<- {"access_token":"XXXXXXXX"}
Reverse Auth is yet another variant of OAuth. Given a user U logged in with an application APP1, Reverse
Auth allows APP1 to enable APP2 to retrieve access tokens valid for U and APP2.
Phase 1: login with APP2, obtain a special request token in the form of an OAuth header
<- OAUTH_HEADER
A typical use case is an iOS application requesting access to the default iOS Twitter account in order to
authenticate the user on a remote service and access his Twitter account.
Note that phase 1 does not need data from APP1. It means that this phase can be performed on an iOS
device but also anywhere else. Performing phase 1 from a remote server is a good practice since it avoids
shipping the APP2 consumer secret along with an iOS application.
Also, when APP1 is Twitter for iOS, APP2 can access the user's direct messages, contrary to what can be
read here and there. iOS users who grant an application access to their Twitter account are not always
aware of that.
We just saw that, for each kind of authentication, client applications need consumer tokens, and that
consumer tokens represent the client identity since they authenticate the client with Twitter.
If we can find consumer tokens from real clients, then we know how to send Twitter API requests looking
exactly the same as the one from the real clients and perform any of these authentication while
impersonating the original client.
So how do we find these keys? Sniffing the network would only reveal consumer_key but not
consumer_secret, which is part of the signing key and is not sent over the wire.
Let's see how to extract consumer keys from popular Twitter clients, including OS X and iOS.
3.1 /usr/bin/strings
Consumer tokens can be simply embedded in the binary code, waiting to be dumped, such as with Twitter
official client for OS X, Twitterrific or Tweetbot.
5 of 16 5/1/20, 10:49 PM
seriot.ch - Abusing Twitter API
Twitter.app
$ strings /Applications/Twitter.app/Contents/MacOS/Twitter
3rJOl1ODzm9yZy63FACdg # consumer_key
5jPo************************************** # consumer_secret
Twitterrific
$ strings /Applications/Twitterrific.app/Contents/MacOS/Twitterrific
ZSdaBDXCKZ9kLPe4Ymr0Q
Tq66***************************************
Tweetbot.app
$ strings /Applications/Tweetbot.app/Contents/MacOS/Tweetbot
HS47qOdHzVFQYXTJMA
qvkE***************************************
We can quickly test the tokens for validity with the Tweepy Python module:
#!/usr/bin/env python
CONSUMER_KEY = '3rJOl1ODzm9yZy63FACdg'
CONSUMER_SECRET = '5jPo**************************************'
3.2 GDB
Several other applications try to protect their consumer tokens with some level of obsfuscation. The
strings command does not reveal the tokens. However, examining method names with GDB (info func
OAuth, info func consumer, ...) can reveal the names of the Objective-C which return the consumer
tokens. We can then set breakpoints, interact with the application so that it will need the consumer tokens,
and when breakpoints are hit, we just let the functions finish and return. At this point, all we have to do is to
read the return value of the function. This value is stored in the $eax register for Intel 32-bits and the $rax
register for Intel 64-bits.
This technique works fine to retrieve consumer tokens from Socialite but also from OS X Twitter integration
and iOS Twitter integration. In this last case, we attache GDB to a process running in the iPhone simulator.
$ gdb /Applications/Socialite.app/Contents/MacOS/Socialite
OS X (64 bits)
6 of 16 5/1/20, 10:49 PM
seriot.ch - Abusing Twitter API
Some other applications hide their symbols. It gets difficult to know the address of the functions that return
the consumer tokens. However, we know that the program will need to use the tokens at some point
because they are needed to sign OAuth requests.
We can then use another technique which consists in dumping the memory of the process and looking for
the tokens into the dump.
We will use the gcore tool from Amit Singh's book "Mac OS X Internals": http://www.osxbook.com
/book/bonus/chapter8/core/.
Let us use this technique to retrieve the consumer tokens from YoruFukurou.
YoruFukurou
The file will be quite huge. Before using strings on the file, we must remove or alter the Mach-O magic
header 0xCFFAEDFE or strings won't run.
We can start by looking for consumer_key. The consumer key appears in all HTTP headers of the OAuth
requests. Note that this value is not really hidden and could have been retrieved by sniffing the network.
We know from Twitter documentation on signature creation that consumer_secret is part of the signing
key, separated from access_token_secret with an ampersand, ie HMAC_signing_key ==
consumer_secret&token_secret. Additionaly, before the application receives access tokens, OAuth
requests are signed with consumer_secret only. Now it's easy to discover the consumer_secret by
grepping this pattern.
7 of 16 5/1/20, 10:49 PM
seriot.ch - Abusing Twitter API
69zI**************************************
Yet another technique consists in logging the freed pointers with a DTrace probe:
The output is pretty verbose but can be reduced with the same sort -u technique as above, and grepped
accordingly.
A more Objective-C variant of logging every freed pointer would be logging only the deallocated NSString
instances. This technique consists in writing a NSString category with a my_dealloc method logging the
string just before calling [super dealloc]. This method must then be swizzled with the regular dealloc
method.
+ (void)load {
Swizzle([NSString class], @selector(dealloc), @selector(my_dealloc));
}
- (void)my_dealloc {
NSLog(@"%@", self);
[self my_dealloc];
}
@end
The code can then be compiled in a framework and dynamically loaded with GDB.
We've seen how to extract tokens "the hard way", but anyone can find dozens of valid consumer tokens with
Google, ie..:
https://gist.github.com/re4k/3878505
http://www.binrand.com/post/2399484-twitter-ipad-consumer-key.html
http://rndc.or.id/wiki/index.php/(Ab)Using_Twitter_Client
https://github.com/mitsuhiko/logbook/blob/master/twitter-secrets.txt
...
The interesting thing is that all API endpoints are not documented. Several of them are used by official
Twitter clients and not available to third-party clients.
[2014-07-02] Check out this visual documentation of Twitter API I just created: twitter_api.pdf
Most if not all endpoints can be found by dumping strings from the official Twitter client.
GET activity/about_me.json
GET activity/by_friends.json
GET conversation/show.json
GET discover/highlight.json
GET discover/universal.json
GET statuses/:id/activity/summary.json
GET statuses/media_timeline.json
GET statuses/mentions_timeline.json
GET timeline/home.json
GET trends/available.json
GET users/recommendations.json
8 of 16 5/1/20, 10:49 PM
seriot.ch - Abusing Twitter API
If you are familiar with Twitter API, you should be able to guess most parameters easily, but you may also
want to check the actual parameters sent to these endpoints. To do that, you can open the Twitter binary
with Hopper.app, browse methods names and notice the address of somewhere you'd like to break, eg.
0x00028582 meth_ABHTTPRequest_setParameters_:. Your gdb session will look similar to this for
Twitter.app version 2.3.1:
A much more efficient technique to discover the actual endpoints and their parameters is sniffing the
network. Unfortunately, setting up an HTTPS proxy is not sufficient because official Twitter clients use SSL
certificate pinning. It means that the applications will refuse to establish a connection if the certificate
presented by the server does not match the one hardcoded in the application. There are several techniques
to defeat certificate pinning. We will use Hopper to decompile Twitter.app and patch the binary to bypass
certificate pinning on a jailbroken device.
Let's take Twitter for iPad version 5.11.1 and open it in Hopper. By browsing the disassembled code, we
quickly find the check that won't let the application connect to api.twitter.com. In -[ABHTTPRequest
connection:willSendRequestForAuthenticationChallenge:] are some instructions meaning:
if([self _isPinnedCertificateChain:chain]) {
// goto the happy path ie. 0x258c0c
} else {
// create an error and return
}
At 0x00260cf0 is the very test that will decide what to do according to the result of the
_isPinnedCertificateChain: message send. The result, originally stored in r0, was moved into r4 at
0x00258ae0. Now tst.w evaluates r4 & 0xFF and sets the Z flag if the result is zero. Then, the bne
instruction tests the Z flag and, if clear, jump to 0x260e14. In summary, we can read these two lines as "if
r4 is true then branch else go on" (to error creation).
In order to take the happy path in any case, we will replace the test tst.w r4, 0xff with the
unconditional branch b 0x260e14. In order to find the opcodes for this unconditional branch, we can use
the Hopper menu "Assemble Instruction" which gives 90E0.
9 of 16 5/1/20, 10:49 PM
seriot.ch - Abusing Twitter API
Note that, if you don't have Hopper or if you want to understand where 90E0 comes from, you can calculate
this value by yourself with the ARM THUMB Instruction Set. The opcode format for unconditional branch is
1110 0--- ---- ---- where dashes are a 11-bits offset shifted to the right. We want to jump from
0x00260cf4 to 0x00260e14 ie an offset of 0x120 or 0000 0001 0010 0000. Shift this value to the right
and add the unconditional branch format, you'll end up with 1110 0000 1001 0000 == 0xE090 or
0x90E0 in little-endian representation.
So, changing 2 bytes on nearly 12 millions was enough to bypass this annoying security feature. Now the
modified Twitter application will establish connections with any SSL/TLS certificate trusted by a trusted CA
and we can happily observe the HTTPS traffic in mitmproxy.
Here is for example how Twitter.app for iPad does fetch the timeline. The
statuses/home_timeline.json endpoint is documented but the exact parameters are not:
GET https://api.twitter.com/1.1/statuses/home_timeline.json?cards_platform=iPad-3&contributor
The response may contain promoted content because of the pc=true parameter. Promoted tweets have an
additional attribute named "promoted_content" which looks like:
"promoted_content" = {
advertiser = {
description = "Follow us here for all the news on Chevrolet in Europe";
name = "Chevrolet Europe";
// ...
};
"disclosure_type" = promoted;
"impression_id" = 1ffa1774327be2ec;
// ...
}
And now it gets easy to edit the iOS binary, change the pc string into, say, xx, resign it with your own
certificate, deploy it OTA or copy it through XCode and your Twitter.app won't display ads anymore :-) Step
by step recipe:
1) on jailbroken device, decrypt the Twitter binary (or find it somewhere on the web)
# Clutch Twitter
$ scp [email protected]:/var/root/Documents/Cracked/Twitter-v5.11.1.ipa .
$ unzip Twitter-v5.11.1.ipa
$ cd Payload/Twitter.app
3) with Hopper, read Twitter and locate the pc string used in requests, change it into xx
$ export CODESIGN_ALLOCATE=/usr/bin/codesign_allocate
$ codesign -fs "iPhone Developer: Nicolas Seriot" Twitter
6) in Xcode Organizer, drag and drop your modified Twitter.app on your device
Here is how accounts are created from iOS Settings on iOS 5 and iOS 7:
POST https://api.twitter.com/1/account/generate.json
10 of 16 5/1/20, 10:49 PM
seriot.ch - Abusing Twitter API
Parameters:
adc: pad
discoverable_by_email: 0
email: EMAIL
geo_enabled: 0
lang: en
name: NAME
password: PASSWORD
screen_name: SCREEN_NAME
send_error_codes: true
time_zone: CEST
This request will fail using any other consumer key but IHUYavQ7mmPBhNiBBlF9Q.
You can find the related consumer secret as well as access tokens by opening an Twitter account from iOS
7 Simulator with gdb attached to /Applications/Preferences.app/Preferences.
This is very similar to what we did on 3.2. First set breakpoints on consumerKey and consumerSecret
getters:
Then, open an account from the Settings. When breakpoints are hit, go the the end of the getter function
and read the return value:
Hence, creating Twitter accounts can be scripted. No need to fill captchas anymore.
A fun fact with these consumer tokens is the identity shown in the authorize tokens phase: "iOS5 SignUp,
mehack.com, Test sign-up application".
So basically, when creating an account, iOS 5 uses "iOS 5 Signup" consumer tokens and @raffi user
account. And @raffi secret token is hardcoded in iOS 5. Great! (see next section for details)
On iOS 7.1 the account used to sign signup requests is 179654598 ie @twobiledev which seems a bit more
reasonable.
Access tokens and consumer tokens are hardcoded, sometimes lightly obfuscated. Here are their locations.
Also, meet Twitter super secret tokens obfuscation: substracting 1 to odd-indexed characters.
iOS 5.1
/System/Library/Frameworks/Twitter.framework/Twitter
iOS 6 and iOS 7
/System/Library/Accounts/Authentication/TwitterAuthenticationPlugin.bundle/TwitterAuthenticat
11 of 16 5/1/20, 10:49 PM
seriot.ch - Abusing Twitter API
OS X 10.9
/System/Library/Accounts/Authentication/TwitterAuthenticationPlugin.bundle/Contents/MacOS/Twi
iOS 7
/System/Library/PreferenceBundles/TwitterSettings.bundle/TwitterSettings
These tokens are all you need to craft an OAuth request to /account/generate.json.
Since iOS 5 and OS X 10.8, users can setup a Twitter account in the System Preferences. This account can
then be accessed by any application after asking for user's permission through Objective-C APIs, namely
Accounts.framework and Social.framework.
All the requests are then signed with iOS or OS X consumer secret. Can Twitter then identify (and revoke)
the application making a certain request. WWDC 2011 session 124 (from 36:26) says:
"As part of this signing process, we actually embed enough information about your process
that Twitter can identify your application correctly and attribute tweets that come from you on
the Twitter web site so you won't lose that identification.".
12 of 16 5/1/20, 10:49 PM
seriot.ch - Abusing Twitter API
Indeed, the application ID is sent along with every request in the application_id parameters, along with
an adc parameter, probably identifying the device. For example:
adc=pad
application_id=ch.seriot.MyApp
This is only true with TWRequest instances (iOS 5). Note that this value cannot be overridden. Adding your
own application_id parameter will result in two parameters like application_id=sdf&
application_id=ch.seriot.MyApp.
Since iOS 6, you can use SLRequest instances and, from what I could observe, the application_id
parameter is not sent anymore, and so Twitter cannot tell which application is using iOS
Social.framework.
As an alternative to OS X Twitter integration, applications can use their own Twitter and OAuth library. There
are several of them, one of the best ones being OAuthConsumer.
I still find it a bit outdated (no block based API) and cumbersome to use for my taste. To be sure to
understand the in-and-outs of Twitter OAuth authentication, I've decided to write my own library and created
STTwitter. In fact, STTwitter is a Twitter-only OAuth 1.0a library, but also provides an interface for OS X
Twitter integration.
To ensure that the STTwitter library is actually usable, I integrated it into TwitHunter.
TwitHunter has been my historical Twitter client pet project. It never was fully functional by let me
experiment ideas like scoring, which consists in calculating a score for each tweet according to a set of user-
defined rules, and then filtering out the tweets below a certain score.
TwitHunter is now also a proof of concept of a Twitter client where the user can choose the client identity he
wants. It is somewhat similar to a browser where you can choose the User-Agent you want. TwitHunter
lacks a lot a features but can send pictures and choose the tweet location. And Twitter cannot prevent
TwitHunter from displaying the tweets the way it wants without blocking existing applications.
13 of 16 5/1/20, 10:49 PM
seriot.ch - Abusing Twitter API
6. Security Considerations
Consumer keys are supposed to be kept secret in the OAuth protocol. This can be achieved when the
OAuth consumer and OAuth provider are remote web servers (eg. bit.ly and twitter.com). However, we have
seen that keeping these tokens secret in a desktop application is much more difficult, if possible at all.
Taking OAuth usage from the web to the desktop was somehow a conceptual error from Twitter, since it
really can't prevent hacker from extracting consumer tokens. Let us go though what can go wrong when
consumers token leak. Note that such a leak can go unnoticed from the application developer until it's too
late.
When using a user's context (PIN-based or xAuth authentication), there is a limit in reading for the tuple
(client, user) and another limit in writing for the user. Leaking consumer tokens should not exhaust these
limits faster since they depend on each user. However, the 100,000 users tokens cap per application may
be reached very quickly, resulting in a denial of service for the users of the application.
Now, without user context (application only authentication), anyone knowing the application consumer
tokens can get the bearer token. He can then send as many requests he wants to until the application rate
limits are exhausted, resulting in a denial of service for the legitimate application users.
Note that rate limits are sent along with response headers, such as in:
{
"x-rate-limit-limit" = 180;
"x-rate-limit-remaining" = 179;
"x-rate-limit-reset" = 1381661076;
}
While using the (application only authentication), anybody having an application consumer tokens can get
the bearer token, and post a request to invalidate it, resulting once again in an actual denial of service for
the legitimate application users who are still using the former, now invalidated bearer token.
Twitter says it will systematically invalidate keys of compromised applications (Developer Rules of the Road,
II. 3 C), which locks out users using the application, forcing them to use another one or use the Twitter
website in order to access the service.
Twitter frequently revokes consumer keys, but more rarely keys from popular applications. However, it did
not hesitate to revoke UberTwitter and twitdroyd tokens in February, 2011.
14 of 16 5/1/20, 10:49 PM
seriot.ch - Abusing Twitter API
We ask all developers in Twitter ecosystem to abide by a simple set of rules that are in the
interests of our users, as well as the health and vitality of the platform as a whole.
We often take actions to enforce these rules; in fact, on an average day we turn off more than
one hundred services that violate our API rules of the road. This keeps the ecosystem fair for
everyone.
http://techcrunch.com/2011/02/18/twitter-suspends-ubermedia-clients-ubertwitter-and-
twidroyd-for-violating-policies/
To restore API access after a key is invalidated, the developer of a compromised application has to register
a new key, prepare a new version of its application with the new key inside and have its users upgrade after
deploying the application, which may reqiore a lengthy review process such as in Apple App Store.
Also, leaked keys can expose the user to be stolen his user access tokens with an OAuth session fixation
attack empowered by a social engineering attack. It goes like that:
1. the attacker asks for request tokens and signs the request with the keys of a popular application
2. the attacker puts his own server pirate.net in the oauth_callback parameter in the request
token phase
3. the attacker tricks the user into clicking the link and authorizing the compromised app
4. twitter sends the verifier to pirate.net?oauth_token=xxx&oauth_verifier=yyy
5. optionally, the pirate server can redirect the user to twitter.com so that the victim won't even realise
he's been powned
The user has chosen to authorize some application to access his account, but the verifier was received by
the attacker. This verifier is all the attacker needs to ask and receive valid access tokens for the user.
Also, it is to be noted that there's no formal verification of client identity, so you can register "Twitter for
Windows 8" and trick users into trusting it by posting the token request URL in a popular forum.
This vulnerability was supposed to be fixed with OAuth 1.1a. However, Twitter does not fully enforce it and
that's why the attack is still possible with some consumer tokens from improperly configured applications,
such as TweetDeck, Tweetbot or Twitterrific for Mac, for instance.
Twitter insists on using OAuth to identify the client application, although it raises many issues.
One of the main reason asserted by Twitter to promote OAuth is that OAuth doesn't send the password over
the network.
First, we can object that HTTP Digest authentication does achieve the same goal.
Second, the most common Twitter clients such as official Twitter clients, OS X and iOS Twitter integration
but also many third-party client use xAuth to retrieve the user access tokens, and xAuth sends the username
and password in clear over the network.
Nevertheless, OAuth still has the advantage of not requiring the client application to store the password, but
just storing the access tokens instead.
Twitter claims that the consumer keys are needed to kill applications used by spammers, but OAuth was
simply not designed to be used for that purpose. Additionally, it may not be efficient at all, since spammers
will use consumer tokens from official clients, and blocking official clients is not an option. Closing individual
spammer accounts makes much more sense.
The consumer tokens are fundamentally insecure when used within a client application. Additionaly,
requesting the consumer keys to be kept secret effectively kills open-source applications.
Twitter asks developers to protect their keys in an environnment where users have complete control over the
execution flow and access to full address space, so it's impossible to prevent keys extraction.
This problem is somehow similar to the DVD / HDMI / HDCP decryption. At some point, the user has to use
a machine that will load in memory cryptographic keys that will be use to decrypt the protected content. It's
just a matter of time and motivation until motivated hackers extract the keys and can replicate the decryption
process.
Twitter's uses OAuth for something it is not made for. Indeed, the OAuth specification cannot be more clear:
15 of 16 5/1/20, 10:49 PM
seriot.ch - Abusing Twitter API
"In many cases, the client application will be under the control of potentially untrusted parties.
For example, if the client is a desktop application with freely available source code or an
executable binary, an attacker may be able to download a copy for analysis. In such cases,
attackers will be able to recover the client credentials." http://tools.ietf.org
/html/rfc5849#section-4.6
Nevertheless, Twitter keeps asking developers to hide theses keys as they can:
With desktop applications, it's a matter of "best effort" security with your consumer secret and
access token secrets. We recommend making it difficult to obtain the keys from a packaged
application, while acknowledging that a determined hacker would be able to obtain them.
That's where monitoring and damage control comes in -- we give all app developers the ability
to reset/regenerate their consumer key and secret at any time, which is an effective "kill switch"
for the former secrets.
We do our best to monitor for abuse and proactively stub out issues when they arise.
Twitter's implementation of OAuth lacks a couple of OAuth specification requirements on the server side.
Specifically:
Twitter does not check that combination of nonce/timestamp/token are not reused. The same request
can be replayed for a few minutes, and new requests can reuse a former, already used (nonce,
timestamp, token) combination.
A constant nonce can be reused across requests. It can even be "0".
So, strictly speaking, Twitter implements a custom, less secure variant of OAuth.
7. Conclusion
In this article:
we've talked about Twitter evolution from an open, geek-friendly network towards a closed, big-media
and advertisers friendly network, and the consequences on Twitter API;
we've presented the OAuth protocol with focus on the process to receive access tokens;
we've used some reverse engineering techniques to extract OAuth consumer tokens from popular
Twitter clients;
we've exposed hardcoded Twitter tokens, their locations and the way they are obfuscated;
we've built a modern Objective-C library to use Twitter API v1.1 and a prototypic Twitter client on top
of it;
we've seen how to impersonate popular Twitter clients;
we've explained how to craft accounts creation requests similar to iOS ones;
we've demonstrated a practical session fixation attack;
we've discussed this situation from a security standpoint.
It appears from our work that the main reason for switching from basic authentication to OAuth is not user
security or spam fighting, but simply third-party applications control.
We also showed that Twitter has currently no technical way of enforcing its new display requirements or any
such policy. Restricting access to their API to their official clients only while banning third-party clients is a
very hard problem to solve, if possible at all. For sure, they could go the Skype way with an proprietary,
complicated protocol but it would not be simple and would raise many new issues.
So, Twitter tries to live with the consumer keys management issue by asking developers to do their best to
hide the consumer_secret in their applications, monitoring leaks and revoking the keys when problems
arise.
Copyright - seriot.ch
16 of 16 5/1/20, 10:49 PM