Compare commits

..

79 Commits
1.1 ... 1.1.4

Author SHA1 Message Date
Miroslav Stampar
cfe34f61b8 Implementation for an Issue #1895 2017-04-06 11:33:59 +02:00
Miroslav Stampar
c1c7ea33fe Minor update 2017-03-30 12:05:05 +02:00
Miroslav Stampar
4458a443ef Fixes #1664 2017-03-30 11:58:03 +02:00
Miroslav Stampar
16bd3a1f02 Fixes #2453 2017-03-30 11:42:34 +02:00
Miroslav Stampar
a358bc0a38 Minor update 2017-03-30 10:24:57 +02:00
Miroslav Stampar
aebae6e27b Added (heuristic) support for #1679 2017-03-30 10:16:35 +02:00
Miroslav Stampar
0a3e771b1b Fixes #2449 2017-03-28 15:22:53 +02:00
Miroslav Stampar
f82c0497fa Fixes #2447 2017-03-27 22:36:04 +02:00
Miroslav Stampar
715763885d Fixes #2306 2017-03-24 14:20:18 +01:00
Miroslav Stampar
4aae5d9a9d Fixes #2444 2017-03-19 21:34:47 +01:00
Miroslav Stampar
1bc583d358 Another patch related to the #2440 2017-03-17 09:43:45 +01:00
Miroslav Stampar
e506a390db Minor patch (prevent message spamming of multiple union column possibilities) 2017-03-15 16:18:20 +01:00
Miroslav Stampar
c5b4af8636 Dummy commit (to provoke rehash) 2017-03-15 16:07:52 +01:00
Miroslav Stampar
c29e47f72f Fixes #2440 2017-03-15 16:04:56 +01:00
Miroslav Stampar
4087213501 Merge pull request #2439 from klensy/mysql-fingerprint-update
updated mysql version numbers
2017-03-14 21:15:44 +01:00
klensy
e4725366d3 updated mysql version numbers 2017-03-14 15:11:03 +03:00
Miroslav Stampar
60e8c725f9 Fixes #2437 2017-03-12 23:24:13 +01:00
Miroslav Stampar
5dba32b2e1 Fixes #2431 2017-03-12 09:52:37 +01:00
Miroslav Stampar
ef04c99069 No more dumb usage of '--dbms' 2017-03-06 12:53:04 +01:00
Miroslav Stampar
e2fb16c98c Fixes #2425 2017-03-06 12:05:58 +01:00
Miroslav Stampar
d2b16c5c91 Fixes #2422 2017-03-01 11:09:55 +01:00
Miroslav Stampar
9f0c42dde0 Minor leftover 2017-03-01 10:09:13 +01:00
Miroslav Stampar
78ca371162 Adding option --web-root (Issue #2419) 2017-03-01 10:07:26 +01:00
Miroslav Stampar
a35c976759 Proper implementation for an Issue #2418 2017-02-28 14:00:42 +01:00
Miroslav Stampar
89e9f4939d Merge pull request #2418 from Ekultek/ip_regex
IP address regex updated to not provide a false positive
2017-02-28 14:00:00 +01:00
Ekultek
71984fc452 updated IP address regex as to not provide false positive 2017-02-28 06:35:37 -06:00
Miroslav Stampar
a0a6702a4e Minor patch (reported via ML) 2017-02-28 13:16:19 +01:00
Miroslav Stampar
b18444f215 Issue #2417 (most probably -> most likely) 2017-02-27 22:14:52 +01:00
Miroslav Stampar
7ea524800a Taking couple of suggestions from #2417 2017-02-27 22:03:15 +01:00
Miroslav Stampar
7960045cf9 Fixes #2277 and #2300 2017-02-27 13:58:07 +01:00
Miroslav Stampar
d253a97a6f Merge pull request #2411 from bbbbbrie/master
Correct typo in basic.py
2017-02-27 12:55:59 +01:00
Brie Carranza
1475ba441c Correct typo in basic.py 2017-02-26 09:05:36 -05:00
Miroslav Stampar
b2585cc8ea Patch for #2410 2017-02-25 07:58:59 +01:00
Miroslav Stampar
7b263327cc Update for #2410 2017-02-25 07:54:54 +01:00
Miroslav Stampar
cd31bf4ecb Merge pull request #2410 from qnrq/patch-1
Adds option command to api client
2017-02-25 07:47:23 +01:00
Niklas Femerstrand
1b938c758f Adds option command to api client 2017-02-25 10:24:00 +07:00
Miroslav Stampar
5a08b71999 Minor update 2017-02-23 11:36:37 +01:00
Miroslav Stampar
4b420e7579 Removing Google PageRank as it is dead now 2017-02-23 11:33:39 +01:00
Miroslav Stampar
6b580a682a Minor update 2017-02-20 10:06:06 +01:00
Miroslav Stampar
d6e7c2acdc Minor touch 2017-02-19 01:48:12 +01:00
Miroslav Stampar
4d3aa1605c Merge pull request #2401 from tomahock/master
Fix proxyFile regex to properly match an address with a -
2017-02-19 01:31:12 +01:00
Tomahock
7fe1820ce4 Fix proxyFile regex to properly match an address with a - 2017-02-17 23:32:32 +00:00
Miroslav Stampar
98e449e38c Adding plus2fnconcat tamper script (Issue #2396) 2017-02-17 10:26:25 +01:00
Miroslav Stampar
9acf122ba6 Patch for an Issue #2396 2017-02-16 16:56:54 +01:00
Miroslav Stampar
2ed144ec85 Patch for wrong encoding reported privately via email 2017-02-16 15:52:07 +01:00
Miroslav Stampar
ec0c103952 Bug fix (reported privately) 2017-02-15 10:30:29 +01:00
Miroslav Stampar
a35d1e5373 Minor patch related to the email from ML 2017-02-14 13:14:35 +01:00
Miroslav Stampar
f5cf22a536 Update for an Issue #2377 2017-02-06 13:57:33 +01:00
Miroslav Stampar
38f16decef Update for an Issue #2384 2017-02-06 13:28:33 +01:00
Miroslav Stampar
15f86e85b1 Minor update for #2379 2017-02-06 12:03:18 +01:00
Miroslav Stampar
5217efc69b Fixes #2379 2017-02-06 12:01:46 +01:00
Miroslav Stampar
03bbf552ef Patch for an Issue #2382 2017-02-06 11:14:45 +01:00
Miroslav Stampar
664684ad8f Update for #2378 2017-02-03 23:04:38 +01:00
Miroslav Stampar
ddea0bf6e4 Merge pull request #2378 from samogot/patch-1
Minor parse-error extension
2017-02-03 22:56:05 +01:00
samogot
1c1f259df4 Update settings.py
fix - looking for any tag
2017-02-03 16:50:16 +02:00
samogot
6249823335 Minor parse-error extension
parse errors produced by Yii PHP Framework
2017-02-03 16:36:57 +02:00
Miroslav Stampar
bad3f80a1c Touch update 2017-01-31 14:18:36 +01:00
Miroslav Stampar
529089ba5b Merge pull request #2374 from anarcoder/space2morecomment
New space 2 more comment bypass
2017-01-31 14:16:53 +01:00
Miroslav Stampar
9851a5703a Fixes #2373 2017-01-31 14:00:12 +01:00
Daniel Almeida
aa9989ff90 [add] new space 2 more comment bypass 2017-01-31 10:50:14 -02:00
Miroslav Stampar
2a3014b606 Fixes #2367 2017-01-24 18:07:06 +01:00
Miroslav Stampar
16d5e22b72 Fixes #2358 2017-01-21 23:58:37 +01:00
Miroslav Stampar
a8a6dce38b Fixes #2366 2017-01-21 23:09:15 +01:00
Miroslav Stampar
f542e828d2 Fixes #2364 2017-01-20 13:11:12 +01:00
Miroslav Stampar
cf182882b1 Minor update 2017-01-18 10:40:39 +01:00
Miroslav Stampar
2224ac76aa Merge pull request #2359 from MyKings/master
Adding new WAF script(TencentCloud)
2017-01-18 10:36:39 +01:00
Miroslav Stampar
dd5ac6f1e7 Fixes #2357 2017-01-18 10:33:54 +01:00
Miroslav Stampar
1e7a453ff6 Fixes #2356 2017-01-18 10:19:23 +01:00
MyKings
8a84c252be Adding new WAF script(TencentCloud) 2017-01-18 16:11:03 +08:00
Miroslav Stampar
138aa6db65 Patch for an Issue #2351 2017-01-16 15:23:38 +01:00
Miroslav Stampar
121f0376ea Implementation for #2351 2017-01-16 14:29:23 +01:00
Miroslav Stampar
dfc684640a Proper implementation for #2347 2017-01-16 14:01:44 +01:00
Miroslav Stampar
104fbc80af Patch for #2348 2017-01-16 13:53:46 +01:00
Miroslav Stampar
cadba37059 Proper implementation for #2350 2017-01-16 13:44:46 +01:00
Miroslav Stampar
750d57ec96 Fixed bug reported privately via email 2017-01-13 14:41:41 +01:00
Miroslav Stampar
9a86365d92 Fixes #2333 2017-01-08 01:21:31 +01:00
Miroslav Stampar
f794d9d5a5 Fixes #2328 2017-01-02 15:26:32 +01:00
Miroslav Stampar
c29db43bfa Minor refactoring 2017-01-02 15:14:59 +01:00
Miroslav Stampar
e0eeed0a96 Minor update 2017-01-02 14:31:19 +01:00
55 changed files with 655 additions and 387 deletions

3
.gitignore vendored
View File

@@ -2,4 +2,5 @@
output/
.sqlmap_history
traffic.txt
*~
*~
.idea/

View File

@@ -361,7 +361,6 @@ This license does not apply to the following components:
* The MultipartPost library located under thirdparty/multipartpost/.
* The Odict library located under thirdparty/odict/.
* The Oset library located under thirdparty/oset/.
* The PageRank library located under thirdparty/pagerank/.
* The PrettyPrint library located under thirdparty/prettyprint/.
* The PyDes library located under thirdparty/pydes/.
* The SocksiPy library located under thirdparty/socks/.

View File

@@ -281,8 +281,6 @@ be bound by the terms and conditions of this License Agreement.
* The bottle web framework library located under thirdparty/bottle/.
Copyright (C) 2012, Marcel Hellkamp.
* The PageRank library located under thirdparty/pagerank/.
Copyright (C) 2010, Corey Goldberg.
* The Termcolor library located under thirdparty/termcolor/.
Copyright (C) 2008-2011, Volvox Development Team.

View File

@@ -13,7 +13,7 @@ then
NEW_TAG=$(python -c "import re, sys, time; version = re.search('\"([0-9.]*)\"', sys.argv[1]).group(1); _ = version.split('.'); print '.'.join(_[:-1]) if len(_) == 4 and _[-1] == '0' else ''" "$LINE")
if [ -n "$NEW_TAG" ]
then
git commit -am "Automatic monthly tagging"
#git commit -am "Automatic monthly tagging"
echo "Creating new tag ${NEW_TAG}"
git tag $NEW_TAG
git push origin $NEW_TAG

View File

@@ -107,7 +107,7 @@ If you prefer fetching daily updates, you can download sqlmap by cloning the
::
git clone https://github.com/sqlmapproject/sqlmap.git sqlmap-dev
git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git sqlmap-dev
sqlmap works out of the box with
`Python <http://www.python.org/download/>`__ version **2.6.x** and

View File

@@ -20,6 +20,7 @@ from lib.core.common import extractRegexResult
from lib.core.common import extractTextTagContent
from lib.core.common import findDynamicContent
from lib.core.common import Format
from lib.core.common import getFilteredPageContent
from lib.core.common import getLastRequestHTTPError
from lib.core.common import getPublicTypeMembers
from lib.core.common import getSafeExString
@@ -63,6 +64,7 @@ from lib.core.exception import SqlmapConnectionException
from lib.core.exception import SqlmapNoneDataException
from lib.core.exception import SqlmapSilentQuitException
from lib.core.exception import SqlmapUserQuitException
from lib.core.settings import CANDIDATE_SENTENCE_MIN_LENGTH
from lib.core.settings import DEFAULT_GET_POST_DELIMITER
from lib.core.settings import DUMMY_NON_SQLI_CHECK_APPENDIX
from lib.core.settings import FI_ERROR_REGEX
@@ -478,6 +480,26 @@ def checkSqlInjection(place, parameter, value):
injectable = True
elif threadData.lastComparisonRatio > UPPER_RATIO_BOUND and not any((conf.string, conf.notString, conf.regexp, conf.code, kb.nullConnection)):
originalSet = set(getFilteredPageContent(kb.pageTemplate, True, "\n").split("\n"))
trueSet = set(getFilteredPageContent(truePage, True, "\n").split("\n"))
falseSet = set(getFilteredPageContent(falsePage, True, "\n").split("\n"))
if originalSet == trueSet != falseSet:
candidates = trueSet - falseSet
if candidates:
candidates = sorted(candidates, key=lambda _: len(_))
for candidate in candidates:
if re.match(r"\A[\w.,! ]+\Z", candidate) and ' ' in candidate and len(candidate) > CANDIDATE_SENTENCE_MIN_LENGTH:
conf.string = candidate
injectable = True
infoMsg = "%s parameter '%s' appears to be '%s' injectable (with --string=\"%s\")" % (paramType, parameter, title, repr(conf.string).lstrip('u').strip("'"))
logger.info(infoMsg)
break
if injectable:
if kb.pageStable and not any((conf.string, conf.notString, conf.regexp, conf.code, kb.nullConnection)):
if all((falseCode, trueCode)) and falseCode != trueCode:

View File

@@ -65,7 +65,6 @@ from lib.core.settings import REFERER_ALIASES
from lib.core.settings import USER_AGENT_ALIASES
from lib.core.target import initTargetEnv
from lib.core.target import setupTargetEnv
from thirdparty.pagerank.pagerank import get_pagerank
def _selectInjection():
"""
@@ -163,6 +162,7 @@ def _showInjections():
header = "sqlmap resumed the following injection point(s) from stored session"
if hasattr(conf, "api"):
conf.dumper.string("", {"url": conf.url, "query": conf.parameters.get(PLACE.GET), "data": conf.parameters.get(PLACE.POST)}, content_type=CONTENT_TYPE.TARGET)
conf.dumper.string("", kb.injections, content_type=CONTENT_TYPE.TECHNIQUES)
else:
data = "".join(set(_formatInjection(_) for _ in kb.injections)).rstrip("\n")
@@ -319,7 +319,7 @@ def start():
if conf.forms and conf.method:
message = "[#%d] form:\n%s %s" % (hostCount, conf.method, targetUrl)
else:
message = "URL %d:\n%s %s%s" % (hostCount, HTTPMETHOD.GET, targetUrl, " (PageRank: %s)" % get_pagerank(targetUrl) if conf.googleDork and conf.pageRank else "")
message = "URL %d:\n%s %s" % (hostCount, HTTPMETHOD.GET, targetUrl)
if conf.cookie:
message += "\nCookie: %s" % conf.cookie

View File

@@ -77,11 +77,6 @@ def setHandler():
items.insert(0, _)
for dbms, aliases, Handler, Connector in items:
if conf.dbms and conf.dbms.lower() != dbms and conf.dbms.lower() not in aliases:
debugMsg = "skipping test for %s" % dbms
logger.debug(debugMsg)
continue
handler = Handler()
conf.dbmsConnector = Connector()
@@ -107,6 +102,8 @@ def setHandler():
conf.dbmsHandler = max(_ for _ in items if _[0] == kb.resolutionDbms)[2]()
else:
conf.dbmsHandler = handler
conf.dbmsHandler._dbms = dbms
break
else:
conf.dbmsConnector = None

View File

@@ -1079,5 +1079,20 @@ class Agent(object):
return query
def whereQuery(self, query):
if conf.dumpWhere and query:
prefix, suffix = query.split(" ORDER BY ") if " ORDER BY " in query else (query, "")
if "%s)" % conf.tbl.upper() in prefix.upper():
prefix = re.sub(r"(?i)%s\)" % re.escape(conf.tbl), "%s WHERE %s)" % (conf.tbl, conf.dumpWhere), prefix)
elif re.search(r"(?i)\bWHERE\b", prefix):
prefix += " AND %s" % conf.dumpWhere
else:
prefix += " WHERE %s" % conf.dumpWhere
query = "%s ORDER BY %s" % (prefix, suffix) if suffix else prefix
return query
# SQL agent
agent = Agent()

View File

@@ -465,6 +465,8 @@ class Backend:
if not kb:
pass
elif not kb.get("testMode") and conf.get("dbmsHandler") and getattr(conf.dbmsHandler, "_dbms", None):
dbms = conf.dbmsHandler._dbms
elif Backend.getForcedDbms() is not None:
dbms = Backend.getForcedDbms()
elif Backend.getDbms() is not None:
@@ -515,10 +517,9 @@ class Backend:
# Comparison methods
@staticmethod
def isDbms(dbms):
if Backend.getDbms() is not None:
return Backend.getDbms() == aliasToDbmsEnum(dbms)
else:
return Backend.getIdentifiedDbms() == aliasToDbmsEnum(dbms)
if not kb.get("testMode") and all((Backend.getDbms(), Backend.getIdentifiedDbms())) and Backend.getDbms() != Backend.getIdentifiedDbms():
singleTimeWarnMessage("identified ('%s') and fingerprinted ('%s') DBMSes differ. If you experience problems in enumeration phase please rerun with '--flush-session'" % (Backend.getIdentifiedDbms(), Backend.getDbms()))
return Backend.getIdentifiedDbms() == aliasToDbmsEnum(dbms)
@staticmethod
def isDbmsWithin(aliases):
@@ -589,7 +590,7 @@ def paramToDict(place, parameters=None):
or re.search(r'\A9{3,}', _) or re.search(r'\A-\d+\Z', _) or re.search(DUMMY_USER_INJECTION, _))\
and not parameter.upper().startswith(GOOGLE_ANALYTICS_COOKIE_PREFIX):
warnMsg = "it appears that you have provided tainted parameter values "
warnMsg += "('%s') with most probably leftover " % element
warnMsg += "('%s') with most likely leftover " % element
warnMsg += "chars/statements from manual SQL injection test(s). "
warnMsg += "Please, always use only valid parameter values "
warnMsg += "so sqlmap could be able to run properly"
@@ -613,7 +614,8 @@ def paramToDict(place, parameters=None):
candidates = OrderedDict()
def walk(head, current=None):
current = current or head
if current is None:
current = head
if isListLike(current):
for _ in current:
walk(head, _)
@@ -621,14 +623,15 @@ def paramToDict(place, parameters=None):
for key in current.keys():
value = current[key]
if isinstance(value, (list, tuple, set, dict)):
walk(head, value)
if value:
walk(head, value)
elif isinstance(value, (bool, int, float, basestring)):
original = current[key]
if isinstance(value, bool):
current[key] = "%s%s" % (str(value).lower(), BOUNDED_INJECTION_MARKER)
else:
current[key] = "%s%s" % (value, BOUNDED_INJECTION_MARKER)
candidates["%s (%s)" % (parameter, key)] = json.dumps(deserialized)
candidates["%s (%s)" % (parameter, key)] = re.sub("(%s\s*=\s*)%s" % (re.escape(parameter), re.escape(testableParameters[parameter])), r"\g<1>%s" % json.dumps(deserialized), parameters)
current[key] = original
deserialized = json.loads(testableParameters[parameter])
@@ -728,7 +731,11 @@ def getManualDirectories():
directories = normalizePath(directories)
if directories:
if conf.webRoot:
directories = [conf.webRoot]
infoMsg = "using '%s' as web server document root" % conf.webRoot
logger.info(infoMsg)
elif directories:
infoMsg = "retrieved the web server document root: '%s'" % directories
logger.info(infoMsg)
else:
@@ -1260,7 +1267,7 @@ def parseTargetDirect():
remote = False
for dbms in SUPPORTED_DBMS:
details = re.search("^(?P<dbms>%s)://(?P<credentials>(?P<user>.+?)\:(?P<pass>.*)\@)?(?P<remote>(?P<hostname>.+?)\:(?P<port>[\d]+)\/)?(?P<db>[\w\d\ \:\.\_\-\/\\\\]+?)$" % dbms, conf.direct, re.I)
details = re.search("^(?P<dbms>%s)://(?P<credentials>(?P<user>.+?)\:(?P<pass>.*)\@)?(?P<remote>(?P<hostname>[\w.-]+?)\:(?P<port>[\d]+)\/)?(?P<db>[\w\d\ \:\.\_\-\/\\\\]+?)$" % dbms, conf.direct, re.I)
if details:
conf.dbms = details.group("dbms")
@@ -1491,11 +1498,12 @@ def getLimitRange(count, plusOne=False):
count = int(count)
limitStart, limitStop = 1, count
if isinstance(conf.limitStop, int) and conf.limitStop > 0 and conf.limitStop < limitStop:
limitStop = conf.limitStop
if kb.dumpTable:
if isinstance(conf.limitStop, int) and conf.limitStop > 0 and conf.limitStop < limitStop:
limitStop = conf.limitStop
if isinstance(conf.limitStart, int) and conf.limitStart > 0 and conf.limitStart <= limitStop:
limitStart = conf.limitStart
if isinstance(conf.limitStart, int) and conf.limitStart > 0 and conf.limitStart <= limitStop:
limitStart = conf.limitStart
retVal = xrange(limitStart, limitStop + 1) if plusOne else xrange(limitStart - 1, limitStop)
@@ -1755,7 +1763,7 @@ def safeStringFormat(format_, params):
break
return retVal
def getFilteredPageContent(page, onlyText=True):
def getFilteredPageContent(page, onlyText=True, split=" "):
"""
Returns filtered page content without script, style and/or comments
or all HTML tags
@@ -1768,10 +1776,10 @@ def getFilteredPageContent(page, onlyText=True):
# only if the page's charset has been successfully identified
if isinstance(page, unicode):
retVal = re.sub(r"(?si)<script.+?</script>|<!--.+?-->|<style.+?</style>%s" % (r"|<[^>]+>|\t|\n|\r" if onlyText else ""), " ", page)
while retVal.find(" ") != -1:
retVal = retVal.replace(" ", " ")
retVal = htmlunescape(retVal.strip())
retVal = re.sub(r"(?si)<script.+?</script>|<!--.+?-->|<style.+?</style>%s" % (r"|<[^>]+>|\t|\n|\r" if onlyText else ""), split, page)
while retVal.find(2 * split) != -1:
retVal = retVal.replace(2 * split, split)
retVal = htmlunescape(retVal.strip().strip(split))
return retVal
@@ -2327,7 +2335,7 @@ def wasLastResponseDBMSError():
def wasLastResponseHTTPError():
"""
Returns True if the last web request resulted in an errornous HTTP code (like 500)
Returns True if the last web request resulted in an erroneous HTTP code (like 500)
"""
threadData = getCurrentThreadData()
@@ -2345,7 +2353,7 @@ def wasLastResponseDelayed():
deviation = stdev(kb.responseTimes.get(kb.responseTimeMode, []))
threadData = getCurrentThreadData()
if deviation and not conf.direct:
if deviation and not conf.direct and not conf.disableStats:
if len(kb.responseTimes[kb.responseTimeMode]) < MIN_TIME_RESPONSES:
warnMsg = "time-based standard deviation method used on a model "
warnMsg += "with less than %d response times" % MIN_TIME_RESPONSES
@@ -2365,7 +2373,10 @@ def wasLastResponseDelayed():
return retVal
else:
return (threadData.lastQueryDuration - conf.timeSec) >= 0
delta = threadData.lastQueryDuration - conf.timeSec
if Backend.getIdentifiedDbms() in (DBMS.MYSQL,): # MySQL's SLEEP(X) lasts 0.05 seconds shorter on average
delta += 0.05
return delta >= 0
def adjustTimeDelay(lastQueryDuration, lowerStdLimit):
"""
@@ -2604,7 +2615,7 @@ def getPublicTypeMembers(type_, onlyValues=False):
retVal = []
for name, value in inspect.getmembers(type_):
if not name.startswith('__'):
if not name.startswith("__"):
if not onlyValues:
retVal.append((name, value))
else:
@@ -2664,7 +2675,7 @@ def extractTextTagContent(page):
except MemoryError:
page = page.replace(REFLECTED_VALUE_MARKER, "")
return filter(None, (_.group('result').strip() for _ in re.finditer(TEXT_TAG_REGEX, page)))
return filter(None, (_.group("result").strip() for _ in re.finditer(TEXT_TAG_REGEX, page)))
def trimAlphaNum(value):
"""
@@ -2776,11 +2787,11 @@ def removeDynamicContent(page):
if prefix is None and suffix is None:
continue
elif prefix is None:
page = re.sub(r'(?s)^.+%s' % re.escape(suffix), suffix.replace('\\', r'\\'), page)
page = re.sub(r"(?s)^.+%s" % re.escape(suffix), suffix.replace('\\', r'\\'), page)
elif suffix is None:
page = re.sub(r'(?s)%s.+$' % re.escape(prefix), prefix.replace('\\', r'\\'), page)
page = re.sub(r"(?s)%s.+$" % re.escape(prefix), prefix.replace('\\', r'\\'), page)
else:
page = re.sub(r'(?s)%s.+%s' % (re.escape(prefix), re.escape(suffix)), '%s%s' % (prefix.replace('\\', r'\\'), suffix.replace('\\', r'\\')), page)
page = re.sub(r"(?s)%s.+%s" % (re.escape(prefix), re.escape(suffix)), "%s%s" % (prefix.replace('\\', r'\\'), suffix.replace('\\', r'\\')), page)
return page
@@ -3633,13 +3644,31 @@ def randomizeParameterValue(value):
value = re.sub(r"%[0-9a-fA-F]{2}", "", value)
for match in re.finditer('[A-Z]+', value):
retVal = retVal.replace(match.group(), randomStr(len(match.group())).upper())
while True:
original = match.group()
candidate = randomStr(len(match.group())).upper()
if original != candidate:
break
retVal = retVal.replace(original, candidate)
for match in re.finditer('[a-z]+', value):
retVal = retVal.replace(match.group(), randomStr(len(match.group())).lower())
while True:
original = match.group()
candidate = randomStr(len(match.group())).lower()
if original != candidate:
break
retVal = retVal.replace(original, candidate)
for match in re.finditer('[0-9]+', value):
retVal = retVal.replace(match.group(), str(randomInt(len(match.group()))))
while True:
original = match.group()
candidate = str(randomInt(len(match.group())))
if original != candidate:
break
retVal = retVal.replace(original, candidate)
return retVal

View File

@@ -176,6 +176,7 @@ class HTTP_HEADER:
PROXY_CONNECTION = "Proxy-Connection"
RANGE = "Range"
REFERER = "Referer"
REFRESH = "Refresh" # Reference: http://stackoverflow.com/a/283794
SERVER = "Server"
SET_COOKIE = "Set-Cookie"
TRANSFER_ENCODING = "Transfer-Encoding"
@@ -286,31 +287,32 @@ class WEB_API:
JSP = "jsp"
class CONTENT_TYPE:
TECHNIQUES = 0
DBMS_FINGERPRINT = 1
BANNER = 2
CURRENT_USER = 3
CURRENT_DB = 4
HOSTNAME = 5
IS_DBA = 6
USERS = 7
PASSWORDS = 8
PRIVILEGES = 9
ROLES = 10
DBS = 11
TABLES = 12
COLUMNS = 13
SCHEMA = 14
COUNT = 15
DUMP_TABLE = 16
SEARCH = 17
SQL_QUERY = 18
COMMON_TABLES = 19
COMMON_COLUMNS = 20
FILE_READ = 21
FILE_WRITE = 22
OS_CMD = 23
REG_READ = 24
TARGET = 0
TECHNIQUES = 1
DBMS_FINGERPRINT = 2
BANNER = 3
CURRENT_USER = 4
CURRENT_DB = 5
HOSTNAME = 6
IS_DBA = 7
USERS = 8
PASSWORDS = 9
PRIVILEGES = 10
ROLES = 11
DBS = 12
TABLES = 13
COLUMNS = 14
SCHEMA = 15
COUNT = 16
DUMP_TABLE = 17
SEARCH = 18
SQL_QUERY = 19
COMMON_TABLES = 20
COMMON_COLUMNS = 21
FILE_READ = 22
FILE_WRITE = 23
OS_CMD = 24
REG_READ = 25
PART_RUN_CONTENT_TYPES = {
"checkDbms": CONTENT_TYPE.TECHNIQUES,

View File

@@ -897,20 +897,25 @@ def _setTamperingFunctions():
for script in re.split(PARAMETER_SPLITTING_REGEX, conf.tamper):
found = False
path = paths.SQLMAP_TAMPER_PATH.encode(sys.getfilesystemencoding() or UNICODE_ENCODING)
script = script.strip().encode(sys.getfilesystemencoding() or UNICODE_ENCODING)
if not script:
continue
try:
if not script:
continue
elif os.path.exists(os.path.join(paths.SQLMAP_TAMPER_PATH, script if script.endswith(".py") else "%s.py" % script)):
script = os.path.join(paths.SQLMAP_TAMPER_PATH, script if script.endswith(".py") else "%s.py" % script)
elif os.path.exists(os.path.join(path, script if script.endswith(".py") else "%s.py" % script)):
script = os.path.join(path, script if script.endswith(".py") else "%s.py" % script)
elif not os.path.exists(script):
errMsg = "tamper script '%s' does not exist" % script
raise SqlmapFilePathException(errMsg)
elif not os.path.exists(script):
errMsg = "tamper script '%s' does not exist" % script
raise SqlmapFilePathException(errMsg)
elif not script.endswith(".py"):
errMsg = "tamper script '%s' should have an extension '.py'" % script
elif not script.endswith(".py"):
errMsg = "tamper script '%s' should have an extension '.py'" % script
raise SqlmapSyntaxException(errMsg)
except UnicodeDecodeError:
errMsg = "invalid character provided in option '--tamper'"
raise SqlmapSyntaxException(errMsg)
dirname, filename = os.path.split(script)
@@ -928,7 +933,7 @@ def _setTamperingFunctions():
sys.path.insert(0, dirname)
try:
module = __import__(filename[:-3])
module = __import__(filename[:-3].encode(sys.getfilesystemencoding() or UNICODE_ENCODING))
except (ImportError, SyntaxError), ex:
raise SqlmapSyntaxException("cannot import tamper script '%s' (%s)" % (filename[:-3], getSafeExString(ex)))
@@ -1001,7 +1006,7 @@ def _setWafFunctions():
try:
if filename[:-3] in sys.modules:
del sys.modules[filename[:-3]]
module = __import__(filename[:-3])
module = __import__(filename[:-3].encode(sys.getfilesystemencoding() or UNICODE_ENCODING))
except ImportError, msg:
raise SqlmapSyntaxException("cannot import WAF script '%s' (%s)" % (filename[:-3], msg))
@@ -2319,7 +2324,7 @@ def _setProxyList():
return
conf.proxyList = []
for match in re.finditer(r"(?i)((http[^:]*|socks[^:]*)://)?([\w.]+):(\d+)", readCachedFileContent(conf.proxyFile)):
for match in re.finditer(r"(?i)((http[^:]*|socks[^:]*)://)?([\w\-.]+):(\d+)", readCachedFileContent(conf.proxyFile)):
_, type_, address, port = match.groups()
conf.proxyList.append("%s://%s:%s" % (type_ or "http", address, port))

View File

@@ -225,11 +225,11 @@ optDict = {
"identifyWaf": "boolean",
"mobile": "boolean",
"offline": "boolean",
"pageRank": "boolean",
"purgeOutput": "boolean",
"skipWaf": "boolean",
"smart": "boolean",
"tmpDir": "string",
"webRoot": "string",
"wizard": "boolean",
"verbose": "integer",
},

View File

@@ -19,7 +19,7 @@ from lib.core.enums import DBMS_DIRECTORY_NAME
from lib.core.enums import OS
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
VERSION = "1.1"
VERSION = "1.1.4.0"
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
@@ -109,7 +109,7 @@ DUMMY_SEARCH_USER_AGENT = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:49.0) Geck
TEXT_TAG_REGEX = r"(?si)<(abbr|acronym|b|blockquote|br|center|cite|code|dt|em|font|h\d|i|li|p|pre|q|strong|sub|sup|td|th|title|tt|u)(?!\w).*?>(?P<result>[^<]+)"
# Regular expression used for recognition of IP addresses
IP_ADDRESS_REGEX = r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b"
IP_ADDRESS_REGEX = r"\b(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\b"
# Regular expression used for recognition of generic "your ip has been blocked" messages
BLOCKED_IP_REGEX = r"(?i)(\A|\b)ip\b.*\b(banned|blocked|block list|firewall)"
@@ -303,6 +303,7 @@ ERROR_PARSING_REGEXES = (
r"(?m)^(fatal|error|warning|exception):?\s*(?P<result>[^\n]+?)$",
r"(?P<result>[^\n>]*SQL Syntax[^\n<]+)",
r"<li>Error Type:<br>(?P<result>.+?)</li>",
r"CDbCommand (?P<result>[^<>\n]*SQL[^<>\n]+)",
r"error '[0-9a-f]{8}'((<[^>]+>)|\s)+(?P<result>[^<>]+)",
r"\[[^\n\]]+(ODBC|JDBC)[^\n\]]+\](\[[^\]]+\])?(?P<result>[^\n]+(in query expression|\(SQL| at /[^ ]+pdo)[^\n<]+)"
)
@@ -358,6 +359,9 @@ MIN_RATIO = 0.0
# Maximum value for comparison ratio
MAX_RATIO = 1.0
# Minimum length of sentence for automatic choosing of --string (in case of high matching ratio)
CANDIDATE_SENTENCE_MIN_LENGTH = 10
# Character used for marking injectable position inside provided data
CUSTOM_INJECTION_MARK_CHAR = '*'
@@ -587,7 +591,7 @@ BANNER = re.sub(r"\[.\]", lambda _: "[\033[01;41m%s\033[01;49m]" % random.sample
DUMMY_NON_SQLI_CHECK_APPENDIX = "<'\">"
# Regular expression used for recognition of file inclusion errors
FI_ERROR_REGEX = "(?i)[^\n]*(no such file|failed (to )?open)[^\n]*"
FI_ERROR_REGEX = "(?i)[^\n]{0,100}(no such file|failed (to )?open)[^\n]{0,100}"
# Length of prefix and suffix used in non-SQLI heuristic checks
NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH = 6
@@ -692,7 +696,7 @@ MAX_HISTORY_LENGTH = 1000
MIN_ENCODED_LEN_CHECK = 5
# Timeout in seconds in which Metasploit remote session has to be initialized
METASPLOIT_SESSION_TIMEOUT = 300
METASPLOIT_SESSION_TIMEOUT = 120
# Reference: http://www.postgresql.org/docs/9.0/static/catalog-pg-largeobject.html
LOBLKSIZE = 2048

View File

@@ -7,12 +7,11 @@ See the file 'doc/COPYING' for copying permission
import difflib
import random
import thread
import threading
import time
import traceback
from thread import error as ThreadError
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
@@ -47,6 +46,7 @@ class _ThreadData(threading.local):
self.lastComparisonPage = None
self.lastComparisonHeaders = None
self.lastComparisonCode = None
self.lastComparisonRatio = None
self.lastErrorPage = None
self.lastHTTPError = None
self.lastRedirectMsg = None
@@ -151,7 +151,7 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
try:
thread.start()
except ThreadError, ex:
except thread.error, ex:
errMsg = "error occurred while starting new thread ('%s')" % ex.message
logger.critical(errMsg)
break

View File

@@ -482,10 +482,10 @@ def cmdLineParser(argv=None):
help="Use WHERE condition while table dumping")
enumeration.add_option("--start", dest="limitStart", type="int",
help="First query output entry to retrieve")
help="First dump table entry to retrieve")
enumeration.add_option("--stop", dest="limitStop", type="int",
help="Last query output entry to retrieve")
help="Last dump table entry to retrieve")
enumeration.add_option("--first", dest="firstChar", type="int",
help="First query output word character to retrieve")
@@ -738,10 +738,6 @@ def cmdLineParser(argv=None):
action="store_true",
help="Work in offline mode (only use session data)")
miscellaneous.add_option("--page-rank", dest="pageRank",
action="store_true",
help="Display page rank (PR) for Google dork results")
miscellaneous.add_option("--purge-output", dest="purgeOutput",
action="store_true",
help="Safely remove all content from output directory")
@@ -760,6 +756,9 @@ def cmdLineParser(argv=None):
miscellaneous.add_option("--tmp-dir", dest="tmpDir",
help="Local directory for storing temporary files")
miscellaneous.add_option("--web-root", dest="webRoot",
help="Web server document root directory (e.g. \"/var/www\")")
miscellaneous.add_option("--wizard", dest="wizard",
action="store_true",
help="Simple wizard interface for beginner users")
@@ -777,6 +776,9 @@ def cmdLineParser(argv=None):
parser.add_option("--disable-precon", dest="disablePrecon", action="store_true",
help=SUPPRESS_HELP)
parser.add_option("--disable-stats", dest="disableStats", action="store_true",
help=SUPPRESS_HELP)
parser.add_option("--profile", dest="profile", action="store_true",
help=SUPPRESS_HELP)
@@ -900,6 +902,9 @@ def cmdLineParser(argv=None):
elif len(argv[i]) > 1 and all(ord(_) in xrange(0x2018, 0x2020) for _ in ((argv[i].split('=', 1)[-1].strip() or ' ')[0], argv[i][-1])):
dataToStdout("[!] copy-pasting illegal (non-console) quote characters from Internet is, well, illegal (%s)\n" % argv[i])
raise SystemExit
elif len(argv[i]) > 1 and u"\uff0c" in argv[i].split('=', 1)[-1]:
dataToStdout("[!] copy-pasting illegal (non-console) comma characters from Internet is, well, illegal (%s)\n" % argv[i])
raise SystemExit
elif re.search(r"\A-\w=.+", argv[i]):
dataToStdout("[!] potentially miswritten (illegal '=') short option detected ('%s')\n" % argv[i])
raise SystemExit

