diff --git a/extra/pagerank/pagerank.py b/extra/pagerank/pagerank.py index 106ac72fb..4d7b80afb 100644 --- a/extra/pagerank/pagerank.py +++ b/extra/pagerank/pagerank.py @@ -1,75 +1,75 @@ -#!/usr/bin/env python -# -# Script for getting Google Page Rank of page -# Google Toolbar 3.0.x/4.0.x Pagerank Checksum Algorithm -# -# original from http://pagerank.gamesaga.net/ -# this version was adapted from http://www.djangosnippets.org/snippets/221/ -# by Corey Goldberg - 2010 -# -# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php - -import urllib - -def get_pagerank(url): - hsh = check_hash(hash_url(url)) - gurl = 'http://www.google.com/search?client=navclient-auto&features=Rank:&q=info:%s&ch=%s' % (urllib.quote(url), hsh) - try: - f = urllib.urlopen(gurl) - rank = f.read().strip()[9:] - except Exception: - rank = 'N/A' - if rank == '': - rank = '0' - return rank - -def int_str(string, integer, factor): - for i in range(len(string)) : - integer *= factor - integer &= 0xFFFFFFFF - integer += ord(string[i]) - return integer - -def hash_url(string): - c1 = int_str(string, 0x1505, 0x21) - c2 = int_str(string, 0, 0x1003F) - - c1 >>= 2 - c1 = ((c1 >> 4) & 0x3FFFFC0) | (c1 & 0x3F) - c1 = ((c1 >> 4) & 0x3FFC00) | (c1 & 0x3FF) - c1 = ((c1 >> 4) & 0x3C000) | (c1 & 0x3FFF) - - t1 = (c1 & 0x3C0) << 4 - t1 |= c1 & 0x3C - t1 = (t1 << 2) | (c2 & 0xF0F) - - t2 = (c1 & 0xFFFFC000) << 4 - t2 |= c1 & 0x3C00 - t2 = (t2 << 0xA) | (c2 & 0xF0F0000) - - return (t1 | t2) - -def check_hash(hash_int): - hash_str = '%u' % (hash_int) - flag = 0 - check_byte = 0 - - i = len(hash_str) - 1 - while i >= 0: - byte = int(hash_str[i]) - if 1 == (flag % 2): - byte *= 2; - byte = byte / 10 + byte % 10 - check_byte += byte - flag += 1 - i -= 1 - - check_byte %= 10 - if 0 != check_byte: - check_byte = 10 - check_byte - if 1 == flag % 2: - if 1 == check_byte % 2: - check_byte += 9 - check_byte >>= 1 - - return '7' + str(check_byte) + hash_str +#!/usr/bin/env python +# +# Script for getting Google Page Rank of page +# Google Toolbar 3.0.x/4.0.x Pagerank Checksum Algorithm +# +# original from http://pagerank.gamesaga.net/ +# this version was adapted from http://www.djangosnippets.org/snippets/221/ +# by Corey Goldberg - 2010 +# +# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php + +import urllib + +def get_pagerank(url): + hsh = check_hash(hash_url(url)) + gurl = 'http://www.google.com/search?client=navclient-auto&features=Rank:&q=info:%s&ch=%s' % (urllib.quote(url), hsh) + try: + f = urllib.urlopen(gurl) + rank = f.read().strip()[9:] + except Exception: + rank = 'N/A' + if rank == '': + rank = '0' + return rank + +def int_str(string, integer, factor): + for i in range(len(string)) : + integer *= factor + integer &= 0xFFFFFFFF + integer += ord(string[i]) + return integer + +def hash_url(string): + c1 = int_str(string, 0x1505, 0x21) + c2 = int_str(string, 0, 0x1003F) + + c1 >>= 2 + c1 = ((c1 >> 4) & 0x3FFFFC0) | (c1 & 0x3F) + c1 = ((c1 >> 4) & 0x3FFC00) | (c1 & 0x3FF) + c1 = ((c1 >> 4) & 0x3C000) | (c1 & 0x3FFF) + + t1 = (c1 & 0x3C0) << 4 + t1 |= c1 & 0x3C + t1 = (t1 << 2) | (c2 & 0xF0F) + + t2 = (c1 & 0xFFFFC000) << 4 + t2 |= c1 & 0x3C00 + t2 = (t2 << 0xA) | (c2 & 0xF0F0000) + + return (t1 | t2) + +def check_hash(hash_int): + hash_str = '%u' % (hash_int) + flag = 0 + check_byte = 0 + + i = len(hash_str) - 1 + while i >= 0: + byte = int(hash_str[i]) + if 1 == (flag % 2): + byte *= 2; + byte = byte / 10 + byte % 10 + check_byte += byte + flag += 1 + i -= 1 + + check_byte %= 10 + if 0 != check_byte: + check_byte = 10 - check_byte + if 1 == flag % 2: + if 1 == check_byte % 2: + check_byte += 9 + check_byte >>= 1 + + return '7' + str(check_byte) + hash_str diff --git a/lib/core/replication.py b/lib/core/replication.py index 5aa2b275d..d15957b8b 100644 --- a/lib/core/replication.py +++ b/lib/core/replication.py @@ -1,102 +1,102 @@ -#!/usr/bin/env python - -""" -$Id$ - -Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) -See the file 'doc/COPYING' for copying permission -""" - -from lib.core.exception import sqlmapMissingDependence -from lib.core.exception import sqlmapValueException - -class Replication: - """ - This class holds all methods/classes used for database - replication purposes. - """ - - def __init__(self, dbpath): - try: - import sqlite3 - except ImportError, _: - errMsg = "missing module 'sqlite3' needed by --replicate switch" - raise sqlmapMissingDependence, errMsg - - self.dbpath = dbpath - self.connection = sqlite3.connect(dbpath) - self.connection.isolation_level = None - self.cursor = self.connection.cursor() - - class DataType: - """ - Using this class we define auxiliary objects - used for representing sqlite data types. - """ - - def __init__(self, name): - self.name = name - - def __str__(self): - return self.name - - def __repr__(self): - return "" % self - - class Table: - """ - This class defines methods used to manipulate table objects. - """ - - def __init__(self, parent, name, columns=None, create=True, typeless=False): - self.parent = parent - self.name = name - self.columns = columns - if create: - self.parent.cursor.execute('DROP TABLE IF EXISTS %s' % self.name) - if not typeless: - self.parent.cursor.execute('CREATE TABLE %s (%s)' % (self.name, ','.join('%s %s' % (colname, coltype) for colname, coltype in self.columns))) - else: - self.parent.cursor.execute('CREATE TABLE %s (%s)' % (self.name, ','.join(colname for colname in self.columns))) - - def insert(self, values): - """ - This function is used for inserting row(s) into current table. - """ - if len(values) == len(self.columns): - self.parent.cursor.execute('INSERT INTO %s VALUES (%s)' % (self.name, ','.join(['?']*len(values))), values) - else: - errMsg = "wrong number of columns used in replicating insert" - raise sqlmapValueException, errMsg - - def select(self, condition=None): - """ - This function is used for selecting row(s) from current table. - """ - stmt = 'SELECT * FROM %s' % self.name - if condition: - stmt += 'WHERE %s' % condition - return self.parent.cursor.execute(stmt) - - def createTable(self, tblname, columns=None, typeless=False): - """ - This function creates Table instance with current connection settings. - """ - return Replication.Table(parent=self, name=tblname, columns=columns, typeless=typeless) - - def dropTable(self, tblname): - """ - This function drops table with given name using current connection. - """ - self.cursor.execute('DROP TABLE IF EXISTS %s' % tblname) - - def __del__(self): - self.cursor.close() - self.connection.close() - - # sqlite data types - NULL = DataType('NULL') - INTEGER = DataType('INTEGER') - REAL = DataType('REAL') - TEXT = DataType('TEXT') - BLOB = DataType('BLOB') +#!/usr/bin/env python + +""" +$Id$ + +Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) +See the file 'doc/COPYING' for copying permission +""" + +from lib.core.exception import sqlmapMissingDependence +from lib.core.exception import sqlmapValueException + +class Replication: + """ + This class holds all methods/classes used for database + replication purposes. + """ + + def __init__(self, dbpath): + try: + import sqlite3 + except ImportError, _: + errMsg = "missing module 'sqlite3' needed by --replicate switch" + raise sqlmapMissingDependence, errMsg + + self.dbpath = dbpath + self.connection = sqlite3.connect(dbpath) + self.connection.isolation_level = None + self.cursor = self.connection.cursor() + + class DataType: + """ + Using this class we define auxiliary objects + used for representing sqlite data types. + """ + + def __init__(self, name): + self.name = name + + def __str__(self): + return self.name + + def __repr__(self): + return "" % self + + class Table: + """ + This class defines methods used to manipulate table objects. + """ + + def __init__(self, parent, name, columns=None, create=True, typeless=False): + self.parent = parent + self.name = name + self.columns = columns + if create: + self.parent.cursor.execute('DROP TABLE IF EXISTS %s' % self.name) + if not typeless: + self.parent.cursor.execute('CREATE TABLE %s (%s)' % (self.name, ','.join('%s %s' % (colname, coltype) for colname, coltype in self.columns))) + else: + self.parent.cursor.execute('CREATE TABLE %s (%s)' % (self.name, ','.join(colname for colname in self.columns))) + + def insert(self, values): + """ + This function is used for inserting row(s) into current table. + """ + if len(values) == len(self.columns): + self.parent.cursor.execute('INSERT INTO %s VALUES (%s)' % (self.name, ','.join(['?']*len(values))), values) + else: + errMsg = "wrong number of columns used in replicating insert" + raise sqlmapValueException, errMsg + + def select(self, condition=None): + """ + This function is used for selecting row(s) from current table. + """ + stmt = 'SELECT * FROM %s' % self.name + if condition: + stmt += 'WHERE %s' % condition + return self.parent.cursor.execute(stmt) + + def createTable(self, tblname, columns=None, typeless=False): + """ + This function creates Table instance with current connection settings. + """ + return Replication.Table(parent=self, name=tblname, columns=columns, typeless=typeless) + + def dropTable(self, tblname): + """ + This function drops table with given name using current connection. + """ + self.cursor.execute('DROP TABLE IF EXISTS %s' % tblname) + + def __del__(self): + self.cursor.close() + self.connection.close() + + # sqlite data types + NULL = DataType('NULL') + INTEGER = DataType('INTEGER') + REAL = DataType('REAL') + TEXT = DataType('TEXT') + BLOB = DataType('BLOB') diff --git a/lib/core/revision.py b/lib/core/revision.py index ba5aa0643..1e751a4ec 100644 --- a/lib/core/revision.py +++ b/lib/core/revision.py @@ -1,42 +1,42 @@ -#!/usr/bin/env python - -""" -$Id$ - -Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) -See the file 'doc/COPYING' for copying permission -""" - -import os -import re - -from subprocess import PIPE -from subprocess import Popen as execute - -def getRevisionNumber(): - curDir = os.path.dirname(os.path.realpath(__file__)) - retVal = None - - try: - import pysvn - - client = pysvn.Client() - if client.info(curDir): - retVal = client.info(curDir).revision.number - except ImportError, _: - process = execute("svn info %s" % curDir, shell=True, stdout=PIPE, stderr=PIPE) - svnStdout, svnStderr = process.communicate() - - if svnStdout: - revision = re.search("Revision:\s+([\d]+)", svnStdout) - - if revision: - retVal = revision.group(1) - - if retVal: - try: - retVal = int(retVal) - except ValueError: - retVal = None - - return retVal +#!/usr/bin/env python + +""" +$Id$ + +Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) +See the file 'doc/COPYING' for copying permission +""" + +import os +import re + +from subprocess import PIPE +from subprocess import Popen as execute + +def getRevisionNumber(): + curDir = os.path.dirname(os.path.realpath(__file__)) + retVal = None + + try: + import pysvn + + client = pysvn.Client() + if client.info(curDir): + retVal = client.info(curDir).revision.number + except ImportError, _: + process = execute("svn info %s" % curDir, shell=True, stdout=PIPE, stderr=PIPE) + svnStdout, svnStderr = process.communicate() + + if svnStdout: + revision = re.search("Revision:\s+([\d]+)", svnStdout) + + if revision: + retVal = revision.group(1) + + if retVal: + try: + retVal = int(retVal) + except ValueError: + retVal = None + + return retVal diff --git a/lib/request/basicauthhandler.py b/lib/request/basicauthhandler.py index abbb57d3c..eac1faceb 100644 --- a/lib/request/basicauthhandler.py +++ b/lib/request/basicauthhandler.py @@ -1,33 +1,33 @@ -#!/usr/bin/env python - -""" -$Id$ - -Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) -See the file 'doc/COPYING' for copying permission -""" - -import urllib2 - -class SmartHTTPBasicAuthHandler(urllib2.HTTPBasicAuthHandler): - """ - Reference: http://selenic.com/hg/rev/6c51a5056020 - Fix for a: http://bugs.python.org/issue8797 - """ - def __init__(self, *args, **kwargs): - urllib2.HTTPBasicAuthHandler.__init__(self, *args, **kwargs) - self.retried_req = set() - - def reset_retry_count(self): - # Python 2.6.5 will call this on 401 or 407 errors and thus loop - # forever. We disable reset_retry_count completely and reset in - # http_error_auth_reqed instead. - pass - - def http_error_auth_reqed(self, auth_header, host, req, headers): - # Reset the retry counter once for each request. - if hash(req) not in self.retried_req: - self.retried_req.add(hash(req)) - self.retried = 0 - return urllib2.HTTPBasicAuthHandler.http_error_auth_reqed( - self, auth_header, host, req, headers) +#!/usr/bin/env python + +""" +$Id$ + +Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) +See the file 'doc/COPYING' for copying permission +""" + +import urllib2 + +class SmartHTTPBasicAuthHandler(urllib2.HTTPBasicAuthHandler): + """ + Reference: http://selenic.com/hg/rev/6c51a5056020 + Fix for a: http://bugs.python.org/issue8797 + """ + def __init__(self, *args, **kwargs): + urllib2.HTTPBasicAuthHandler.__init__(self, *args, **kwargs) + self.retried_req = set() + + def reset_retry_count(self): + # Python 2.6.5 will call this on 401 or 407 errors and thus loop + # forever. We disable reset_retry_count completely and reset in + # http_error_auth_reqed instead. + pass + + def http_error_auth_reqed(self, auth_header, host, req, headers): + # Reset the retry counter once for each request. + if hash(req) not in self.retried_req: + self.retried_req.add(hash(req)) + self.retried = 0 + return urllib2.HTTPBasicAuthHandler.http_error_auth_reqed( + self, auth_header, host, req, headers) diff --git a/lib/utils/hash.py b/lib/utils/hash.py index d904d44a3..abb70930b 100644 --- a/lib/utils/hash.py +++ b/lib/utils/hash.py @@ -1,465 +1,465 @@ -#!/usr/bin/env python - -""" -$Id$ - -Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) -See the file 'doc/COPYING' for copying permission -""" - -import re -import time - -from hashlib import md5 -from hashlib import sha1 -from zipfile import ZipFile - -from extra.pydes.pyDes import des -from extra.pydes.pyDes import CBC -from lib.core.common import checkFile -from lib.core.common import clearConsoleLine -from lib.core.common import dataToStdout -from lib.core.common import getCompiledRegex -from lib.core.common import getFileItems -from lib.core.common import Backend -from lib.core.common import getPublicTypeMembers -from lib.core.common import getUnicode -from lib.core.common import paths -from lib.core.common import readInput -from lib.core.convert import hexdecode -from lib.core.convert import hexencode -from lib.core.data import kb -from lib.core.data import logger -from lib.core.enums import DBMS -from lib.core.enums import HASH -from lib.core.exception import sqlmapUserQuitException -from lib.core.settings import COMMON_PASSWORD_SUFFIXES -from lib.core.settings import DUMMY_USER_PREFIX -from lib.core.settings import UNICODE_ENCODING - -def mysql_passwd(password, uppercase=True): - """ - Reference(s): - http://csl.sublevel3.org/mysql-password-function/ - - >>> mysql_passwd(password='testpass', uppercase=True) - '*00E247AC5F9AF26AE0194B41E1E769DEE1429A29' - """ - - retVal = "*%s" % sha1(sha1(password).digest()).hexdigest() - - return retVal.upper() if uppercase else retVal.lower() - -def mysql_old_passwd(password, uppercase=True): # prior to version '4.1' - """ - Reference(s): - http://www.sfr-fresh.com/unix/privat/tpop3d-1.5.5.tar.gz:a/tpop3d-1.5.5/password.c - http://voidnetwork.org/5ynL0rd/darkc0de/python_script/darkMySQLi.html - - >>> mysql_old_passwd(password='testpass', uppercase=True) - '7DCDA0D57290B453' - """ - - a, b, c = 1345345333, 7, 0x12345671 - - for d in password: - if d == ' ' or d == '\t': - continue - - e = ord(d) - a ^= (((a & 63) + b) * e) + (a << 8) - c += (c << 8) ^ a - b += e - - retVal = "%08lx%08lx" % (a & ((1 << 31) - 1), c & ((1 << 31) - 1)) - - return retVal.upper() if uppercase else retVal.lower() - -def postgres_passwd(password, username, uppercase=False): - """ - Reference(s): - http://pentestmonkey.net/blog/cracking-postgres-hashes/ - - >>> postgres_passwd(password='testpass', username='testuser', uppercase=False) - 'md599e5ea7a6f7c3269995cba3927fd0093' - """ - - retVal = "md5%s" % md5(password + username).hexdigest() - - return retVal.upper() if uppercase else retVal.lower() - -def mssql_passwd(password, salt, uppercase=False): - """ - Reference(s): - http://www.leidecker.info/projects/phrasendrescher/mssql.c - https://www.evilfingers.com/tools/GSAuditor.php - - >>> mssql_passwd(password='testpass', salt='4086ceb6', uppercase=False) - '0x01004086ceb60c90646a8ab9889fe3ed8e5c150b5460ece8425a' - """ - - binsalt = hexdecode(salt) - unistr = "".join("%s\0" % c for c in password) - - retVal = "0100%s%s" % (salt, sha1(unistr + binsalt).hexdigest()) - - return "0x%s" % (retVal.upper() if uppercase else retVal.lower()) - -def mssql_old_passwd(password, salt, uppercase=True): # prior to version '2005' - """ - Reference(s): - www.exploit-db.com/download_pdf/15537/ - http://www.leidecker.info/projects/phrasendrescher/mssql.c - https://www.evilfingers.com/tools/GSAuditor.php - - >>> mssql_old_passwd(password='testpass', salt='4086ceb6', uppercase=True) - '0x01004086CEB60C90646A8AB9889FE3ED8E5C150B5460ECE8425AC7BB7255C0C81D79AA5D0E93D4BB077FB9A51DA0' - """ - - binsalt = hexdecode(salt) - unistr = "".join("%s\0" % c for c in password) - - retVal = "0100%s%s%s" % (salt, sha1(unistr + binsalt).hexdigest(), sha1(unistr.upper() + binsalt).hexdigest()) - - return "0x%s" % (retVal.upper() if uppercase else retVal.lower()) - -def oracle_passwd(password, salt, uppercase=True): - """ - Reference(s): - https://www.evilfingers.com/tools/GSAuditor.php - http://www.notesbit.com/index.php/scripts-oracle/oracle-11g-new-password-algorithm-is-revealed-by-seclistsorg/ - http://seclists.org/bugtraq/2007/Sep/304 - - >>> oracle_passwd(password='SHAlala', salt='1B7B5F82B7235E9E182C', uppercase=True) - 'S:2BFCFDF5895014EE9BB2B9BA067B01E0389BB5711B7B5F82B7235E9E182C' - """ - - binsalt = hexdecode(salt) - - retVal="s:%s%s" % (sha1(password + binsalt).hexdigest(), salt) - - return retVal.upper() if uppercase else retVal.lower() - -def oracle_old_passwd(password, username, uppercase=True): # prior to version '11g' - """ - Reference(s): - http://www.notesbit.com/index.php/scripts-oracle/oracle-11g-new-password-algorithm-is-revealed-by-seclistsorg/ - - >>> oracle_old_passwd(password='tiger', username='scott', uppercase=True) - 'F894844C34402B67' - """ - IV, pad = "\0"*8, "\0" - - if isinstance(username, unicode): - username = unicode.encode(username, UNICODE_ENCODING) #pyDes has issues with unicode strings - - unistr = "".join("\0%s" % c for c in (username + password).upper()) - - cipher = des(hexdecode("0123456789ABCDEF"), CBC, IV, pad) - encrypted = cipher.encrypt(unistr) - cipher = des(encrypted[-8:], CBC, IV, pad) - encrypted = cipher.encrypt(unistr) - - retVal = hexencode(encrypted[-8:]) - - return retVal.upper() if uppercase else retVal.lower() - -def md5_generic_passwd(password, uppercase=False): - """ - >>> md5_generic_passwd(password='testpass', uppercase=False) - '179ad45c6ce2cb97cf1029e212046e81' - """ - - retVal = md5(password).hexdigest() - - return retVal.upper() if uppercase else retVal.lower() - -def sha1_generic_passwd(password, uppercase=False): - """ - >>> sha1_generic_passwd(password='testpass', uppercase=False) - '206c80413b9a96c1312cc346b7d2517b84463edd' - """ - - retVal = sha1(password).hexdigest() - - return retVal.upper() if uppercase else retVal.lower() - -__functions__ = { - HASH.MYSQL: mysql_passwd, - HASH.MYSQL_OLD: mysql_old_passwd, - HASH.POSTGRES: postgres_passwd, - HASH.MSSQL: mssql_passwd, - HASH.MSSQL_OLD: mssql_old_passwd, - HASH.ORACLE: oracle_passwd, - HASH.ORACLE_OLD: oracle_old_passwd, - HASH.MD5_GENERIC: md5_generic_passwd, - HASH.SHA1_GENERIC: sha1_generic_passwd - } - -def attackCachedUsersPasswords(): - if kb.data.cachedUsersPasswords: - results = dictionaryAttack(kb.data.cachedUsersPasswords) - - for (user, hash_, password) in results: - for i in xrange(len(kb.data.cachedUsersPasswords[user])): - if kb.data.cachedUsersPasswords[user][i] and hash_.lower() in kb.data.cachedUsersPasswords[user][i].lower(): - kb.data.cachedUsersPasswords[user][i] += "%s clear-text password: %s" % ('\n' if kb.data.cachedUsersPasswords[user][i][-1] != '\n' else '', password) - -def attackDumpedTable(): - if kb.data.dumpedTable: - table = kb.data.dumpedTable - columns = table.keys() - count = table["__infos__"]["count"] - - colUser = '' - attack_dict = {} - - for column in columns: - if column and column.lower() in ('user', 'username', 'user_name'): - colUser = column - break - - for i in range(count): - for column in columns: - if column == colUser or column == '__infos__': - continue - - if len(table[column]['values']) <= i: - continue - - value = table[column]['values'][i] - - if hashRecognition(value): - if colUser: - if table[colUser]['values'][i] not in attack_dict: - attack_dict[table[colUser]['values'][i]] = [] - - attack_dict[table[colUser]['values'][i]].append(value) - else: - attack_dict['%s%d' % (DUMMY_USER_PREFIX, i)] = [value] - - if attack_dict: - message = "recognized possible password hash values. " - message += "do you want to use dictionary attack on retrieved table items? [Y/n/q]" - test = readInput(message, default="Y") - - if test[0] in ("n", "N"): - return - elif test[0] in ("q", "Q"): - raise sqlmapUserQuitException - - results = dictionaryAttack(attack_dict) - - for (user, hash_, password) in results: - for i in range(count): - for column in columns: - if column == colUser or column == '__infos__': - continue - if len(table[column]['values']) <= i: - continue - - value = table[column]['values'][i] - - if value.lower() == hash_.lower(): - table[column]['values'][i] += " (%s)" % password - table[column]['length'] = max(table[column]['length'], len(table[column]['values'][i])) - -def hashRecognition(value): - retVal = None - - if value: - for name, regex in getPublicTypeMembers(HASH): - # Hashes for Oracle and old MySQL look the same hence these checks - if Backend.getIdentifiedDbms() == DBMS.ORACLE and regex == HASH.MYSQL_OLD: - continue - elif Backend.getIdentifiedDbms() == DBMS.MYSQL and regex == HASH.ORACLE_OLD: - continue - elif getCompiledRegex(regex).match(value): - retVal = regex - break - - return retVal - -def dictionaryAttack(attack_dict): - hash_regexes = [] - results = [] - - for (_, hashes) in attack_dict.items(): - for hash_ in hashes: - if not hash_: - continue - - hash_ = hash_.split()[0] - regex = hashRecognition(hash_) - - if regex and regex not in hash_regexes: - hash_regexes.append(regex) - infoMsg = "using hash method: '%s'" % __functions__[regex].func_name - logger.info(infoMsg) - - for hash_regex in hash_regexes: - attack_info = [] - - for (user, hashes) in attack_dict.items(): - for hash_ in hashes: - if not hash_: - continue - - hash_ = hash_.split()[0] - - if re.match(hash_regex, hash_): - hash_ = hash_.lower() - - if hash_regex in (HASH.MYSQL, HASH.MYSQL_OLD, HASH.MD5_GENERIC, HASH.SHA1_GENERIC): - attack_info.append([(user, hash_), {}]) - - elif hash_regex in (HASH.ORACLE_OLD, HASH.POSTGRES): - attack_info.append([(user, hash_), {'username': user}]) - - elif hash_regex in (HASH.ORACLE): - attack_info.append([(user, hash_), {'salt': hash_[-20:]}]) - - elif hash_regex in (HASH.MSSQL, HASH.MSSQL_OLD): - attack_info.append([(user, hash_), {'salt': hash_[6:14]}]) - - if not kb.wordlist: - if hash_regex == HASH.ORACLE_OLD: #it's the slowest of all methods hence smaller default dict - message = "what's the dictionary's location? [%s]" % paths.ORACLE_DEFAULT_PASSWD - dictpath = readInput(message, default=paths.ORACLE_DEFAULT_PASSWD) - - else: - message = "what's the dictionary's location? [%s]" % paths.WORDLIST - dictpath = readInput(message, default=paths.WORDLIST) - - checkFile(dictpath) - - infoMsg = "loading dictionary from: '%s'" % dictpath - logger.info(infoMsg) - kb.wordlist = getFileItems(dictpath, None, False) - - message = "do you want to use common password suffixes? (slow!) [y/N] " - test = readInput(message, default="N") - - suffix_list = [""] - if test[0] in ("y", "Y"): - suffix_list += COMMON_PASSWORD_SUFFIXES - - infoMsg = "starting dictionary attack (%s)" % __functions__[hash_regex].func_name - logger.info(infoMsg) - - for item in attack_info: - ((user, _), _) = item - kb.wordlist.append(getUnicode(user)) - - length = len(kb.wordlist) * len(suffix_list) - - if hash_regex in (HASH.MYSQL, HASH.MYSQL_OLD, HASH.MD5_GENERIC, HASH.SHA1_GENERIC): - count = 0 - - for suffix in suffix_list: - if not attack_info: - break - - for word in kb.wordlist: - if not attack_info: - break - - count += 1 - - if suffix: - word = word + suffix - - try: - current = __functions__[hash_regex](password = word, uppercase = False) - - for item in attack_info: - ((user, hash_), _) = item - - if hash_ == current: - results.append((user, hash_, word)) - clearConsoleLine() - - infoMsg = "[%s] [INFO] found: '%s'" % (time.strftime("%X"), word) - - if user and not user.startswith(DUMMY_USER_PREFIX): - infoMsg += " for user: '%s'\n" % user - else: - infoMsg += " for hash: '%s'\n" % hash_ - - dataToStdout(infoMsg, True) - - attack_info.remove(item) - - elif count % 1117 == 0 or count == length or hash_regex in (HASH.ORACLE_OLD): - status = '%d/%d words (%d%s)' % (count, length, round(100.0*count/length), '%') - dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status)) - - except KeyboardInterrupt: - raise - - except: - warnMsg = "there was a problem while hashing entry: %s. " % repr(word) - warnMsg += "Please report by e-mail to sqlmap-users@lists.sourceforge.net." - logger.critical(warnMsg) - - clearConsoleLine() - - else: - for ((user, hash_), kwargs) in attack_info: - count = 0 - found = False - - for suffix in suffix_list: - if found: - break - - for word in kb.wordlist: - current = __functions__[hash_regex](password = word, uppercase = False, **kwargs) - count += 1 - - if suffix: - word = word + suffix - - try: - if hash_ == current: - if regex == HASH.ORACLE_OLD: #only for cosmetic purposes - word = word.upper() - results.append((user, hash_, word)) - clearConsoleLine() - - infoMsg = "[%s] [INFO] found: '%s'" % (time.strftime("%X"), word) - - if user and not user.startswith(DUMMY_USER_PREFIX): - infoMsg += " for user: '%s'\n" % user - else: - infoMsg += " for hash: '%s'\n" % hash_ - - dataToStdout(infoMsg, True) - - found = True - break - - elif count % 1117 == 0 or count == length or hash_regex in (HASH.ORACLE_OLD): - status = '%d/%d words (%d%s) (user: %s)' % (count, length, round(100.0*count/length), '%', user) - dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status)) - - except KeyboardInterrupt: - raise - - except: - warnMsg = "there was a problem while hashing entry: %s. " % repr(word) - warnMsg += "Please report by e-mail to sqlmap-users@lists.sourceforge.net." - logger.critical(warnMsg) - - clearConsoleLine() - - if len(hash_regexes) == 0: - warnMsg = "unknown hash Format. " - warnMsg += "Please report by e-mail to sqlmap-users@lists.sourceforge.net." - logger.warn(warnMsg) - - if len(results) == 0: - warnMsg = "no clear password(s) found" - logger.warn(warnMsg) - - return results +#!/usr/bin/env python + +""" +$Id$ + +Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) +See the file 'doc/COPYING' for copying permission +""" + +import re +import time + +from hashlib import md5 +from hashlib import sha1 +from zipfile import ZipFile + +from extra.pydes.pyDes import des +from extra.pydes.pyDes import CBC +from lib.core.common import checkFile +from lib.core.common import clearConsoleLine +from lib.core.common import dataToStdout +from lib.core.common import getCompiledRegex +from lib.core.common import getFileItems +from lib.core.common import Backend +from lib.core.common import getPublicTypeMembers +from lib.core.common import getUnicode +from lib.core.common import paths +from lib.core.common import readInput +from lib.core.convert import hexdecode +from lib.core.convert import hexencode +from lib.core.data import kb +from lib.core.data import logger +from lib.core.enums import DBMS +from lib.core.enums import HASH +from lib.core.exception import sqlmapUserQuitException +from lib.core.settings import COMMON_PASSWORD_SUFFIXES +from lib.core.settings import DUMMY_USER_PREFIX +from lib.core.settings import UNICODE_ENCODING + +def mysql_passwd(password, uppercase=True): + """ + Reference(s): + http://csl.sublevel3.org/mysql-password-function/ + + >>> mysql_passwd(password='testpass', uppercase=True) + '*00E247AC5F9AF26AE0194B41E1E769DEE1429A29' + """ + + retVal = "*%s" % sha1(sha1(password).digest()).hexdigest() + + return retVal.upper() if uppercase else retVal.lower() + +def mysql_old_passwd(password, uppercase=True): # prior to version '4.1' + """ + Reference(s): + http://www.sfr-fresh.com/unix/privat/tpop3d-1.5.5.tar.gz:a/tpop3d-1.5.5/password.c + http://voidnetwork.org/5ynL0rd/darkc0de/python_script/darkMySQLi.html + + >>> mysql_old_passwd(password='testpass', uppercase=True) + '7DCDA0D57290B453' + """ + + a, b, c = 1345345333, 7, 0x12345671 + + for d in password: + if d == ' ' or d == '\t': + continue + + e = ord(d) + a ^= (((a & 63) + b) * e) + (a << 8) + c += (c << 8) ^ a + b += e + + retVal = "%08lx%08lx" % (a & ((1 << 31) - 1), c & ((1 << 31) - 1)) + + return retVal.upper() if uppercase else retVal.lower() + +def postgres_passwd(password, username, uppercase=False): + """ + Reference(s): + http://pentestmonkey.net/blog/cracking-postgres-hashes/ + + >>> postgres_passwd(password='testpass', username='testuser', uppercase=False) + 'md599e5ea7a6f7c3269995cba3927fd0093' + """ + + retVal = "md5%s" % md5(password + username).hexdigest() + + return retVal.upper() if uppercase else retVal.lower() + +def mssql_passwd(password, salt, uppercase=False): + """ + Reference(s): + http://www.leidecker.info/projects/phrasendrescher/mssql.c + https://www.evilfingers.com/tools/GSAuditor.php + + >>> mssql_passwd(password='testpass', salt='4086ceb6', uppercase=False) + '0x01004086ceb60c90646a8ab9889fe3ed8e5c150b5460ece8425a' + """ + + binsalt = hexdecode(salt) + unistr = "".join("%s\0" % c for c in password) + + retVal = "0100%s%s" % (salt, sha1(unistr + binsalt).hexdigest()) + + return "0x%s" % (retVal.upper() if uppercase else retVal.lower()) + +def mssql_old_passwd(password, salt, uppercase=True): # prior to version '2005' + """ + Reference(s): + www.exploit-db.com/download_pdf/15537/ + http://www.leidecker.info/projects/phrasendrescher/mssql.c + https://www.evilfingers.com/tools/GSAuditor.php + + >>> mssql_old_passwd(password='testpass', salt='4086ceb6', uppercase=True) + '0x01004086CEB60C90646A8AB9889FE3ED8E5C150B5460ECE8425AC7BB7255C0C81D79AA5D0E93D4BB077FB9A51DA0' + """ + + binsalt = hexdecode(salt) + unistr = "".join("%s\0" % c for c in password) + + retVal = "0100%s%s%s" % (salt, sha1(unistr + binsalt).hexdigest(), sha1(unistr.upper() + binsalt).hexdigest()) + + return "0x%s" % (retVal.upper() if uppercase else retVal.lower()) + +def oracle_passwd(password, salt, uppercase=True): + """ + Reference(s): + https://www.evilfingers.com/tools/GSAuditor.php + http://www.notesbit.com/index.php/scripts-oracle/oracle-11g-new-password-algorithm-is-revealed-by-seclistsorg/ + http://seclists.org/bugtraq/2007/Sep/304 + + >>> oracle_passwd(password='SHAlala', salt='1B7B5F82B7235E9E182C', uppercase=True) + 'S:2BFCFDF5895014EE9BB2B9BA067B01E0389BB5711B7B5F82B7235E9E182C' + """ + + binsalt = hexdecode(salt) + + retVal="s:%s%s" % (sha1(password + binsalt).hexdigest(), salt) + + return retVal.upper() if uppercase else retVal.lower() + +def oracle_old_passwd(password, username, uppercase=True): # prior to version '11g' + """ + Reference(s): + http://www.notesbit.com/index.php/scripts-oracle/oracle-11g-new-password-algorithm-is-revealed-by-seclistsorg/ + + >>> oracle_old_passwd(password='tiger', username='scott', uppercase=True) + 'F894844C34402B67' + """ + IV, pad = "\0"*8, "\0" + + if isinstance(username, unicode): + username = unicode.encode(username, UNICODE_ENCODING) #pyDes has issues with unicode strings + + unistr = "".join("\0%s" % c for c in (username + password).upper()) + + cipher = des(hexdecode("0123456789ABCDEF"), CBC, IV, pad) + encrypted = cipher.encrypt(unistr) + cipher = des(encrypted[-8:], CBC, IV, pad) + encrypted = cipher.encrypt(unistr) + + retVal = hexencode(encrypted[-8:]) + + return retVal.upper() if uppercase else retVal.lower() + +def md5_generic_passwd(password, uppercase=False): + """ + >>> md5_generic_passwd(password='testpass', uppercase=False) + '179ad45c6ce2cb97cf1029e212046e81' + """ + + retVal = md5(password).hexdigest() + + return retVal.upper() if uppercase else retVal.lower() + +def sha1_generic_passwd(password, uppercase=False): + """ + >>> sha1_generic_passwd(password='testpass', uppercase=False) + '206c80413b9a96c1312cc346b7d2517b84463edd' + """ + + retVal = sha1(password).hexdigest() + + return retVal.upper() if uppercase else retVal.lower() + +__functions__ = { + HASH.MYSQL: mysql_passwd, + HASH.MYSQL_OLD: mysql_old_passwd, + HASH.POSTGRES: postgres_passwd, + HASH.MSSQL: mssql_passwd, + HASH.MSSQL_OLD: mssql_old_passwd, + HASH.ORACLE: oracle_passwd, + HASH.ORACLE_OLD: oracle_old_passwd, + HASH.MD5_GENERIC: md5_generic_passwd, + HASH.SHA1_GENERIC: sha1_generic_passwd + } + +def attackCachedUsersPasswords(): + if kb.data.cachedUsersPasswords: + results = dictionaryAttack(kb.data.cachedUsersPasswords) + + for (user, hash_, password) in results: + for i in xrange(len(kb.data.cachedUsersPasswords[user])): + if kb.data.cachedUsersPasswords[user][i] and hash_.lower() in kb.data.cachedUsersPasswords[user][i].lower(): + kb.data.cachedUsersPasswords[user][i] += "%s clear-text password: %s" % ('\n' if kb.data.cachedUsersPasswords[user][i][-1] != '\n' else '', password) + +def attackDumpedTable(): + if kb.data.dumpedTable: + table = kb.data.dumpedTable + columns = table.keys() + count = table["__infos__"]["count"] + + colUser = '' + attack_dict = {} + + for column in columns: + if column and column.lower() in ('user', 'username', 'user_name'): + colUser = column + break + + for i in range(count): + for column in columns: + if column == colUser or column == '__infos__': + continue + + if len(table[column]['values']) <= i: + continue + + value = table[column]['values'][i] + + if hashRecognition(value): + if colUser: + if table[colUser]['values'][i] not in attack_dict: + attack_dict[table[colUser]['values'][i]] = [] + + attack_dict[table[colUser]['values'][i]].append(value) + else: + attack_dict['%s%d' % (DUMMY_USER_PREFIX, i)] = [value] + + if attack_dict: + message = "recognized possible password hash values. " + message += "do you want to use dictionary attack on retrieved table items? [Y/n/q]" + test = readInput(message, default="Y") + + if test[0] in ("n", "N"): + return + elif test[0] in ("q", "Q"): + raise sqlmapUserQuitException + + results = dictionaryAttack(attack_dict) + + for (user, hash_, password) in results: + for i in range(count): + for column in columns: + if column == colUser or column == '__infos__': + continue + if len(table[column]['values']) <= i: + continue + + value = table[column]['values'][i] + + if value.lower() == hash_.lower(): + table[column]['values'][i] += " (%s)" % password + table[column]['length'] = max(table[column]['length'], len(table[column]['values'][i])) + +def hashRecognition(value): + retVal = None + + if value: + for name, regex in getPublicTypeMembers(HASH): + # Hashes for Oracle and old MySQL look the same hence these checks + if Backend.getIdentifiedDbms() == DBMS.ORACLE and regex == HASH.MYSQL_OLD: + continue + elif Backend.getIdentifiedDbms() == DBMS.MYSQL and regex == HASH.ORACLE_OLD: + continue + elif getCompiledRegex(regex).match(value): + retVal = regex + break + + return retVal + +def dictionaryAttack(attack_dict): + hash_regexes = [] + results = [] + + for (_, hashes) in attack_dict.items(): + for hash_ in hashes: + if not hash_: + continue + + hash_ = hash_.split()[0] + regex = hashRecognition(hash_) + + if regex and regex not in hash_regexes: + hash_regexes.append(regex) + infoMsg = "using hash method: '%s'" % __functions__[regex].func_name + logger.info(infoMsg) + + for hash_regex in hash_regexes: + attack_info = [] + + for (user, hashes) in attack_dict.items(): + for hash_ in hashes: + if not hash_: + continue + + hash_ = hash_.split()[0] + + if re.match(hash_regex, hash_): + hash_ = hash_.lower() + + if hash_regex in (HASH.MYSQL, HASH.MYSQL_OLD, HASH.MD5_GENERIC, HASH.SHA1_GENERIC): + attack_info.append([(user, hash_), {}]) + + elif hash_regex in (HASH.ORACLE_OLD, HASH.POSTGRES): + attack_info.append([(user, hash_), {'username': user}]) + + elif hash_regex in (HASH.ORACLE): + attack_info.append([(user, hash_), {'salt': hash_[-20:]}]) + + elif hash_regex in (HASH.MSSQL, HASH.MSSQL_OLD): + attack_info.append([(user, hash_), {'salt': hash_[6:14]}]) + + if not kb.wordlist: + if hash_regex == HASH.ORACLE_OLD: #it's the slowest of all methods hence smaller default dict + message = "what's the dictionary's location? [%s]" % paths.ORACLE_DEFAULT_PASSWD + dictpath = readInput(message, default=paths.ORACLE_DEFAULT_PASSWD) + + else: + message = "what's the dictionary's location? [%s]" % paths.WORDLIST + dictpath = readInput(message, default=paths.WORDLIST) + + checkFile(dictpath) + + infoMsg = "loading dictionary from: '%s'" % dictpath + logger.info(infoMsg) + kb.wordlist = getFileItems(dictpath, None, False) + + message = "do you want to use common password suffixes? (slow!) [y/N] " + test = readInput(message, default="N") + + suffix_list = [""] + if test[0] in ("y", "Y"): + suffix_list += COMMON_PASSWORD_SUFFIXES + + infoMsg = "starting dictionary attack (%s)" % __functions__[hash_regex].func_name + logger.info(infoMsg) + + for item in attack_info: + ((user, _), _) = item + kb.wordlist.append(getUnicode(user)) + + length = len(kb.wordlist) * len(suffix_list) + + if hash_regex in (HASH.MYSQL, HASH.MYSQL_OLD, HASH.MD5_GENERIC, HASH.SHA1_GENERIC): + count = 0 + + for suffix in suffix_list: + if not attack_info: + break + + for word in kb.wordlist: + if not attack_info: + break + + count += 1 + + if suffix: + word = word + suffix + + try: + current = __functions__[hash_regex](password = word, uppercase = False) + + for item in attack_info: + ((user, hash_), _) = item + + if hash_ == current: + results.append((user, hash_, word)) + clearConsoleLine() + + infoMsg = "[%s] [INFO] found: '%s'" % (time.strftime("%X"), word) + + if user and not user.startswith(DUMMY_USER_PREFIX): + infoMsg += " for user: '%s'\n" % user + else: + infoMsg += " for hash: '%s'\n" % hash_ + + dataToStdout(infoMsg, True) + + attack_info.remove(item) + + elif count % 1117 == 0 or count == length or hash_regex in (HASH.ORACLE_OLD): + status = '%d/%d words (%d%s)' % (count, length, round(100.0*count/length), '%') + dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status)) + + except KeyboardInterrupt: + raise + + except: + warnMsg = "there was a problem while hashing entry: %s. " % repr(word) + warnMsg += "Please report by e-mail to sqlmap-users@lists.sourceforge.net." + logger.critical(warnMsg) + + clearConsoleLine() + + else: + for ((user, hash_), kwargs) in attack_info: + count = 0 + found = False + + for suffix in suffix_list: + if found: + break + + for word in kb.wordlist: + current = __functions__[hash_regex](password = word, uppercase = False, **kwargs) + count += 1 + + if suffix: + word = word + suffix + + try: + if hash_ == current: + if regex == HASH.ORACLE_OLD: #only for cosmetic purposes + word = word.upper() + results.append((user, hash_, word)) + clearConsoleLine() + + infoMsg = "[%s] [INFO] found: '%s'" % (time.strftime("%X"), word) + + if user and not user.startswith(DUMMY_USER_PREFIX): + infoMsg += " for user: '%s'\n" % user + else: + infoMsg += " for hash: '%s'\n" % hash_ + + dataToStdout(infoMsg, True) + + found = True + break + + elif count % 1117 == 0 or count == length or hash_regex in (HASH.ORACLE_OLD): + status = '%d/%d words (%d%s) (user: %s)' % (count, length, round(100.0*count/length), '%', user) + dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status)) + + except KeyboardInterrupt: + raise + + except: + warnMsg = "there was a problem while hashing entry: %s. " % repr(word) + warnMsg += "Please report by e-mail to sqlmap-users@lists.sourceforge.net." + logger.critical(warnMsg) + + clearConsoleLine() + + if len(hash_regexes) == 0: + warnMsg = "unknown hash Format. " + warnMsg += "Please report by e-mail to sqlmap-users@lists.sourceforge.net." + logger.warn(warnMsg) + + if len(results) == 0: + warnMsg = "no clear password(s) found" + logger.warn(warnMsg) + + return results diff --git a/tamper/between.py b/tamper/between.py index 0d1eef357..89c97f902 100644 --- a/tamper/between.py +++ b/tamper/between.py @@ -1,49 +1,49 @@ -#!/usr/bin/env python - -""" -$Id$ - -Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) -See the file 'doc/COPYING' for copying permission -""" - -from lib.core.enums import PRIORITY - -__priority__ = PRIORITY.HIGHEST - -def tamper(value): - """ - Replaces '>' with 'NOT BETWEEN 0 AND #' - Example: 'A > B' becomes 'A NOT BETWEEN 0 AND B' - """ - - retVal = value - - if value: - retVal = "" - quote, doublequote, firstspace = False, False, False - - for i in xrange(len(value)): - if not firstspace: - if value[i].isspace(): - firstspace = True - retVal += " " - continue - - elif value[i] == '\'': - quote = not quote - - elif value[i] == '"': - doublequote = not doublequote - - elif value[i] == ">" and not doublequote and not quote: - retVal += " " if i > 0 and not value[i-1].isspace() else "" - retVal += "NOT BETWEEN 0 AND" - retVal += " " if i < len(value) - 1 and not value[i+1].isspace() else "" - - continue - - retVal += value[i] - - return retVal - +#!/usr/bin/env python + +""" +$Id$ + +Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) +See the file 'doc/COPYING' for copying permission +""" + +from lib.core.enums import PRIORITY + +__priority__ = PRIORITY.HIGHEST + +def tamper(value): + """ + Replaces '>' with 'NOT BETWEEN 0 AND #' + Example: 'A > B' becomes 'A NOT BETWEEN 0 AND B' + """ + + retVal = value + + if value: + retVal = "" + quote, doublequote, firstspace = False, False, False + + for i in xrange(len(value)): + if not firstspace: + if value[i].isspace(): + firstspace = True + retVal += " " + continue + + elif value[i] == '\'': + quote = not quote + + elif value[i] == '"': + doublequote = not doublequote + + elif value[i] == ">" and not doublequote and not quote: + retVal += " " if i > 0 and not value[i-1].isspace() else "" + retVal += "NOT BETWEEN 0 AND" + retVal += " " if i < len(value) - 1 and not value[i+1].isspace() else "" + + continue + + retVal += value[i] + + return retVal + diff --git a/tamper/charencode.py b/tamper/charencode.py index f90c1a206..8f1390a60 100644 --- a/tamper/charencode.py +++ b/tamper/charencode.py @@ -1,37 +1,37 @@ -#!/usr/bin/env python - -""" -$Id$ - -Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) -See the file 'doc/COPYING' for copying permission -""" - -import string - -from lib.core.enums import PRIORITY -from lib.core.exception import sqlmapUnsupportedFeatureException - -__priority__ = PRIORITY.LOWEST - -def tamper(value): - """ - Replaces value with urlencode of non-encoded chars in value - Example: 'SELECT%20FIELD%20FROM%20TABLE' becomes '%53%45%4c%45%43%54%20%46%49%45%4c%44%20%46%52%4f%4d%20%54%41%42%4c%45' - """ - - retVal = value - - if value: - retVal = "" - i = 0 - - while i < len(value): - if value[i] == '%' and (i < len(value) - 2) and value[i+1] in string.hexdigits and value[i+2] in string.hexdigits: - retVal += value[i:i+3] - i += 3 - else: - retVal += '%%%X' % ord(value[i]) - i += 1 - - return retVal +#!/usr/bin/env python + +""" +$Id$ + +Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) +See the file 'doc/COPYING' for copying permission +""" + +import string + +from lib.core.enums import PRIORITY +from lib.core.exception import sqlmapUnsupportedFeatureException + +__priority__ = PRIORITY.LOWEST + +def tamper(value): + """ + Replaces value with urlencode of non-encoded chars in value + Example: 'SELECT%20FIELD%20FROM%20TABLE' becomes '%53%45%4c%45%43%54%20%46%49%45%4c%44%20%46%52%4f%4d%20%54%41%42%4c%45' + """ + + retVal = value + + if value: + retVal = "" + i = 0 + + while i < len(value): + if value[i] == '%' and (i < len(value) - 2) and value[i+1] in string.hexdigits and value[i+2] in string.hexdigits: + retVal += value[i:i+3] + i += 3 + else: + retVal += '%%%X' % ord(value[i]) + i += 1 + + return retVal diff --git a/tamper/charunicodeencode.py b/tamper/charunicodeencode.py index d316e8a7d..9d3c11b2d 100644 --- a/tamper/charunicodeencode.py +++ b/tamper/charunicodeencode.py @@ -1,37 +1,37 @@ -#!/usr/bin/env python - -""" -$Id$ - -Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) -See the file 'doc/COPYING' for copying permission -""" - -import string - -from lib.core.enums import PRIORITY -from lib.core.exception import sqlmapUnsupportedFeatureException - -__priority__ = PRIORITY.LOWEST - -def tamper(value): - """ - Replaces value with unicode-urlencode of non-encoded chars in value - Example: 'SELECT%20FIELD%20FROM%20TABLE' becomes '%u0053%u0045%u004c%u0045%u0043%u0054%u0020%u0046%u0049%u0045%u004c%u0044%u0020%u0046%u0052%u004f%u004d%u0020%u0054%u0041%u0042%u004c%u0045' - """ - - retVal = value - - if value: - retVal = "" - i = 0 - - while i < len(value): - if value[i] == '%' and (i < len(value) - 2) and value[i+1] in string.hexdigits and value[i+2] in string.hexdigits: - retVal += "%%u00%s" % value[i+1:i+3] - i += 3 - else: - retVal += '%%u00%X' % ord(value[i]) - i += 1 - - return retVal +#!/usr/bin/env python + +""" +$Id$ + +Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) +See the file 'doc/COPYING' for copying permission +""" + +import string + +from lib.core.enums import PRIORITY +from lib.core.exception import sqlmapUnsupportedFeatureException + +__priority__ = PRIORITY.LOWEST + +def tamper(value): + """ + Replaces value with unicode-urlencode of non-encoded chars in value + Example: 'SELECT%20FIELD%20FROM%20TABLE' becomes '%u0053%u0045%u004c%u0045%u0043%u0054%u0020%u0046%u0049%u0045%u004c%u0044%u0020%u0046%u0052%u004f%u004d%u0020%u0054%u0041%u0042%u004c%u0045' + """ + + retVal = value + + if value: + retVal = "" + i = 0 + + while i < len(value): + if value[i] == '%' and (i < len(value) - 2) and value[i+1] in string.hexdigits and value[i+2] in string.hexdigits: + retVal += "%%u00%s" % value[i+1:i+3] + i += 3 + else: + retVal += '%%u00%X' % ord(value[i]) + i += 1 + + return retVal diff --git a/tamper/ifnull2ifisnull.py b/tamper/ifnull2ifisnull.py index 7b4e752f5..0d549a4e9 100644 --- a/tamper/ifnull2ifisnull.py +++ b/tamper/ifnull2ifisnull.py @@ -1,49 +1,49 @@ -#!/usr/bin/env python - -""" -$Id$ - -Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) -See the file 'doc/COPYING' for copying permission -""" - -from lib.core.enums import PRIORITY - -__priority__ = PRIORITY.HIGHEST - -def tamper(value): - """ - Replaces 'IFNULL(A, B)' with 'IF(ISNULL(A), B, A)' - Example: 'IFNULL(1, 2)' becomes 'IF(ISNULL(1), 2, 1)' - """ - - if value and value.find("IFNULL") > -1: - - while value.find("IFNULL(") > -1: - index = value.find("IFNULL(") - deepness = 1 - comma, end = None, None - - for i in xrange(index + len("IFNULL("), len(value)): - if deepness == 1 and value[i] == ',': - comma = i - - elif deepness == 1 and value[i] == ')': - end = i - break - - elif value[i] == '(': - deepness += 1 - - elif value[i] == ')': - deepness -= 1 - - if comma and end: - A = value[index + len("IFNULL("):comma] - B = value[comma + 1:end] - newVal = "IF(ISNULL(%s),%s,%s)" % (A, B, A) - value = value[:index] + newVal + value[end+1:] - else: - break - - return value +#!/usr/bin/env python + +""" +$Id$ + +Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) +See the file 'doc/COPYING' for copying permission +""" + +from lib.core.enums import PRIORITY + +__priority__ = PRIORITY.HIGHEST + +def tamper(value): + """ + Replaces 'IFNULL(A, B)' with 'IF(ISNULL(A), B, A)' + Example: 'IFNULL(1, 2)' becomes 'IF(ISNULL(1), 2, 1)' + """ + + if value and value.find("IFNULL") > -1: + + while value.find("IFNULL(") > -1: + index = value.find("IFNULL(") + deepness = 1 + comma, end = None, None + + for i in xrange(index + len("IFNULL("), len(value)): + if deepness == 1 and value[i] == ',': + comma = i + + elif deepness == 1 and value[i] == ')': + end = i + break + + elif value[i] == '(': + deepness += 1 + + elif value[i] == ')': + deepness -= 1 + + if comma and end: + A = value[index + len("IFNULL("):comma] + B = value[comma + 1:end] + newVal = "IF(ISNULL(%s),%s,%s)" % (A, B, A) + value = value[:index] + newVal + value[end+1:] + else: + break + + return value diff --git a/tamper/randomcase.py b/tamper/randomcase.py index 67193db60..cca53a6c7 100644 --- a/tamper/randomcase.py +++ b/tamper/randomcase.py @@ -1,38 +1,38 @@ -#!/usr/bin/env python - -""" -$Id$ - -Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) -See the file 'doc/COPYING' for copying permission -""" - -import re - -from lib.core.common import randomRange -from lib.core.data import kb -from lib.core.enums import PRIORITY - -__priority__ = PRIORITY.NORMAL - -def tamper(value): - """ - Replaces each character with random case value - Example: 'INSERT' might become 'InsERt' - """ - - retVal = value - - if value: - for match in re.finditer(r"[A-Za-z_]+", retVal): - word = match.group() - - if word.upper() in kb.keywords: - newWord = str() - - for i in xrange(len(word)): - newWord += word[i].upper() if randomRange(0, 1) else word[i].lower() - - retVal = retVal.replace(word, newWord) - - return retVal +#!/usr/bin/env python + +""" +$Id$ + +Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) +See the file 'doc/COPYING' for copying permission +""" + +import re + +from lib.core.common import randomRange +from lib.core.data import kb +from lib.core.enums import PRIORITY + +__priority__ = PRIORITY.NORMAL + +def tamper(value): + """ + Replaces each character with random case value + Example: 'INSERT' might become 'InsERt' + """ + + retVal = value + + if value: + for match in re.finditer(r"[A-Za-z_]+", retVal): + word = match.group() + + if word.upper() in kb.keywords: + newWord = str() + + for i in xrange(len(word)): + newWord += word[i].upper() if randomRange(0, 1) else word[i].lower() + + retVal = retVal.replace(word, newWord) + + return retVal diff --git a/tamper/randomcomments.py b/tamper/randomcomments.py index 8057dc3d6..7c8cf3d46 100644 --- a/tamper/randomcomments.py +++ b/tamper/randomcomments.py @@ -1,42 +1,42 @@ -#!/usr/bin/env python - -""" -$Id$ - -Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) -See the file 'doc/COPYING' for copying permission -""" - -import re - -from lib.core.common import randomRange -from lib.core.data import kb -from lib.core.enums import PRIORITY - -__priority__ = PRIORITY.LOW - -def tamper(value): - """ - Add random comments to SQL keywords in value - Example: 'INSERT' becomes 'IN/**/S/**/ERT' - """ - - retVal = value - - if value: - for match in re.finditer(r"[A-Za-z_]+", retVal): - word = match.group() - - if len(word) < 2: - continue - - if word.upper() in kb.keywords: - newWord = word[0] - - for i in xrange(1, len(word) - 1): - newWord += "%s%s" % ("/**/" if randomRange(0, 1) else "", word[i]) - - newWord += word[-1] - retVal = retVal.replace(word, newWord) - - return retVal +#!/usr/bin/env python + +""" +$Id$ + +Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) +See the file 'doc/COPYING' for copying permission +""" + +import re + +from lib.core.common import randomRange +from lib.core.data import kb +from lib.core.enums import PRIORITY + +__priority__ = PRIORITY.LOW + +def tamper(value): + """ + Add random comments to SQL keywords in value + Example: 'INSERT' becomes 'IN/**/S/**/ERT' + """ + + retVal = value + + if value: + for match in re.finditer(r"[A-Za-z_]+", retVal): + word = match.group() + + if len(word) < 2: + continue + + if word.upper() in kb.keywords: + newWord = word[0] + + for i in xrange(1, len(word) - 1): + newWord += "%s%s" % ("/**/" if randomRange(0, 1) else "", word[i]) + + newWord += word[-1] + retVal = retVal.replace(word, newWord) + + return retVal diff --git a/tamper/space2comment.py b/tamper/space2comment.py index 11bb23309..a6cd85ca4 100644 --- a/tamper/space2comment.py +++ b/tamper/space2comment.py @@ -1,46 +1,46 @@ -#!/usr/bin/env python - -""" -$Id$ - -Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) -See the file 'doc/COPYING' for copying permission -""" - -from lib.core.enums import PRIORITY - -__priority__ = PRIORITY.LOW - -def tamper(value): - """ - Replaces ' ' with '/**/' - Example: 'SELECT id FROM users' becomes 'SELECT/**/id/**/FROM/**/users' - """ - - retVal = value - - if value: - retVal = "" - quote, doublequote, firstspace = False, False, False - - for i in xrange(len(value)): - if not firstspace: - if value[i].isspace(): - firstspace = True - retVal += "/**/" - continue - - elif value[i] == '\'': - quote = not quote - - elif value[i] == '"': - doublequote = not doublequote - - elif value[i]==" " and not doublequote and not quote: - retVal += "/**/" - continue - - retVal += value[i] - - return retVal - +#!/usr/bin/env python + +""" +$Id$ + +Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) +See the file 'doc/COPYING' for copying permission +""" + +from lib.core.enums import PRIORITY + +__priority__ = PRIORITY.LOW + +def tamper(value): + """ + Replaces ' ' with '/**/' + Example: 'SELECT id FROM users' becomes 'SELECT/**/id/**/FROM/**/users' + """ + + retVal = value + + if value: + retVal = "" + quote, doublequote, firstspace = False, False, False + + for i in xrange(len(value)): + if not firstspace: + if value[i].isspace(): + firstspace = True + retVal += "/**/" + continue + + elif value[i] == '\'': + quote = not quote + + elif value[i] == '"': + doublequote = not doublequote + + elif value[i]==" " and not doublequote and not quote: + retVal += "/**/" + continue + + retVal += value[i] + + return retVal + diff --git a/tamper/space2plus.py b/tamper/space2plus.py index 9e84d1ba1..f25bf8bd2 100644 --- a/tamper/space2plus.py +++ b/tamper/space2plus.py @@ -1,46 +1,46 @@ -#!/usr/bin/env python - -""" -$Id$ - -Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) -See the file 'doc/COPYING' for copying permission -""" - -from lib.core.enums import PRIORITY - -__priority__ = PRIORITY.LOW - -def tamper(value): - """ - Replaces ' ' with '+' - Example: 'SELECT id FROM users' becomes 'SELECT+id+FROM+users' - """ - - retVal = value - - if value: - retVal = "" - quote, doublequote, firstspace = False, False, False - - for i in xrange(len(value)): - if not firstspace: - if value[i].isspace(): - firstspace = True - retVal += "+" - continue - - elif value[i] == '\'': - quote = not quote - - elif value[i] == '"': - doublequote = not doublequote - - elif value[i]==" " and not doublequote and not quote: - retVal += "+" - continue - - retVal += value[i] - - return retVal - +#!/usr/bin/env python + +""" +$Id$ + +Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) +See the file 'doc/COPYING' for copying permission +""" + +from lib.core.enums import PRIORITY + +__priority__ = PRIORITY.LOW + +def tamper(value): + """ + Replaces ' ' with '+' + Example: 'SELECT id FROM users' becomes 'SELECT+id+FROM+users' + """ + + retVal = value + + if value: + retVal = "" + quote, doublequote, firstspace = False, False, False + + for i in xrange(len(value)): + if not firstspace: + if value[i].isspace(): + firstspace = True + retVal += "+" + continue + + elif value[i] == '\'': + quote = not quote + + elif value[i] == '"': + doublequote = not doublequote + + elif value[i]==" " and not doublequote and not quote: + retVal += "+" + continue + + retVal += value[i] + + return retVal + diff --git a/tamper/space2randomblank.py b/tamper/space2randomblank.py index 6a5bf1684..a41b664cb 100644 --- a/tamper/space2randomblank.py +++ b/tamper/space2randomblank.py @@ -1,49 +1,49 @@ -#!/usr/bin/env python - -""" -$Id$ - -Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) -See the file 'doc/COPYING' for copying permission -""" - -import random - -from lib.core.enums import PRIORITY - -__priority__ = PRIORITY.LOW - -def tamper(value): - """ - Replaces ' ' with a random blank char from a set ('\r', '\n', '\t') - Example: 'SELECT id FROM users' becomes 'SELECT\rid\tFROM\nusers' - """ - - blanks = ['\r', '\n', '\t'] - retVal = value - - if value: - retVal = "" - quote, doublequote, firstspace = False, False, False - - for i in xrange(len(value)): - if not firstspace: - if value[i].isspace(): - firstspace = True - retVal += random.choice(blanks) - continue - - elif value[i] == '\'': - quote = not quote - - elif value[i] == '"': - doublequote = not doublequote - - elif value[i]==" " and not doublequote and not quote: - retVal += random.choice(blanks) - continue - - retVal += value[i] - - return retVal - +#!/usr/bin/env python + +""" +$Id$ + +Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) +See the file 'doc/COPYING' for copying permission +""" + +import random + +from lib.core.enums import PRIORITY + +__priority__ = PRIORITY.LOW + +def tamper(value): + """ + Replaces ' ' with a random blank char from a set ('\r', '\n', '\t') + Example: 'SELECT id FROM users' becomes 'SELECT\rid\tFROM\nusers' + """ + + blanks = ['\r', '\n', '\t'] + retVal = value + + if value: + retVal = "" + quote, doublequote, firstspace = False, False, False + + for i in xrange(len(value)): + if not firstspace: + if value[i].isspace(): + firstspace = True + retVal += random.choice(blanks) + continue + + elif value[i] == '\'': + quote = not quote + + elif value[i] == '"': + doublequote = not doublequote + + elif value[i]==" " and not doublequote and not quote: + retVal += random.choice(blanks) + continue + + retVal += value[i] + + return retVal + diff --git a/tamper/urlencode.py b/tamper/urlencode.py index 2e0d3db01..eaf6cbbb9 100644 --- a/tamper/urlencode.py +++ b/tamper/urlencode.py @@ -1,25 +1,25 @@ -#!/usr/bin/env python - -""" -$Id$ - -Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) -See the file 'doc/COPYING' for copying permission -""" - -from lib.core.convert import urlencode -from lib.core.enums import PRIORITY -from lib.core.exception import sqlmapUnsupportedFeatureException - -__priority__ = PRIORITY.LOWER - -def tamper(value): - """ - Replaces value with urlencode(value) - Example: 'SELECT FIELD FROM TABLE' becomes 'SELECT%20FIELD%20FROM%20TABLE' - """ - - if value: - value = urlencode(value, convall=True) - - return value +#!/usr/bin/env python + +""" +$Id$ + +Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) +See the file 'doc/COPYING' for copying permission +""" + +from lib.core.convert import urlencode +from lib.core.enums import PRIORITY +from lib.core.exception import sqlmapUnsupportedFeatureException + +__priority__ = PRIORITY.LOWER + +def tamper(value): + """ + Replaces value with urlencode(value) + Example: 'SELECT FIELD FROM TABLE' becomes 'SELECT%20FIELD%20FROM%20TABLE' + """ + + if value: + value = urlencode(value, convall=True) + + return value