asfws 2013 rump session - abusing twitter api one year later… nicolas seriot
TRANSCRIPT
Application Security Forum - 2012Western Switzerland
7-8 novembre 2012Y-Parc / Yverdon-les-Bainshttps://www.appsec-forum.ch
AbusingTwitter APINicolas Seriot
One year later…
AppSec 2012Twitter relied on OAuth to control 3rd party clients.
Bad idea! secret tokens are easy to extract.
Leaked consumer secrets can result in API abuses, DoS and
session fixation attacks.
@boblord
HITB 2013 Amsterdam
HITB, April 10th April 23rd, 2013
Some App. Twitter
invalidate_token
user_timeline
violet token is for Some App.
consumer_secret
consumer_key
bearer_token
App
. Onl
yA
uthe
ntic
atio
ntoken
Use the consumer tokens to get the bearer token and exhaust the limits. Denial of service.
And now you can invalidate the bearer token.
Denial of servicefor “Some App.”! ht
tps:
//dev
.twitt
er.c
om/d
ocs/
auth
/app
licat
ion-
only
-aut
h
UniBinary
Pack 289+ ASCII chars or 209+ bytes into 140 chinese characters.https://github.com/nst/UniBinary
Core Text Crasher
$ gdb Twitter
(gdb) rStarting program: /Applications/Twitter.app/Contents/MacOS/Twitter
Program received signal EXC_BAD_ACCESS, Could not access memory.Reason: KERN_INVALID_ADDRESS at address: 0x00000001084e80080x00007fff9432ead2 in vDSP_sveD ()
(gdb) bt#0 0x00007fff9432ead2 in vDSP_sveD ()#1 0x00007fff934594fe in TStorageRange::SetStorageSubRange ()#2 0x00007fff93457d5c in TRun::TRun ()#3 0x00007fff934579ee in CTGlyphRun::CloneRange ()#4 0x00007fff93466764 in TLine::SetLevelRange ()#5 0x00007fff93467e2c in TLine::SetTrailingWhitespaceLevel ()#6 0x00007fff93467d58 in TRunReorder::ReorderRuns ()#7 0x00007fff93467bfe in TTypesetter::FinishLineFill ()#8 0x00007fff934858ae in TFramesetter::FrameInRect ()#9 0x00007fff93485110 in TFramesetter::CreateFrame ()#10 0x00007fff93484af2 in CTFramesetterCreateFrame ()...
The vulnerable code has probably been in the wild for yonks; some people noticed it six months ago and it appeared on some slides [PDF] in April for a Hack In The Box conference presentation. Barely anyone took any notice back then - but it started to spread around the web over the weekend after a trigger string appeared on a Russian website.
http://www.theregister.co.uk/2013/09/04/unicode_of_death_crash/
http://www.lemondeinformatique.fr/actualites/lire-un-developpeur-detourne-la-
fonction-oauth-de-twitter-53213.html
request_token
access_token
home_timeline green tokens are for@nst021 with
My.app
consumer_secret
consumer_key
access_secret
access_key
request_key
Rev
erse
Aut
h.
iOS_secret
iOS_key
My.app Server
My.app Server
My.app
✓ CS is not shipped with My.app.
✗ Users unknowingly grants My.app access to her DMs.
http
s://d
ev.tw
itter
.com
/doc
s/io
s/us
ing-
reve
rse-
auth
Twitter / iOS Integration
• How does Twitter identify the application sending requests through iOS frameworks ?
• TWRequest (iOS 5) adds an application_id param to each request (eg. ch.seriot.myApp)
• SLRequest (iOS 6+) does not!
Accounts Creation
Web iOS Settings
CaptchaNo
Captcha
Create Accounts in Batch
POST https://api.twitter.com/1/account/generate.json
Authorization: OAuth \ oauth_nonce="C4E16213-9058-49E8-A06E-65A5D961EED0", \ oauth_signature_method="HMAC-SHA1", \ oauth_timestamp="1378598935", \ oauth_consumer_key="IHUYavQ7mmPBhNiBBlF9Q", \ oauth_token="8285392-niqOtDvwwUXOzQJsCvDxcPndUBHb4dWrTLXw1nTw", \ oauth_signature="V6ySPsviDz%2BJnTvBFoE2qpHJv70%3D", \ oauth_version="1.0"
adc: paddiscoverable_by_email: 0email: EMAILgeo_enabled: 0lang: enname: NAMEpassword: PASSWORDscreen_name: SCREEN_NAMEsend_error_codes: truetime_zone: CEST
Related consumer secret is easy to find with GDB
attached to iOS Simulator.
No need to fill captchas anymore :)
Weird Consumer Identity
WTF?!
“Almost” OAuth3.2. Verifying Requests
Servers receiving an authenticated request MUST validate it by: (...)
o If using the "HMAC-SHA1" or "RSA-SHA1" signature methods, ensuring that the combination of nonce/timestamp/token (if present) received from the client has not been used before in a previous request (the server MAY reject requests with stale timestamps as described in Section 3.3).
3.3. Nonce and Timestamp
(...) A nonce is a random string, uniquely generated by the client to allow the server to verify that a request has never been made before and helps prevent replay attacks when requests are made over a non-secure channel. The nonce value MUST be unique across all requests with the same timestamp, client credentials, and token combinations.
http://tools.ietf.org/html/rfc5849
✗ (nonce, timestamp, token)can be reused across requests.
✗ nonce can be fixed.
Ad
No Ad
Promoted Contents
Undocumented API?$ strings Twitter ...activity/about_me.jsonactivity/by_friends.jsonconversation/show.jsondiscover/highlight.jsondiscover/universal.jsonstatuses/:id/activity/summary.jsonstatuses/media_timeline.jsonstatuses/mentions_timeline.jsontimeline/home.jsontrends/available.jsonusers/recommendations.json...
Looking for Ads• Still no clues about promoted contents.
Let’s start our favorite SSL proxy!
• Does’t work because of certificate pinning.
• Binary patching FTW!
Twitter.app SSL proxy api.twitter.com
-[ABHTTPRequest connection:willSendRequestForAuthenticationChallenge:] ... 0x00260cd4 45F2EA50 movw r0, #0x55ea 0x00260cd8 3246 mov r2, r6 0x00260cda C0F23900 movt r0, #0x39 0x00260cde 7844 add r0, pc ; 0x5f62cc 0x00260ce0 0168 ldr r1, [r0] ; @selector(_isPinnedCertificateChain:) 0x00260ce2 2046 mov r0, r4 0x00260ce4 B0F1DEEC blx imp___picsymbolstub4__objc_msgSend
; BOOL isPinned = [self _isPinnedCertificateChain:object];
0x00260ce8 0446 mov r4, r0 0x00260cea 2846 mov r0, r5 0x00260cec B0F1FAEC blx imp___picsymbolstub4__objc_release
0x00260cf0 14F0FF0F tst.w r4, #0xff ; Z = (r4 & 0xff) == 0 ; Z = (r4 == 0) 0x00260cf4 40F08E80 bne.w 0x260e14 ...
; if(isPinned) { ; goto 0x260e14; // continue handling the request ; } else { ; return error; ; }
https://ece.uwaterloo.ca/~ece222/ARM/ARM7-TDMI-manual-pt3.pdf
ARM THUMB Instruction Set
Crafting Opcode1110 0... .... .... ; opcode format
0x00260e14 - 0x00260cf4 = 0x120 ; offset
0000 0001 0010 0000 ; 0x1200000 0000 1001 0000 ; 0x120 >> 11110 0... .... .... ; format___________________1110 0000 1001 0000 ; 0xE0900xE 0x0 0x9 0x0
-> 0x90E0 little endian
-[ABHTTPRequest connection:willSendRequestForAuthenticationChallenge:] ... 0x00260cd4 45F2EA50 movw r0, #0x55ea 0x00260cd8 3246 mov r2, r6 0x00260cda C0F23900 movt r0, #0x39 0x00260cde 7844 add r0, pc ; 0x5f62cc 0x00260ce0 0168 ldr r1, [r0] ; @selector(_isPinnedCertificateChain:) 0x00260ce2 2046 mov r0, r4 0x00260ce4 B0F1DEEC blx imp___picsymbolstub4__objc_msgSend
; BOOL isPinned = [self _isPinnedCertificateChain:object];
0x00260ce8 0446 mov r4, r0 0x00260cea 2846 mov r0, r5 0x00260cec B0F1FAEC blx imp___picsymbolstub4__objc_release
- 0x00260cf0 14F0FF0F tst.w r4, #0xff ; Z = (r4 & 0xff) == 0 ; Z = (r4 == 0)+ 0x00260cf0 90E0FF0F b 0x260e14 ; jump to happy path (FF0F is unused) 0x00260cf4 40F08E80 bne.w 0x260e14 ; never reached ...
; goto 0x260e14; // continue handling the request ; ; ; return error; ;
My 2 Bytes
Promoted Contents Secret
&pc=true
Twitter: @nst021
Web: http://seriot.ch/abusing_twitter_api.php
Slides: http://www.slideshare.net/ASF-WS/presentations