View File

@@ -14,13 +14,14 @@ from lib.core.common import UnicodeRawConfigParser
from lib.core.data import cmdLineOptions
from lib.core.data import conf
from lib.core.data import logger
from lib.core.enums import OPTION_TYPE
from lib.core.exception import SqlmapMissingMandatoryOptionException
from lib.core.exception import SqlmapSyntaxException
from lib.core.optiondict import optDict
config = None
def configFileProxy(section, option, boolean=False, integer=False):
def configFileProxy(section, option, datatype):
"""
Parse configuration file and save settings into the configuration
advanced dictionary.
@@ -30,10 +31,12 @@ def configFileProxy(section, option, boolean=False, integer=False):
if config.has_option(section, option):
try:
if boolean:
if datatype == OPTION_TYPE.BOOLEAN:
value = config.getboolean(section, option) if config.get(section, option) else False
elif integer:
elif datatype == OPTION_TYPE.INTEGER:
value = config.getint(section, option) if config.get(section, option) else 0
elif datatype == OPTION_TYPE.FLOAT:
value = config.getfloat(section, option) if config.get(section, option) else 0.0
else:
value = config.get(section, option)
except ValueError, ex:
@@ -91,8 +94,4 @@ def configFileParser(configFile):
for family, optionData in optDict.items():
for option, datatype in optionData.items():
datatype = unArrayizeValue(datatype)
boolean = datatype == "boolean"
integer = datatype == "integer"
configFileProxy(family, option, boolean, integer)
configFileProxy(family, option, datatype)

View File

@@ -102,7 +102,7 @@ def forgeHeaders(items=None):
message = "you provided a HTTP %s header value. " % HTTP_HEADER.COOKIE
message += "The target URL provided its own cookies within "
message += "the HTTP %s header which intersect with yours. " % HTTP_HEADER.SET_COOKIE
message += "Do you want to merge them in futher requests? [Y/n] "
message += "Do you want to merge them in further requests? [Y/n] "
_ = readInput(message, default="Y")
kb.mergeCookies = not _ or _[0] in ("y", "Y")
@@ -168,6 +168,8 @@ def checkCharEncoding(encoding, warn=True):
encoding = encoding.replace("8858", "8859") # iso-8858 -> iso-8859
elif "8559" in encoding:
encoding = encoding.replace("8559", "8859") # iso-8559 -> iso-8859
elif "8895" in encoding:
encoding = encoding.replace("8895", "8859") # iso-8895 -> iso-8859
elif "5889" in encoding:
encoding = encoding.replace("5889", "8859") # iso-5889 -> iso-8859
elif "5589" in encoding:
@@ -314,6 +316,12 @@ def decodePage(page, contentEncoding, contentType):
page = re.sub(r"&([^;]+);", lambda _: chr(htmlEntities[_.group(1)]) if htmlEntities.get(_.group(1), 256) < 256 else _.group(0), page)
kb.pageEncoding = kb.pageEncoding or checkCharEncoding(getHeuristicCharEncoding(page))
if kb.pageEncoding and kb.pageEncoding.lower() == "utf-8-sig":
kb.pageEncoding = "utf-8"
if page and page.startswith("\xef\xbb\xbf"): # Reference: https://docs.python.org/2/library/codecs.html (Note: noticed problems when "utf-8-sig" is left to Python for handling)
page = page[3:]
page = getUnicode(page, kb.pageEncoding)
# e.g. &#8217;&#8230;&#8482;
@@ -363,7 +371,7 @@ def processResponse(page, responseHeaders):
if readInput(msg, default='N').strip().upper() != 'Y':
continue
conf.paramDict[PLACE.POST][name] = value
conf.parameters[PLACE.POST] = re.sub("(?i)(%s=)[^&]+" % name, r"\g<1>%s" % value, conf.parameters[PLACE.POST])
conf.parameters[PLACE.POST] = re.sub("(?i)(%s=)[^&]+" % re.escape(name), r"\g<1>%s" % re.escape(value), conf.parameters[PLACE.POST])
if not kb.captchaDetected and re.search(r"(?i)captcha", page or ""):
for match in re.finditer(r"(?si)<form.+?</form>", page):

View File

@@ -144,6 +144,9 @@ def _comparison(page, headers, code, getRatioValue, pageLength):
kb.matchRatio = ratio
logger.debug("setting match ratio for current parameter to %.3f" % kb.matchRatio)
if kb.testMode:
threadData.lastComparisonRatio = ratio
# If it has been requested to return the ratio and not a comparison
# response
if getRatioValue:

View File

@@ -146,9 +146,9 @@ class Connect(object):
if kb.testMode and kb.previousMethod == PAYLOAD.METHOD.TIME:
# timed based payloads can cause web server unresponsiveness
# if the injectable piece of code is some kind of JOIN-like query
warnMsg = "most probably web server instance hasn't recovered yet "
warnMsg = "most likely web server instance hasn't recovered yet "
warnMsg += "from previous timed based payload. If the problem "
warnMsg += "persists please wait for few minutes and rerun "
warnMsg += "persists please wait for a few minutes and rerun "
warnMsg += "without flag 'T' in option '--technique' "
warnMsg += "(e.g. '--flush-session --technique=BEUS') or try to "
warnMsg += "lower the value of option '--time-sec' (e.g. '--time-sec=2')"
@@ -374,9 +374,7 @@ class Connect(object):
# Reset header values to original in case of provided request file
if target and conf.requestFile:
headers = OrderedDict(conf.httpHeaders)
if cookie:
headers[HTTP_HEADER.COOKIE] = cookie
headers = forgeHeaders({HTTP_HEADER.COOKIE: cookie})
if auxHeaders:
for key, value in auxHeaders.items():
@@ -475,7 +473,7 @@ class Connect(object):
return conn, None, None
# Get HTTP response
if hasattr(conn, 'redurl'):
if hasattr(conn, "redurl"):
page = (threadData.lastRedirectMsg[1] if kb.redirectChoice == REDIRECTION.NO\
else Connect._connReadProxy(conn)) if not skipRead else None
skipLogTraffic = kb.redirectChoice == REDIRECTION.NO
@@ -483,45 +481,54 @@ class Connect(object):
else:
page = Connect._connReadProxy(conn) if not skipRead else None
code = code or (conn.code if conn else None)
responseHeaders = conn.info()
responseHeaders[URI_HTTP_HEADER] = conn.geturl()
if conn:
code = conn.code
responseHeaders = conn.info()
responseHeaders[URI_HTTP_HEADER] = conn.geturl()
else:
code = None
responseHeaders = {}
page = decodePage(page, responseHeaders.get(HTTP_HEADER.CONTENT_ENCODING), responseHeaders.get(HTTP_HEADER.CONTENT_TYPE))
status = getUnicode(conn.msg)
status = getUnicode(conn.msg) if conn else None
kb.connErrorCounter = 0
if extractRegexResult(META_REFRESH_REGEX, page) and not refreshing:
refresh = extractRegexResult(META_REFRESH_REGEX, page)
if not refreshing:
refresh = responseHeaders.get(HTTP_HEADER.REFRESH, "").split("url=")[-1].strip()
debugMsg = "got HTML meta refresh header"
logger.debug(debugMsg)
if extractRegexResult(META_REFRESH_REGEX, page):
refresh = extractRegexResult(META_REFRESH_REGEX, page)
if kb.alwaysRefresh is None:
msg = "sqlmap got a refresh request "
msg += "(redirect like response common to login pages). "
msg += "Do you want to apply the refresh "
msg += "from now on (or stay on the original page)? [Y/n]"
choice = readInput(msg, default="Y")
debugMsg = "got HTML meta refresh header"
logger.debug(debugMsg)
kb.alwaysRefresh = choice not in ("n", "N")
if refresh:
if kb.alwaysRefresh is None:
msg = "sqlmap got a refresh request "
msg += "(redirect like response common to login pages). "
msg += "Do you want to apply the refresh "
msg += "from now on (or stay on the original page)? [Y/n]"
choice = readInput(msg, default="Y")
if kb.alwaysRefresh:
if re.search(r"\Ahttps?://", refresh, re.I):
url = refresh
else:
url = urlparse.urljoin(url, refresh)
kb.alwaysRefresh = choice not in ("n", "N")
threadData.lastRedirectMsg = (threadData.lastRequestUID, page)
kwargs['refreshing'] = True
kwargs['url'] = url
kwargs['get'] = None
kwargs['post'] = None
if kb.alwaysRefresh:
if re.search(r"\Ahttps?://", refresh, re.I):
url = refresh
else:
url = urlparse.urljoin(url, refresh)
try:
return Connect._getPageProxy(**kwargs)
except SqlmapSyntaxException:
pass
threadData.lastRedirectMsg = (threadData.lastRequestUID, page)
kwargs["refreshing"] = True
kwargs["url"] = url
kwargs["get"] = None
kwargs["post"] = None
try:
return Connect._getPageProxy(**kwargs)
except SqlmapSyntaxException:
pass
# Explicit closing of connection object
if conn and not conf.keepAlive:
@@ -627,6 +634,14 @@ class Connect(object):
if kb.testMode and kb.testType not in (None, PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED):
singleTimeWarnMessage("there is a possibility that the target (or WAF/IPS/IDS) is dropping 'suspicious' requests")
warnMsg = "connection timed out to the target URL"
elif "Connection reset" in tbMsg:
if not conf.disablePrecon:
singleTimeWarnMessage("turning off pre-connect mechanism because of connection reset(s)")
conf.disablePrecon = True
if kb.testMode:
singleTimeWarnMessage("there is a possibility that the target (or WAF/IPS/IDS) is resetting 'suspicious' requests")
warnMsg = "connection reset to the target URL"
elif "URLError" in tbMsg or "error" in tbMsg:
warnMsg = "unable to connect to the target URL"
match = re.search(r"Errno \d+\] ([^>]+)", tbMsg)
@@ -1038,15 +1053,29 @@ class Connect(object):
found = False
value = getUnicode(value)
if kb.postHint and re.search(r"\b%s\b" % re.escape(name), post or ""):
if kb.postHint in (POST_HINT.XML, POST_HINT.SOAP):
if re.search(r"<%s\b" % re.escape(name), post):
found = True
post = re.sub(r"(?s)(<%s\b[^>]*>)(.*?)(</%s)" % (re.escape(name), re.escape(name)), "\g<1>%s\g<3>" % value, post)
elif re.search(r"\b%s>" % re.escape(name), post):
found = True
post = re.sub(r"(?s)(\b%s>)(.*?)(</[^<]*\b%s>)" % (re.escape(name), re.escape(name)), "\g<1>%s\g<3>" % value, post)
regex = r"\b(%s)\b([^\w]+)(\w+)" % re.escape(name)
if not found and re.search(regex, (post or "")):
found = True
post = re.sub(regex, "\g<1>\g<2>%s" % value, post)
regex = r"((\A|%s)%s=).+?(%s|\Z)" % (re.escape(delimiter), re.escape(name), re.escape(delimiter))
if not found and re.search(regex, (post or "")):
found = True
post = re.sub(regex, "\g<1>%s\g<3>" % value, post)
if re.search(regex, (get or "")):
found = True
get = re.sub(regex, "\g<1>%s\g<3>" % value, get)
if re.search(regex, (post or "")):
found = True
post = re.sub(regex, "\g<1>%s\g<3>" % value, post)
if re.search(regex, (query or "")):
found = True
uri = re.sub(regex.replace(r"\A", r"\?"), "\g<1>%s\g<3>" % value, uri)
@@ -1073,7 +1102,7 @@ class Connect(object):
elif kb.postUrlEncode:
post = urlencode(post, spaceplus=kb.postSpaceToPlus)
if timeBasedCompare:
if timeBasedCompare and not conf.disableStats:
if len(kb.responseTimes.get(kb.responseTimeMode, [])) < MIN_TIME_RESPONSES:
clearConsoleLine()

View File

@@ -5,6 +5,7 @@ Copyright (c) 2006-2017 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
import re
import types
import urllib2
import urlparse
@@ -123,7 +124,12 @@ class SmartRedirectHandler(urllib2.HTTPRedirectHandler):
req.headers[HTTP_HEADER.HOST] = getHostHeader(redurl)
if headers and HTTP_HEADER.SET_COOKIE in headers:
req.headers[HTTP_HEADER.COOKIE] = headers[HTTP_HEADER.SET_COOKIE].split(conf.cookieDel or DEFAULT_COOKIE_DELIMITER)[0]
delimiter = conf.cookieDel or DEFAULT_COOKIE_DELIMITER
_ = headers[HTTP_HEADER.SET_COOKIE].split(delimiter)[0]
if HTTP_HEADER.COOKIE not in req.headers:
req.headers[HTTP_HEADER.COOKIE] = _
else:
req.headers[HTTP_HEADER.COOKIE] = re.sub("%s{2,}" % delimiter, delimiter, ("%s%s%s" % (re.sub(r"\b%s=[^%s]*%s?" % (_.split('=')[0], delimiter, delimiter), "", req.headers[HTTP_HEADER.COOKIE]), delimiter, _)).strip(delimiter))
try:
result = urllib2.HTTPRedirectHandler.http_error_302(self, req, fp, code, msg, headers)
except urllib2.HTTPError, e:

View File

@@ -351,7 +351,7 @@ class Metasploit:
self._cliCmd += " E"
else:
self._cliCmd = "%s -x 'use multi/handler; set PAYLOAD %s" % (self._msfConsole, self.payloadConnStr)
self._cliCmd = "%s -L -x 'use multi/handler; set PAYLOAD %s" % (self._msfConsole, self.payloadConnStr)
self._cliCmd += "; set EXITFUNC %s" % exitfunc
self._cliCmd += "; set LPORT %s" % self.portStr
@@ -601,6 +601,8 @@ class Metasploit:
except (EOFError, IOError, select.error):
return proc.returncode
except KeyboardInterrupt:
pass
def createMsfShellcode(self, exitfunc, format, extra, encode):
infoMsg = "creating Metasploit Framework multi-stage shellcode "
@@ -620,7 +622,7 @@ class Metasploit:
pollProcess(process)
payloadStderr = process.communicate()[1]
match = re.search("(Total size:|Length:|succeeded with size) ([\d]+)", payloadStderr)
match = re.search("(Total size:|Length:|succeeded with size|Final size of exe file:) ([\d]+)", payloadStderr)
if match:
payloadSize = int(match.group(2))

View File

@@ -26,6 +26,7 @@ from lib.core.common import ntToPosixSlashes
from lib.core.common import isTechniqueAvailable
from lib.core.common import isWindowsDriveLetterPath
from lib.core.common import normalizePath
from lib.core.common import parseFilePaths
from lib.core.common import posixToNtSlashes
from lib.core.common import randomInt
from lib.core.common import randomStr
@@ -38,8 +39,10 @@ from lib.core.data import kb
from lib.core.data import logger
from lib.core.data import paths
from lib.core.enums import DBMS
from lib.core.enums import HTTP_HEADER
from lib.core.enums import OS
from lib.core.enums import PAYLOAD
from lib.core.enums import PLACE
from lib.core.enums import WEB_API
from lib.core.exception import SqlmapNoneDataException
from lib.core.settings import BACKDOOR_RUN_CMD_TIMEOUT
@@ -196,6 +199,60 @@ class Web:
self.webApi = choices[int(choice) - 1]
break
if not kb.absFilePaths:
message = "do you want sqlmap to further try to "
message += "provoke the full path disclosure? [Y/n] "
getOutput = readInput(message, default="Y")
if getOutput in ("y", "Y"):
headers = {}
been = {conf.url}
for match in re.finditer(r"=['\"]((https?):)?(//[^/'\"]+)?(/[\w/.-]*)\bwp-", kb.originalPage, re.I):
url = "%s%s" % (conf.url.replace(conf.path, match.group(4)), "wp-content/wp-db.php")
if url not in been:
try:
page, _, _ = Request.getPage(url=url, raise404=False, silent=True)
parseFilePaths(page)
except:
pass
finally:
been.add(url)
url = re.sub(r"(\.\w+)\Z", "~\g<1>", conf.url)
if url not in been:
try:
page, _, _ = Request.getPage(url=url, raise404=False, silent=True)
parseFilePaths(page)
except:
pass
finally:
been.add(url)
for place in (PLACE.GET, PLACE.POST):
if place in conf.parameters:
value = re.sub(r"(\A|&)(\w+)=", "\g<2>[]=", conf.parameters[place])
if "[]" in value:
page, headers = Request.queryPage(value=value, place=place, content=True, raise404=False, silent=True, noteResponseTime=False)
parseFilePaths(page)
cookie = None
if PLACE.COOKIE in conf.parameters:
cookie = conf.parameters[PLACE.COOKIE]
elif headers and HTTP_HEADER.SET_COOKIE in headers:
cookie = headers[HTTP_HEADER.SET_COOKIE]
if cookie:
value = re.sub(r"(\A|;)(\w+)=[^;]*", "\g<2>=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", cookie)
if value != cookie:
page, _ = Request.queryPage(value=value, place=PLACE.COOKIE, content=True, raise404=False, silent=True, noteResponseTime=False)
parseFilePaths(page)
value = re.sub(r"(\A|;)(\w+)=[^;]*", "\g<2>=", cookie)
if value != cookie:
page, _ = Request.queryPage(value=value, place=PLACE.COOKIE, content=True, raise404=False, silent=True, noteResponseTime=False)
parseFilePaths(page)
directories = list(arrayizeValue(getManualDirectories()))
directories.extend(getAutoDirectories())
directories = list(oset(directories))

View File

@@ -70,8 +70,8 @@ def tableExists(tableFile, regex=None):
if result:
errMsg = "can't use table existence check because of detected invalid results "
errMsg += "(most probably caused by inability of the used injection "
errMsg += "to distinguish errornous results)"
errMsg += "(most likely caused by inability of the used injection "
errMsg += "to distinguish erroneous results)"
raise SqlmapDataException(errMsg)
tables = getFileItems(tableFile, lowercase=Backend.getIdentifiedDbms() in (DBMS.ACCESS,), unique=True)
@@ -178,8 +178,8 @@ def columnExists(columnFile, regex=None):
if result:
errMsg = "can't use column existence check because of detected invalid results "
errMsg += "(most probably caused by inability of the used injection "
errMsg += "to distinguish errornous results)"
errMsg += "(most likely caused by inability of the used injection "
errMsg += "to distinguish erroneous results)"
raise SqlmapDataException(errMsg)
infoMsg = "checking column existence using items from '%s'" % columnFile

View File

@@ -5,6 +5,7 @@ Copyright (c) 2006-2017 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
import logging
import random
import re
@@ -154,7 +155,7 @@ def _findUnionCharCount(comment, place, parameter, value, prefix, suffix, where=
if retVal:
infoMsg = "target URL appears to be UNION injectable with %d columns" % retVal
singleTimeLogMessage(infoMsg)
singleTimeLogMessage(infoMsg, logging.INFO, re.sub(r"\d+", "N", infoMsg))
return retVal

View File

@@ -6,6 +6,7 @@ Copyright (c) 2006-2017 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
import contextlib
import logging
import os
import re
@@ -163,6 +164,8 @@ class Task(object):
def engine_start(self):
if os.path.exists("sqlmap.py"):
self.process = Popen(["python", "sqlmap.py", "--pickled-options", base64pickle(self.options)], shell=False, close_fds=not IS_WIN)
elif os.path.exists(os.path.join(os.getcwd(), "sqlmap.py")):
self.process = Popen(["python", "sqlmap.py", "--pickled-options", base64pickle(self.options)], shell=False, cwd=os.getcwd(), close_fds=not IS_WIN)
else:
self.process = Popen(["sqlmap", "--pickled-options", base64pickle(self.options)], shell=False, close_fds=not IS_WIN)
@@ -646,6 +649,11 @@ def server(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, adapter=REST
DataStore.admin_id = hexencode(os.urandom(16))
Database.filepath = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.IPC, text=False)[1]
if port == 0: # random
with contextlib.closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
s.bind((host, 0))
port = s.getsockname()[1]
logger.info("Running REST-JSON API server at '%s:%d'.." % (host, port))
logger.info("Admin ID: %s" % DataStore.admin_id)
logger.debug("IPC database: %s" % Database.filepath)
@@ -737,13 +745,34 @@ def client(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT):
if not res["success"]:
logger.error("Failed to execute command %s" % command)
dataToStdout("%s\n" % raw)
elif command.startswith("option"):
if not taskid:
logger.error("No task ID in use")
continue
try:
command, option = command.split(" ")
except ValueError:
raw = _client("%s/option/%s/list" % (addr, taskid))
else:
options = {"option": option}
raw = _client("%s/option/%s/get" % (addr, taskid), options)
res = dejsonize(raw)
if not res["success"]:
logger.error("Failed to execute command %s" % command)
dataToStdout("%s\n" % raw)
elif command.startswith("new"):
if ' ' not in command:
logger.error("Program arguments are missing")
continue
argv = ["sqlmap.py"] + shlex.split(command)[1:]
try:
argv = ["sqlmap.py"] + shlex.split(command)[1:]
except Exception, ex:
logger.error("Error occurred while parsing arguments ('%s')" % ex)
taskid = None
continue
try:
cmdLineOptions = cmdLineParser(argv).__dict__
@@ -795,17 +824,19 @@ def client(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT):
return
elif command in ("help", "?"):
msg = "help Show this help message\n"
msg += "new ARGS Start a new scan task with provided arguments (e.g. 'new -u \"http://testphp.vulnweb.com/artists.php?artist=1\"')\n"
msg += "use TASKID Switch current context to different task (e.g. 'use c04d8c5c7582efb4')\n"
msg += "data Retrieve and show data for current task\n"
msg += "log Retrieve and show log for current task\n"
msg += "status Retrieve and show status for current task\n"
msg += "stop Stop current task\n"
msg += "kill Kill current task\n"
msg += "list Display all tasks\n"
msg += "flush Flush tasks (delete all tasks)\n"
msg += "exit Exit this client\n"
msg = "help Show this help message\n"
msg += "new ARGS Start a new scan task with provided arguments (e.g. 'new -u \"http://testphp.vulnweb.com/artists.php?artist=1\"')\n"
msg += "use TASKID Switch current context to different task (e.g. 'use c04d8c5c7582efb4')\n"
msg += "data Retrieve and show data for current task\n"
msg += "log Retrieve and show log for current task\n"
msg += "status Retrieve and show status for current task\n"
msg += "option OPTION Retrieve and show option for current task\n"
msg += "options Retrieve and show all options for current task\n"
msg += "stop Stop current task\n"
msg += "kill Kill current task\n"
msg += "list Display all tasks\n"
msg += "flush Flush tasks (delete all tasks)\n"
msg += "exit Exit this client\n"
dataToStdout(msg)

View File

@@ -63,14 +63,14 @@ def crawl(target):
if current:
content = Request.getPage(url=current, crawling=True, raise404=False)[0]
except SqlmapConnectionException, ex:
errMsg = "connection exception detected (%s). skipping " % ex
errMsg = "connection exception detected (%s). skipping " % getSafeExString(ex)
errMsg += "URL '%s'" % current
logger.critical(errMsg)
except SqlmapSyntaxException:
errMsg = "invalid URL detected. skipping '%s'" % current
logger.critical(errMsg)
except httplib.InvalidURL, ex:
errMsg = "invalid URL detected (%s). skipping " % ex
errMsg = "invalid URL detected (%s). skipping " % getSafeExString(ex)
errMsg += "URL '%s'" % current
logger.critical(errMsg)

View File

@@ -41,7 +41,7 @@ def pivotDumpTable(table, colList, count=None, blind=True):
if count is None:
query = dumpNode.count % table
query = whereQuery(query)
query = agent.whereQuery(query)
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) if blind else inject.getValue(query, blind=False, time=False, expected=EXPECTED.INT)
if isinstance(count, basestring) and count.isdigit():
@@ -91,7 +91,7 @@ def pivotDumpTable(table, colList, count=None, blind=True):
logger.info(infoMsg)
query = dumpNode.count2 % (column, table)
query = whereQuery(query)
query = agent.whereQuery(query)
value = inject.getValue(query, blind=blind, union=not blind, error=not blind, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if isNumPosStrValue(value):
@@ -125,7 +125,7 @@ def pivotDumpTable(table, colList, count=None, blind=True):
else:
query = dumpNode.query2.replace("'%s'", "%s") % (agent.preprocessField(table, column), table, agent.preprocessField(table, colList[0]), unescaper.escape(pivotValue, False))
query = whereQuery(query)
query = agent.whereQuery(query)
return unArrayizeValue(inject.getValue(query, blind=blind, time=blind, union=not blind, error=not blind))
try:
@@ -179,18 +179,3 @@ def pivotDumpTable(table, colList, count=None, blind=True):
logger.critical(errMsg)
return entries, lengths
def whereQuery(query):
if conf.dumpWhere and query:
prefix, suffix = query.split(" ORDER BY ") if " ORDER BY " in query else (query, "")
if "%s)" % conf.tbl.upper() in prefix.upper():
prefix = re.sub(r"(?i)%s\)" % re.escape(conf.tbl), "%s WHERE %s)" % (conf.tbl, conf.dumpWhere), prefix)
elif re.search(r"(?i)\bWHERE\b", prefix):
prefix += " AND %s" % conf.dumpWhere
else:
prefix += " WHERE %s" % conf.dumpWhere
query = "%s ORDER BY %s" % (prefix, suffix) if suffix else prefix
return query

View File

@@ -18,6 +18,6 @@ try:
__import__(_)
except ImportError:
errMsg = "missing one or more core extensions (%s) " % (", ".join("'%s'" % _ for _ in extensions))
errMsg += "most probably because current version of Python has been "
errMsg += "most likely because current version of Python has been "
errMsg += "built without appropriate dev packages (e.g. 'libsqlite3-dev')"
exit(errMsg)

View File

@@ -146,7 +146,7 @@ class Fingerprint(GenericFingerprint):
return value
def checkDbms(self):
if not conf.extensiveFp and (Backend.isDbmsWithin(ACCESS_ALIASES) or (conf.dbms or "").lower() in ACCESS_ALIASES):
if not conf.extensiveFp and Backend.isDbmsWithin(ACCESS_ALIASES):
setDbms(DBMS.ACCESS)
return True

View File

@@ -18,4 +18,3 @@ class Enumeration(GenericEnumeration):
logger.warn(warnMsg)
return {}

View File

@@ -81,7 +81,7 @@ class Fingerprint(GenericFingerprint):
return value
def checkDbms(self):
if not conf.extensiveFp and (Backend.isDbmsWithin(DB2_ALIASES) or (conf.dbms or "").lower() in DB2_ALIASES):
if not conf.extensiveFp and Backend.isDbmsWithin(DB2_ALIASES):
setDbms(DBMS.DB2)
return True

View File

@@ -103,9 +103,7 @@ class Fingerprint(GenericFingerprint):
return retVal
def checkDbms(self):
if not conf.extensiveFp and (Backend.isDbmsWithin(FIREBIRD_ALIASES) \
or (conf.dbms or "").lower() in FIREBIRD_ALIASES) and Backend.getVersion() and \
Backend.getVersion() != UNKNOWN_DBMS_VERSION:
if not conf.extensiveFp and Backend.isDbmsWithin(FIREBIRD_ALIASES):
setDbms("%s %s" % (DBMS.FIREBIRD, Backend.getVersion()))
self.getBanner()

View File

@@ -80,9 +80,7 @@ class Fingerprint(GenericFingerprint):
"""
if not conf.extensiveFp and (Backend.isDbmsWithin(HSQLDB_ALIASES) \
or (conf.dbms or "").lower() in HSQLDB_ALIASES) and Backend.getVersion() and \
Backend.getVersion() != UNKNOWN_DBMS_VERSION:
if not conf.extensiveFp and Backend.isDbmsWithin(HSQLDB_ALIASES):
setDbms("%s %s" % (DBMS.HSQLDB, Backend.getVersion()))
if Backend.isVersionGreaterOrEqualThan("1.7.2"):

View File

@@ -56,7 +56,7 @@ class Fingerprint(GenericFingerprint):
return value
def checkDbms(self):
if not conf.extensiveFp and (Backend.isDbmsWithin(INFORMIX_ALIASES) or (conf.dbms or "").lower() in INFORMIX_ALIASES):
if not conf.extensiveFp and Backend.isDbmsWithin(INFORMIX_ALIASES):
setDbms(DBMS.INFORMIX)
self.getBanner()

View File

@@ -91,7 +91,7 @@ class Fingerprint(GenericFingerprint):
return value
def checkDbms(self):
if not conf.extensiveFp and (Backend.isDbmsWithin(MAXDB_ALIASES) or (conf.dbms or "").lower() in MAXDB_ALIASES):
if not conf.extensiveFp and Backend.isDbmsWithin(MAXDB_ALIASES):
setDbms(DBMS.MAXDB)
self.getBanner()

View File

@@ -65,9 +65,7 @@ class Fingerprint(GenericFingerprint):
return value
def checkDbms(self):
if not conf.extensiveFp and (Backend.isDbmsWithin(MSSQL_ALIASES) \
or (conf.dbms or "").lower() in MSSQL_ALIASES) and Backend.getVersion() and \
Backend.getVersion().isdigit():
if not conf.extensiveFp and Backend.isDbmsWithin(MSSQL_ALIASES):
setDbms("%s %s" % (DBMS.MSSQL, Backend.getVersion()))
self.getBanner()

View File

@@ -46,12 +46,12 @@ class Fingerprint(GenericFingerprint):
(32300, 32359), # MySQL 3.23
(40000, 40032), # MySQL 4.0
(40100, 40131), # MySQL 4.1
(50000, 50092), # MySQL 5.0
(50000, 50096), # MySQL 5.0
(50100, 50172), # MySQL 5.1
(50400, 50404), # MySQL 5.4
(50500, 50552), # MySQL 5.5
(50600, 50633), # MySQL 5.6
(50700, 50715), # MySQL 5.7
(50500, 50554), # MySQL 5.5
(50600, 50635), # MySQL 5.6
(50700, 50717), # MySQL 5.7
(60000, 60014), # MySQL 6.0
)
@@ -150,9 +150,7 @@ class Fingerprint(GenericFingerprint):
* http://dev.mysql.com/doc/refman/6.0/en/news-6-0-x.html (manual has been withdrawn)
"""
if not conf.extensiveFp and (Backend.isDbmsWithin(MYSQL_ALIASES) \
or (conf.dbms or "").lower() in MYSQL_ALIASES) and Backend.getVersion() and \
Backend.getVersion() != UNKNOWN_DBMS_VERSION:
if not conf.extensiveFp and Backend.isDbmsWithin(MYSQL_ALIASES):
setDbms("%s %s" % (DBMS.MYSQL, Backend.getVersion()))
if Backend.isVersionGreaterOrEqualThan("5"):

View File

@@ -58,7 +58,7 @@ class Fingerprint(GenericFingerprint):
return value
def checkDbms(self):
if not conf.extensiveFp and (Backend.isDbmsWithin(ORACLE_ALIASES) or (conf.dbms or "").lower() in ORACLE_ALIASES):
if not conf.extensiveFp and Backend.isDbmsWithin(ORACLE_ALIASES):
setDbms(DBMS.ORACLE)
self.getBanner()

View File

@@ -63,7 +63,7 @@ class Fingerprint(GenericFingerprint):
* http://www.postgresql.org/docs/9.1/interactive/release.html (up to 9.1.3)
"""
if not conf.extensiveFp and (Backend.isDbmsWithin(PGSQL_ALIASES) or (conf.dbms or "").lower() in PGSQL_ALIASES):
if not conf.extensiveFp and Backend.isDbmsWithin(PGSQL_ALIASES):
setDbms(DBMS.PGSQL)
self.getBanner()

View File

@@ -64,7 +64,7 @@ class Fingerprint(GenericFingerprint):
* http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions
"""
if not conf.extensiveFp and (Backend.isDbmsWithin(SQLITE_ALIASES) or (conf.dbms or "").lower() in SQLITE_ALIASES):
if not conf.extensiveFp and Backend.isDbmsWithin(SQLITE_ALIASES):
setDbms(DBMS.SQLITE)
self.getBanner()

View File

@@ -58,9 +58,7 @@ class Fingerprint(GenericFingerprint):
return value
def checkDbms(self):
if not conf.extensiveFp and (Backend.isDbmsWithin(SYBASE_ALIASES) \
or (conf.dbms or "").lower() in SYBASE_ALIASES) and Backend.getVersion() and \
Backend.getVersion().isdigit():
if not conf.extensiveFp and Backend.isDbmsWithin(SYBASE_ALIASES):
setDbms("%s %s" % (DBMS.SYBASE, Backend.getVersion()))
self.getBanner()

View File

@@ -11,6 +11,7 @@ from lib.core.data import conf
from lib.core.data import logger
from lib.core.exception import SqlmapFilePathException
from lib.core.exception import SqlmapUndefinedMethod
from lib.core.settings import UNICODE_ENCODING
class Connector:
"""
@@ -22,8 +23,8 @@ class Connector:
self.cursor = None
def initConnection(self):
self.user = conf.dbmsUser
self.password = conf.dbmsPass if conf.dbmsPass is not None else ""
self.user = conf.dbmsUser.encode(UNICODE_ENCODING) if conf.dbmsUser is not None else ""
self.password = conf.dbmsPass.encode(UNICODE_ENCODING) if conf.dbmsPass is not None else ""
self.hostname = conf.hostname
self.port = conf.port
self.db = conf.dbmsDb

View File

@@ -43,7 +43,6 @@ from lib.core.settings import NULL
from lib.request import inject
from lib.utils.hash import attackDumpedTable
from lib.utils.pivotdumptable import pivotDumpTable
from lib.utils.pivotdumptable import whereQuery
class Entries:
"""
@@ -190,10 +189,17 @@ class Entries:
else:
query = rootQuery.inband.query % (colString, conf.db, tbl)
query = whereQuery(query)
query = agent.whereQuery(query)
if not entries and query:
entries = inject.getValue(query, blind=False, time=False, dump=True)
try:
entries = inject.getValue(query, blind=False, time=False, dump=True)
except KeyboardInterrupt:
entries = None
kb.dumpKeyboardInterrupt = True
clearConsoleLine()
warnMsg = "Ctrl+C detected in dumping phase"
logger.warn(warnMsg)
if not isNoneValue(entries):
if isinstance(entries, basestring):
@@ -244,7 +250,7 @@ class Entries:
else:
query = rootQuery.blind.count % (conf.db, tbl)
query = whereQuery(query)
query = agent.whereQuery(query)
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
@@ -329,7 +335,7 @@ class Entries:
elif Backend.isDbms(DBMS.INFORMIX):
query = rootQuery.blind.query % (index, agent.preprocessField(tbl, column), conf.db, tbl, sorted(colList, key=len)[0])
query = whereQuery(query)
query = agent.whereQuery(query)
value = NULL if column in emptyColumns else inject.getValue(query, union=False, error=False, dump=True)
value = '' if value is None else value

View File

@@ -120,6 +120,8 @@ class Filesystem:
back-end DBMS underlying file system
"""
checkFile(fileName)
with open(fileName, "rb") as f:
content = f.read()

View File

@@ -512,13 +512,13 @@ excludeSysDbs = False
# First query output entry to retrieve
# Valid: integer
# Default: 0 (sqlmap will start to retrieve the query output entries from
# the first)
# Default: 0 (sqlmap will start to retrieve the table dump entries from
# first one)
limitStart = 0
# Last query output entry to retrieve
# Valid: integer
# Default: 0 (sqlmap will detect the number of query output entries and
# Default: 0 (sqlmap will detect the number of table dump entries and
# retrieve them until the last)
limitStop = 0
@@ -779,10 +779,6 @@ mobile = False
# Valid: True or False
offline = False
# Display page rank (PR) for Google dork results.
# Valid: True or False
pageRank = False
# Skip heuristic detection of WAF/IPS/IDS protection.
# Valid: True or False
skipWaf = False
@@ -794,6 +790,9 @@ smart = False
# Local directory for storing temporary files.
tmpDir =
# Web server document root directory (e.g. "/var/www").
webRoot =
# Simple wizard interface for beginner users.
# Valid: True or False
wizard = False

View File

@@ -5,6 +5,8 @@ Copyright (c) 2006-2017 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
import re
from lib.core.common import zeroDepthSearch
from lib.core.enums import PRIORITY
@@ -28,6 +30,9 @@ def tamper(payload, **kwargs):
>>> tamper('SELECT CHAR(113)+CHAR(114)+CHAR(115) FROM DUAL')
'SELECT CONCAT(CHAR(113),CHAR(114),CHAR(115)) FROM DUAL'
>>> tamper('SELECT (CHAR(113)+CHAR(114)+CHAR(115)) FROM DUAL')
'SELECT CONCAT(CHAR(113),CHAR(114),CHAR(115)) FROM DUAL'
"""
retVal = payload
@@ -35,6 +40,7 @@ def tamper(payload, **kwargs):
if payload:
while True:
indexes = zeroDepthSearch(retVal, '+')
if indexes:
first, last = 0, 0
for i in xrange(1, len(indexes)):
@@ -52,6 +58,19 @@ def tamper(payload, **kwargs):
retVal = "%sCONCAT(%s)%s" % (retVal[:start], ''.join(chars)[start:end], retVal[end:])
else:
break
match = re.search(r"\((CHAR\(\d+.+CHAR\(\d+\))\)", retVal)
if match:
part = match.group(0)
indexes = set(zeroDepthSearch(match.group(1), '+'))
if not indexes:
break
chars = [char for char in part]
for i in xrange(1, len(chars)):
if i - 1 in indexes:
chars[i] = ','
replacement = "CONCAT%s" % "".join(chars)
retVal = retVal.replace(part, replacement)
else:
break
return retVal

89
tamper/plus2fnconcat.py Normal file
View File

@@ -0,0 +1,89 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2017 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
import re
from lib.core.common import zeroDepthSearch
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.HIGHEST
def dependencies():
pass
def tamper(payload, **kwargs):
"""
Replaces plus ('+') character with ODBC function {fn CONCAT()}
Tested against:
* Microsoft SQL Server 2008
Requirements:
* Microsoft SQL Server 2008+
Notes:
* Useful in case ('+') character is filtered
* https://msdn.microsoft.com/en-us/library/bb630290.aspx
>>> tamper('SELECT CHAR(113)+CHAR(114)+CHAR(115) FROM DUAL')
'SELECT {fn CONCAT({fn CONCAT(CHAR(113),CHAR(114))},CHAR(115))} FROM DUAL'
>>> tamper('SELECT (CHAR(113)+CHAR(114)+CHAR(115)) FROM DUAL')
'SELECT {fn CONCAT({fn CONCAT(CHAR(113),CHAR(114))},CHAR(115))} FROM DUAL'
"""
retVal = payload
if payload:
while True:
indexes = zeroDepthSearch(retVal, '+')
if indexes:
first, last = 0, 0
for i in xrange(1, len(indexes)):
if ' ' in retVal[indexes[0]:indexes[i]]:
break
else:
last = i
start = retVal[:indexes[first]].rfind(' ') + 1
end = (retVal[indexes[last] + 1:].find(' ') + indexes[last] + 1) if ' ' in retVal[indexes[last] + 1:] else len(retVal) - 1
count = 0
chars = [char for char in retVal]
for index in indexes[first:last + 1]:
if count == 0:
chars[index] = ','
else:
chars[index] = '\x01'
count += 1
retVal = "%s%s%s)}%s" % (retVal[:start], "{fn CONCAT(" * count, ''.join(chars)[start:end].replace('\x01', ")},"), retVal[end:])
else:
match = re.search(r"\((CHAR\(\d+.+CHAR\(\d+\))\)", retVal)
if match:
part = match.group(0)
indexes = set(zeroDepthSearch(match.group(1), '+'))
if not indexes:
break
count = 0
chars = [char for char in part]
for i in xrange(1, len(chars)):
if i - 1 in indexes:
if count == 0:
chars[i] = ','
else:
chars[i] = '\x01'
count += 1
replacement = "%s%s}" % (("{fn CONCAT(" * count)[:-1], "".join(chars).replace('\x01', ")},"))
retVal = retVal.replace(part, replacement)
else:
break
return retVal

View File

@@ -0,0 +1,54 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2017 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOW
def dependencies():
pass
def tamper(payload, **kwargs):
"""
Replaces space character (' ') with comments '/**_**/'
Tested against:
* MySQL 5.0 and 5.5
Notes:
* Useful to bypass weak and bespoke web application firewalls
>>> tamper('SELECT id FROM users')
'SELECT/**_**/id/**_**/FROM/**_**/users'
"""
retVal = payload
if payload:
retVal = ""
quote, doublequote, firstspace = False, False, False
for i in xrange(len(payload)):
if not firstspace:
if payload[i].isspace():
firstspace = True
retVal += "/**_**/"
continue
elif payload[i] == '\'':
quote = not quote
elif payload[i] == '"':
doublequote = not doublequote
elif payload[i] == " " and not doublequote and not quote:
retVal += "/**_**/"
continue
retVal += payload[i]
return retVal

View File

@@ -1,26 +0,0 @@
#!/usr/bin/env python
#
# The MIT License
#
# Copyright 2010 Corey Goldberg
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
pass

View File

@@ -1,87 +0,0 @@
#!/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
#
# important update (http://www.seroundtable.com/google-pagerank-change-14132.html)
# by Miroslav Stampar - 2012
#
# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
import sys
import urllib
import urllib2
def get_pagerank(url, timeout=10):
url = url.encode('utf8') if isinstance(url, unicode) else url
_ = 'http://toolbarqueries.google.com/tbr?client=navclient-auto&features=Rank&ch=%s&q=info:%s' % (check_hash(hash_url(url)), urllib.quote(url))
try:
req = urllib2.Request(_)
rank = urllib2.urlopen(req, timeout=timeout).read().strip()[9:]
except:
rank = 'N/A'
else:
rank = '0' if not rank or not rank.isdigit() else rank
return rank
def int_str(string_, integer, factor):
for i in xrange(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
def main():
print get_pagerank(sys.argv[1]) if len(sys.argv) > 1 else "[x] missing hostname"
if __name__ == "__main__":
main()

View File

@@ -20,13 +20,13 @@ c55b400b72acc43e0e59c87dd8bb8d75 extra/shellcodeexec/windows/shellcodeexec.x32.
310efc965c862cfbd7b0da5150a5ad36 extra/sqlharvest/__init__.py
7713aa366c983cdf1f3dbaa7383ea9e1 extra/sqlharvest/sqlharvest.py
5df358defc488bee9b40084892e3d1cb lib/controller/action.py
699fd4757390aedb5ad17f4316d17972 lib/controller/checks.py
10edc8d1057e89c145218d4c5ccaaa31 lib/controller/controller.py
b3eec7f44bcc5d784d171a187b7fe8cb lib/controller/handler.py
9cb94acd4c59822a5e1a258c4d1a4860 lib/controller/checks.py
dc386321e8813788f155dc557a78be8d lib/controller/controller.py
d79481ab99acd739615e747d4a79d9d0 lib/controller/handler.py
310efc965c862cfbd7b0da5150a5ad36 lib/controller/__init__.py
178066b5737f0e719cbf9271051559a2 lib/core/agent.py
19905ecb4437b94512cf21d5f1720091 lib/core/agent.py
6cc95a117fbd34ef31b9aa25520f0e31 lib/core/bigarray.py
445bd2c2fe0dcca0dd3aab87eb3839d3 lib/core/common.py
145d131884dd5401d7a52effaea2ee9e lib/core/common.py
5065a4242a8cccf72f91e22e1007ae63 lib/core/convert.py
a8143dab9d3a27490f7d49b6b29ea530 lib/core/data.py
7936d78b1a7f1f008ff92bf2f88574ba lib/core/datatype.py
@@ -34,30 +34,30 @@ a8143dab9d3a27490f7d49b6b29ea530 lib/core/data.py
47eecd5499eaa15e931793e1d1ac3566 lib/core/defaults.py
4029f6869b36eb5f796c2bcc948f4fae lib/core/dicts.py
77edcfd3d7c5522bb64baf59ac23a047 lib/core/dump.py
0c0f18761e9bb61d289bfa884dcd7dbd lib/core/enums.py
2acf5449c71bfae4feec8da538e70116 lib/core/enums.py
9381a0c7e8bc19986299e84f4edda1a0 lib/core/exception.py
310efc965c862cfbd7b0da5150a5ad36 lib/core/__init__.py
9ba39bf66e9ecd469446bdbbeda906c3 lib/core/log.py
e544108e2238d756c94a240e8a1ce061 lib/core/optiondict.py
44a61841bcd0bafc4151e31d5a14287d lib/core/option.py
66c9795e2e7da32f46f04497ae910070 lib/core/optiondict.py
0324fce84ef88ed0416123f73c54a6d7 lib/core/option.py
5f2f56e6c5f274408df61943f1e080c0 lib/core/profiling.py
40be71cd774662a7b420caeb7051e7d5 lib/core/readlineng.py
d8e9250f3775119df07e9070eddccd16 lib/core/replication.py
785f86e3f963fa3798f84286a4e83ff2 lib/core/revision.py
40c80b28b3a5819b737a5a17d4565ae9 lib/core/session.py
75d8ca625f08e39702965b2b3569b5d8 lib/core/settings.py
50edc9861e7441371210f5fae263207c lib/core/settings.py
d91291997d2bd2f6028aaf371bf1d3b6 lib/core/shell.py
2ad85c130cc5f2b3701ea85c2f6bbf20 lib/core/subprocessng.py
afd0636d2e93c23f4f0a5c9b6023ea17 lib/core/target.py
8970b88627902239d695280b1160e16c lib/core/testing.py
ce5578a2e6b25dc6fd115133f92e0643 lib/core/threads.py
5521241c750855a4e44747fbac7771c6 lib/core/threads.py
ad74fc58fc7214802fd27067bce18dd2 lib/core/unescaper.py
1f1fa616b5b19308d78c610ec8046399 lib/core/update.py
4d13ed693401a498b6d073a2a494bd83 lib/core/wordlist.py
310efc965c862cfbd7b0da5150a5ad36 lib/__init__.py
8c4b04062db2245d9e190b413985202a lib/parse/banner.py
7af43d486b7183862b932218ed4c988d lib/parse/cmdline.py
1a71306c965d563ae2d01e4c48646030 lib/parse/configfile.py
54f06c50771ce894a3c6a418d545f4bf lib/parse/cmdline.py
3a31657bc38f277d0016ff6d50bde61f lib/parse/configfile.py
14539f1be714d4f1ed042067d63bc50a lib/parse/handler.py
64e5bb3ecbdd75144500588b437ba8da lib/parse/headers.py
165dc27660c8559318009d44354f27cb lib/parse/html.py
@@ -65,9 +65,9 @@ ad74fc58fc7214802fd27067bce18dd2 lib/core/unescaper.py
0b010b7cdb2e42b5aa0caa59607279ad lib/parse/payloads.py
a0444cc351cd6d29015ad16d9eb46ff4 lib/parse/sitemap.py
403d873f1d2fd0c7f73d83f104e41850 lib/request/basicauthhandler.py
c347898f7b2e3d59d0a108b16b0542a3 lib/request/basic.py
4e89d0e13de2eb3576f5412b21e9b648 lib/request/comparison.py
30d7b0df341762c5aa7aab537878ce05 lib/request/connect.py
0035612a620934d7ebe6d18426cfb065 lib/request/basic.py
ef48de622b0a6b4a71df64b0d2785ef8 lib/request/comparison.py
74a2a83e3af11ab02088c79b6367ef29 lib/request/connect.py
fb6b788d0016ab4ec5e5f661f0f702ad lib/request/direct.py
cc1163d38e9b7ee5db2adac6784c02bb lib/request/dns.py
5dcdb37823a0b5eff65cd1018bcf09e4 lib/request/httpshandler.py
@@ -76,20 +76,20 @@ e68e1f00c7bb47b2c4ea6201995c56fb lib/request/inject.py
dc1e0af84ee8eb421797d61c8cb8f172 lib/request/methodrequest.py
bb9c165b050f7696b089b96b5947fac3 lib/request/pkihandler.py
602d4338a9fceaaee40c601410d8ac0b lib/request/rangehandler.py
e687a727b641211dfae7346b671059c5 lib/request/redirecthandler.py
b581e0c5e27cd927883f2c7f1705bf4e lib/request/redirecthandler.py
20a0e6dac2edcf98fa8c47ee9a332c28 lib/request/templates.py
36518b36ae0cf199490457916a85b367 lib/takeover/abstraction.py
c6bc7961a186baabe0a9f5b7e0d8974b lib/takeover/icmpsh.py
310efc965c862cfbd7b0da5150a5ad36 lib/takeover/__init__.py
71d45fd7f11804872284ee3ae5e60970 lib/takeover/metasploit.py
c90c993b020a6ae0f0e497fd84f37466 lib/takeover/metasploit.py
ac541a0d38e4ecb4e41e97799a7235f4 lib/takeover/registry.py
4cd0322f22fbc26284cffa9f8f7545ef lib/takeover/udf.py
a610e0ef2fb8512604c2b6c081174850 lib/takeover/web.py
ab021269ad7f4d552025448ae08c51d0 lib/takeover/web.py
e5a82481947e798d0c11f3acf3e9db60 lib/takeover/xp_cmdshell.py
cae752650755c706272a45ae84519a4b lib/techniques/blind/inference.py
310efc965c862cfbd7b0da5150a5ad36 lib/techniques/blind/__init__.py
310efc965c862cfbd7b0da5150a5ad36 lib/techniques/brute/__init__.py
b24fa5fe58828e00a84991015c561f59 lib/techniques/brute/use.py
a693c023a9fed1eebb9ca9ef51e0aeb8 lib/techniques/brute/use.py
310efc965c862cfbd7b0da5150a5ad36 lib/techniques/dns/__init__.py
ab1601a7f429b47637c4fb8af703d0f1 lib/techniques/dns/test.py
d3da4c7ceaf57c4687a052d58722f6bb lib/techniques/dns/use.py
@@ -97,56 +97,56 @@ d3da4c7ceaf57c4687a052d58722f6bb lib/techniques/dns/use.py
2fb0eb698fc9d6e19960d2136bce787d lib/techniques/error/use.py
310efc965c862cfbd7b0da5150a5ad36 lib/techniques/__init__.py
310efc965c862cfbd7b0da5150a5ad36 lib/techniques/union/__init__.py
4bed3ed51faad9b910899cacf56e8eac lib/techniques/union/test.py
19fd73af7a278fd72b46a5a60f5bdd09 lib/techniques/union/test.py
8cd5655c60a638caa30ca1220896aeda lib/techniques/union/use.py
b3afde39a56dd767f5338ba6464b9f43 lib/utils/api.py
6842092e1d27b71d28acd0e421f90693 lib/utils/crawler.py
b8c9bbf1a50f1b2fdd0d3644922e252a lib/utils/api.py
29e32d59fcdd63c5a13498af1f367c8c lib/utils/crawler.py
ba12c69a90061aa14d848b8396e79191 lib/utils/deps.py
3b9fd519164e0bf275d5fd361c3f11ff lib/utils/getch.py
ccfdad414ce2ec0c394c3deaa39a82bf lib/utils/hashdb.py
aff7355d582fc6c00a675eeee2a5217a lib/utils/hash.py
e76a08237ee6a4cd6855af79610ea8a5 lib/utils/htmlentities.py
310efc965c862cfbd7b0da5150a5ad36 lib/utils/__init__.py
8e4ecc5e5bd8a5c7e2ad0a940cb1a5b1 lib/utils/pivotdumptable.py
9d8c858417d356e49e1959ba253aede4 lib/utils/pivotdumptable.py
8520a745c9b4db3814fe46f4c34c6fbc lib/utils/progress.py
2c3638d499f3c01c34187e531f77d004 lib/utils/purge.py
2da1b35339667646e51101adaa1dfc32 lib/utils/search.py
569521a83b2b6c62497879267b963b21 lib/utils/sqlalchemy.py
caeea96ec9c9d489f615f282259b32ca lib/utils/timeout.py
0b84e74f9eb7681bab7364617e2f2577 lib/utils/versioncheck.py
6fa36b9742293756b226cddee11b7d52 lib/utils/versioncheck.py
31c51a3cc73120ee9490f2e3fa6d0dca lib/utils/xrange.py
b90aae84100a6c4c2bd5eeb4197fbc6e plugins/dbms/access/connector.py
a71f7c8ffcb9b250cc785cad830e8980 plugins/dbms/access/enumeration.py
38a0c758d9b86915fce894b779e79e4d plugins/dbms/access/filesystem.py
818482929a68a270bc4331cf6c436d13 plugins/dbms/access/fingerprint.py
fe34217a0b79ac25e3af007dd46cd340 plugins/dbms/access/fingerprint.py
5a691580a59eca29bae2283b57682025 plugins/dbms/access/__init__.py
c12f4f266830636462eac98e35ebb73e plugins/dbms/access/syntax.py
3fc75c350a30597962bc692c973eeeb3 plugins/dbms/access/takeover.py
a763887d6e6e99c5a73d9cf450cd84fe plugins/dbms/db2/connector.py
c1f6eeb6fccbcb75b53566568c582e9c plugins/dbms/db2/enumeration.py
9d54e01e1576a423159f0e47aeb2837a plugins/dbms/db2/enumeration.py
667e50aa06883f0f194bef335015d694 plugins/dbms/db2/filesystem.py
d82e641f156d7c0fe015510a2f593b16 plugins/dbms/db2/fingerprint.py
9c6ef13c056a256e4704b924af0d7cc6 plugins/dbms/db2/fingerprint.py
35ed6e262cf68d4ab2c6111dd5fb0414 plugins/dbms/db2/__init__.py
ce8bc86383f2ade41e08f2dbee1844bf plugins/dbms/db2/syntax.py
744fb5044f2b9f9d5ebda6e3f08e3be7 plugins/dbms/db2/takeover.py
b8dcd6e97166f58ee452e68c46bfe2c4 plugins/dbms/firebird/connector.py
147afe5f4a3d09548a8a1dbc954fe29e plugins/dbms/firebird/enumeration.py
4e421504f59861bf1ed1a89abda583d1 plugins/dbms/firebird/filesystem.py
fc6fdb1fb1be84db541995c87746efe1 plugins/dbms/firebird/fingerprint.py
bbd239cd27b35c2fbd29443f0af5d973 plugins/dbms/firebird/fingerprint.py
f86ace7fcaea5ff3f9e86ab2dce052c5 plugins/dbms/firebird/__init__.py
04f7c2977ab5198c6f4aa6233b872ae0 plugins/dbms/firebird/syntax.py
1cb1ab93e4b8c97e81586acfe4d030a2 plugins/dbms/firebird/takeover.py
3a97bd07cce66bc812309341e7b54697 plugins/dbms/hsqldb/connector.py
015281fb8f96dbade0d2e30fc8da9c4c plugins/dbms/hsqldb/enumeration.py
c0b14e62e1ecbb679569a1abb9cf1913 plugins/dbms/hsqldb/filesystem.py
205ec651547b3fef04afc9580ab35672 plugins/dbms/hsqldb/fingerprint.py
82304c5d7b06bb564dcdd8cda84dbeae plugins/dbms/hsqldb/fingerprint.py
0b18e3cf582b128cf9f16ee34ef85727 plugins/dbms/hsqldb/__init__.py
65e8f8edc9d18fe482deb474a29f83ff plugins/dbms/hsqldb/syntax.py
0a1584e2b01f33abe3ef91d99bafbd3f plugins/dbms/hsqldb/takeover.py
f8eaeb71239369e6ceff47596439871b plugins/dbms/informix/connector.py
989e75a65503dd648a45258217ae3371 plugins/dbms/informix/enumeration.py
667e50aa06883f0f194bef335015d694 plugins/dbms/informix/filesystem.py
df241894bc46576590fae7809650aa58 plugins/dbms/informix/fingerprint.py
f06d263b2c9b52ea7a120593eb5806c4 plugins/dbms/informix/fingerprint.py
859d2ed1e0c1b8a1b92c8b2044e6afc5 plugins/dbms/informix/__init__.py
0aa8ec7b83435a1ecec19c5320728051 plugins/dbms/informix/syntax.py
744fb5044f2b9f9d5ebda6e3f08e3be7 plugins/dbms/informix/takeover.py
@@ -154,58 +154,58 @@ df241894bc46576590fae7809650aa58 plugins/dbms/informix/fingerprint.py
e50b624ff23c3e180d80e065deb1763f plugins/dbms/maxdb/connector.py
cbd90f22ce862409fe392e65f0ea94ac plugins/dbms/maxdb/enumeration.py
815ea8e7b9bd714d73d9d6c454aff774 plugins/dbms/maxdb/filesystem.py
30ace2bbd22cf6152e4a7e9d8176bdc1 plugins/dbms/maxdb/fingerprint.py
017c723354eff28188773670d3837c01 plugins/dbms/maxdb/fingerprint.py
c03001c1f70e76de39d26241dfcbd033 plugins/dbms/maxdb/__init__.py
e6036f5b2e39aec37ba036a8cf0efd6f plugins/dbms/maxdb/syntax.py
0be362015605e26551e5d79cc83ed466 plugins/dbms/maxdb/takeover.py
e3e78fab9b5eb97867699f0b20e59b62 plugins/dbms/mssqlserver/connector.py
a7ed0510e47384eaf93164d53e2b6b36 plugins/dbms/mssqlserver/enumeration.py
8554437c437052c30237be170ba8ce3a plugins/dbms/mssqlserver/filesystem.py
4e4bb17dfb175b5f6485d7513e4c8fb1 plugins/dbms/mssqlserver/fingerprint.py
13cb15e8abfb05818e6f66c687b78664 plugins/dbms/mssqlserver/fingerprint.py
40bd890988f9acd3942255d687445371 plugins/dbms/mssqlserver/__init__.py
400ce654ff6bc57a40fb291322a18282 plugins/dbms/mssqlserver/syntax.py
20c669e084ea4d6b968a5834f7fec66c plugins/dbms/mssqlserver/takeover.py
48fb283a0dbf980495ca054f7b55783f plugins/dbms/mysql/connector.py
7fe94b803fa273baf479b76ce7a3fb51 plugins/dbms/mysql/enumeration.py
1bd5e659962e814b66a451b807de9110 plugins/dbms/mysql/filesystem.py
e9076fe684eb3fe037f945601c7017f0 plugins/dbms/mysql/fingerprint.py
1a17c2dea2cd7554cf9082fdf96f8360 plugins/dbms/mysql/fingerprint.py
42568a66a13a43ed46748290c503a652 plugins/dbms/mysql/__init__.py
96dfafcc4aecc1c574148ac05dbdb6da plugins/dbms/mysql/syntax.py
33b2dc28075ab560fd8a4dc898682a0d plugins/dbms/mysql/takeover.py
ea4b9cd238075b79945bd2607810934a plugins/dbms/oracle/connector.py
3a08ef0037de6df9f9a92ec5b126d705 plugins/dbms/oracle/enumeration.py
dc5962a1d4d69d4206b6c03e00e7f33d plugins/dbms/oracle/filesystem.py
d19215a6aee5d04d67ee67eb2cac9893 plugins/dbms/oracle/fingerprint.py
525381f48505095b14e567c1f59ca9c7 plugins/dbms/oracle/fingerprint.py
25a99a9dd7072b6b7346438599c78050 plugins/dbms/oracle/__init__.py
783d4795fac75f73a7cfba3cd9c3d01c plugins/dbms/oracle/syntax.py
c05176f6efe66069756fb78dfa0ed3f6 plugins/dbms/oracle/takeover.py
e087d54b9b2617a9f40be15a2bd478c2 plugins/dbms/postgresql/connector.py
8377c5ab3de500f9a495fcd9e2a75d3e plugins/dbms/postgresql/enumeration.py
48822058c620ffaa2acc599b4d39c667 plugins/dbms/postgresql/filesystem.py
1d514afa3106fa5fbd6fa2dd33970917 plugins/dbms/postgresql/fingerprint.py
c10df993e8b243ba3d6a94e8ae28a875 plugins/dbms/postgresql/fingerprint.py
a3a4e82e9a68329c44762897c87acfec plugins/dbms/postgresql/__init__.py
76bde1ffb3040ae709156449a583e9ed plugins/dbms/postgresql/syntax.py
286f95526a6ce0b8ae9bff6fc3117af0 plugins/dbms/postgresql/takeover.py
719fdd12e360458e822950f245d67ad0 plugins/dbms/sqlite/connector.py
28b9d7d0614e52275a30b5a57fc76027 plugins/dbms/sqlite/enumeration.py
954e503cfc8dd1acf9fc50868f5dafb0 plugins/dbms/sqlite/filesystem.py
60febaa44bd2fe5919e80e3bd7f0c2dd plugins/dbms/sqlite/fingerprint.py
ee430d142fa8f9ee571578d0a0916679 plugins/dbms/sqlite/fingerprint.py
6b17cc8cc94a912a0a5cf15acbad5ba4 plugins/dbms/sqlite/__init__.py
4827722159a89652005f49265bb55c43 plugins/dbms/sqlite/syntax.py
02ab8ff465da9dd31ffe6a963c676180 plugins/dbms/sqlite/takeover.py
e3e78fab9b5eb97867699f0b20e59b62 plugins/dbms/sybase/connector.py
a7f4d3a194f52fbb4fb4488be41273b1 plugins/dbms/sybase/enumeration.py
62d772c7cd08275e3503304ba90c4e8a plugins/dbms/sybase/filesystem.py
9e3e9a1f8dd491a95e833155a4157662 plugins/dbms/sybase/fingerprint.py
deed74334b637767fc9de8f74b37647a plugins/dbms/sybase/fingerprint.py
45436a42c2bb8075e1482a950d993d55 plugins/dbms/sybase/__init__.py
89412a921c8c598c19d36762d5820f05 plugins/dbms/sybase/syntax.py
654cd5e69cf5e5c644bfa5d284e61206 plugins/dbms/sybase/takeover.py
1f46f2eac95cfdc3fa150ec5b0500eba plugins/generic/connector.py
be7481a96214220bcd8f51ca00239bed plugins/generic/connector.py
a8f9d0516509e9e4226516ab4f13036a plugins/generic/custom.py
3b54fd65feb9f70c551d315e82653384 plugins/generic/databases.py
085f839221138aa7931bd94c33a32768 plugins/generic/entries.py
f7387352380136ac05c0bc3decb85638 plugins/generic/entries.py
55802d1d5d65938414c77ccc27731cab plugins/generic/enumeration.py
b6666109aa6882ca9c526d615c1bcde3 plugins/generic/filesystem.py
bc32b21a3ab5421b5307ff7317256229 plugins/generic/filesystem.py
feca57a968c528a2fe3ccafbc83a17f8 plugins/generic/fingerprint.py
310efc965c862cfbd7b0da5150a5ad36 plugins/generic/__init__.py
8fd5913823e97e21a8eea717cd12fc96 plugins/generic/misc.py
@@ -252,13 +252,15 @@ a3a0e76922b4f40f422a0daca4e71af3 tamper/htmlencode.py
54e1793f30c755202ee1acaacfac45fb tamper/nonrecursivereplacement.py
00ba60e5869055aaa7ba0cd23b5ed1f4 tamper/overlongutf8.py
3cadacb0f39de03e0f8612c656104e03 tamper/percentage.py
7805efc7af932c2ab452f41967f9eb7b tamper/plus2concat.py
3e09fc9f1a6f3fee03f9213aaee97191 tamper/plus2concat.py
7a18480b27d62eb574cf0150a57e81b1 tamper/plus2fnconcat.py
24753ed4e8ceab6f1a1fc13ee621943b tamper/randomcase.py
4d5fdfe77668fa44967e1d44f8a50ce7 tamper/randomcomments.py
22561b429f41fc0bdd23e36b9a8de9e5 tamper/securesphere.py
a8a0e2150de7c7dc473f74474db857ad tamper/space2comment.py
8728a16a1ae0603c6d835162cc03ab96 tamper/space2dash.py
6cc1afaeb47723886e492454e75d7b7f tamper/space2hash.py
b2331640743170f82be9a8c27f65b206 tamper/space2morecomment.py
507a174c64345df8df003ddba93c8cd1 tamper/space2morehash.py
0ce89b0d602abbd64344ab038be8acbc tamper/space2mssqlblank.py
fa66af20648b5538289748abe7a08fe6 tamper/space2mssqlhash.py
@@ -343,8 +345,6 @@ d41d8cd98f00b204e9800998ecf8427e thirdparty/multipart/__init__.py
08801ea0ba9ae22885275ef65d3ee9dc thirdparty/oset/_abc.py
54a861de0f08bb80c2e8846579ec83bd thirdparty/oset/__init__.py
179f0c584ef3fb39437bdb6e15d9c867 thirdparty/oset/pyoset.py
d24924d878e24946e83cfc1459f806af thirdparty/pagerank/__init__.py
7616693115d08f9b815a567515a0db56 thirdparty/pagerank/pagerank.py
94a4abc0fdac64ef0661b82aff68d791 thirdparty/prettyprint/__init__.py
ff80a22ee858f5331b0c088efa98b3ff thirdparty/prettyprint/prettyprint.py
5c70f8e5f7353aedc6d8d21d4fb72b37 thirdparty/pydes/__init__.py
@@ -400,9 +400,9 @@ ab6f6e3169cb43efcf5b6ed84b58252f waf/comodo.py
7bde9f5ec27b41167d25a3a24853107b waf/dotdefender.py
e4b058d759198216d24f8fed6ef97be4 waf/edgecast.py
f633953970fb181b9ac5420a47e6a610 waf/expressionengine.py
f2295bb96025aeeca7e38661aef7c883 waf/fortiweb.py
1df78b6ad49259514cb6e4d68371cbcf waf/fortiweb.py
ef151fbc34f16620958ba61dd415ae59 waf/generic.py
9126fc8101dee36c27866df731e2d841 waf/hyperguard.py
d50e17ed49e1a3cb846e652ed98e3b3c waf/hyperguard.py
5b5382ccfb82ee6afdc1b47c8a4bce70 waf/incapsula.py
310efc965c862cfbd7b0da5150a5ad36 waf/__init__.py
5a364b68519a5872c4d60be11d2a23c1 waf/isaserver.py
@@ -428,6 +428,7 @@ d4fbb2af37ad3ade3118668f2b516693 waf/requestvalidationmode.py
c1062e5c165cdaeca51113e60973afb2 waf/sophos.py
e909c359a9181e64271e6c7c8347fe15 waf/stingray.py
33f3bdac403519a1f96fb9015680c575 waf/sucuri.py
507f7c1019afd1c45c76bbcd179ddfe9 waf/tencent.py
3de96df7edeae2f21ba7b9d77c90f4d6 waf/teros.py
d428df1e83a6fac9d8dbc90d6b5dab20 waf/trafficshield.py
385c84908b482c7f0fe93262ab5320fa waf/urlscan.py

View File

@@ -10,7 +10,7 @@ import re
from lib.core.enums import HTTP_HEADER
from lib.core.settings import WAF_ATTACK_VECTORS
__product__ = "FortiWeb Web Application Firewall (Fortinet Inc.)"
__product__ = "FortiWeb Web Application Firewall (Fortinet)"
def detect(get_page):
retval = False

View File

@@ -10,7 +10,7 @@ import re
from lib.core.enums import HTTP_HEADER
from lib.core.settings import WAF_ATTACK_VECTORS
__product__ = "Hyperguard Web Application Firewall (art of defence Inc.)"
__product__ = "Hyperguard Web Application Firewall (art of defence)"
def detect(get_page):
retval = False

23
waf/tencent.py Normal file
View File

@@ -0,0 +1,23 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2017 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
import re
from lib.core.settings import WAF_ATTACK_VECTORS
__product__ = "Tencent Cloud Web Application Firewall (Tencent Cloud Computing)"
def detect(get_page):
retval = False
for vector in WAF_ATTACK_VECTORS:
page, _, code = get_page(get=vector)
retval = code == 405 and "waf.tencent-cloud.com" in (page or "")
if retval:
break
return retval