mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-10-12 02:22:55 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7268ffb4d | ||
|
|
7c5b051d60 | ||
|
|
5899fd5ef2 | ||
|
|
f60727a891 | ||
|
|
792ed52ab5 | ||
|
|
132a72c9bd | ||
|
|
8735a49f63 | ||
|
|
b9e2e8b74d | ||
|
|
b23626db70 | ||
|
|
33d8ce8923 | ||
|
|
72f7caa23b | ||
|
|
284bdac72c | ||
|
|
7d6a3c4034 | ||
|
|
02274f6db1 | ||
|
|
bf8b2eb21e | ||
|
|
1436333960 | ||
|
|
d7677f322d | ||
|
|
ab641e9242 | ||
|
|
ec83837342 | ||
|
|
2333903b68 | ||
|
|
d54ec88648 | ||
|
|
f210d66dff | ||
|
|
a651c8a637 | ||
|
|
b608c21dff | ||
|
|
88df293a1a | ||
|
|
323f1285b6 | ||
|
|
26b81f58bb | ||
|
|
839070d6ee | ||
|
|
28ee12c4d2 | ||
|
|
bc61a6828c | ||
|
|
e9380627e1 | ||
|
|
e80e841b25 | ||
|
|
4102d87521 | ||
|
|
67b470245e | ||
|
|
d148694a4b | ||
|
|
9404b63a42 | ||
|
|
58b87e4b6b | ||
|
|
5c35aff22a | ||
|
|
18d78a34cc | ||
|
|
f9e80adcef | ||
|
|
e5f96102af | ||
|
|
d9bf33ea1d | ||
|
|
0d1ea50785 | ||
|
|
cc37b12d37 |
@@ -13,7 +13,7 @@ Les captures d'écran disponible [ici](https://github.com/sqlmapproject/sqlmap/w
|
||||
Installation
|
||||
----
|
||||
|
||||
Vous pouvez télécharger le plus récent fichier tarball en cliquant [ici](https://github.com/sqlmapproject/sqlmap/tarball/master). Vous pouvez aussi télécharger le plus récent archive zip [ici](https://github.com/sqlmapproject/sqlmap/zipball/master).
|
||||
Vous pouvez télécharger le fichier "tarball" le plus récent en cliquant [ici](https://github.com/sqlmapproject/sqlmap/tarball/master). Vous pouvez aussi télécharger l'archive zip la plus récente [ici](https://github.com/sqlmapproject/sqlmap/zipball/master).
|
||||
|
||||
De préférence, télécharger __sqlmap__ en le [clonant](https://github.com/sqlmapproject/sqlmap):
|
||||
|
||||
@@ -21,7 +21,7 @@ De préférence, télécharger __sqlmap__ en le [clonant](https://github.com/sql
|
||||
|
||||
sqlmap fonctionne sur n'importe quel système d'exploitation avec la version **2.6.x** et **2.7.x** de [Python](http://www.python.org/download/)
|
||||
|
||||
Usage
|
||||
Utilisation
|
||||
----
|
||||
|
||||
Pour afficher une liste des fonctions de bases et des commutateurs (switches), tapez:
|
||||
@@ -33,7 +33,7 @@ Pour afficher une liste complète des options et des commutateurs (switches), ta
|
||||
python sqlmap.py -hh
|
||||
|
||||
Vous pouvez regarder un vidéo [ici](https://asciinema.org/a/46601) pour plus d'exemples.
|
||||
Pour obtenir un aperçu des ressources de __sqlmap__, une liste des fonctionnalités prises en charge et la description de toutes les options, ainsi que des exemples , nous vous recommandons de consulter [le wiki](https://github.com/sqlmapproject/sqlmap/wiki/Usage).
|
||||
Pour obtenir un aperçu des ressources de __sqlmap__, une liste des fonctionnalités prises en charge, la description de toutes les options, ainsi que des exemples, nous vous recommandons de consulter [le wiki](https://github.com/sqlmapproject/sqlmap/wiki/Usage).
|
||||
|
||||
Liens
|
||||
----
|
||||
@@ -41,7 +41,7 @@ Liens
|
||||
* Page d'acceuil: http://sqlmap.org
|
||||
* Téléchargement: [.tar.gz](https://github.com/sqlmapproject/sqlmap/tarball/master) ou [.zip](https://github.com/sqlmapproject/sqlmap/zipball/master)
|
||||
* Commits RSS feed: https://github.com/sqlmapproject/sqlmap/commits/master.atom
|
||||
* Issue tracker: https://github.com/sqlmapproject/sqlmap/issues
|
||||
* Suivi des issues: https://github.com/sqlmapproject/sqlmap/issues
|
||||
* Manuel de l'utilisateur: https://github.com/sqlmapproject/sqlmap/wiki
|
||||
* Foire aux questions (FAQ): https://github.com/sqlmapproject/sqlmap/wiki/FAQ
|
||||
* Twitter: [@sqlmap](https://twitter.com/sqlmap)
|
||||
|
||||
+23
-22
@@ -7,6 +7,7 @@ See the file 'LICENSE' for copying permission
|
||||
|
||||
import copy
|
||||
import httplib
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
@@ -42,6 +43,7 @@ from lib.core.common import readInput
|
||||
from lib.core.common import showStaticWords
|
||||
from lib.core.common import singleTimeLogMessage
|
||||
from lib.core.common import singleTimeWarnMessage
|
||||
from lib.core.common import unArrayizeValue
|
||||
from lib.core.common import urlencode
|
||||
from lib.core.common import wasLastResponseDBMSError
|
||||
from lib.core.common import wasLastResponseHTTPError
|
||||
@@ -281,9 +283,9 @@ def checkSqlInjection(place, parameter, value):
|
||||
# Skip DBMS-specific test if it does not match the
|
||||
# previously identified DBMS (via DBMS-specific error message)
|
||||
if kb.reduceTests and not intersect(payloadDbms, kb.reduceTests, True):
|
||||
debugMsg = "skipping test '%s' because the parsed " % title
|
||||
debugMsg += "error message(s) showed that the back-end DBMS "
|
||||
debugMsg += "could be %s" % Format.getErrorParsedDBMSes()
|
||||
debugMsg = "skipping test '%s' because the heuristic " % title
|
||||
debugMsg += "tests showed that the back-end DBMS "
|
||||
debugMsg += "could be '%s'" % unArrayizeValue(kb.reduceTests)
|
||||
logger.debug(debugMsg)
|
||||
continue
|
||||
|
||||
@@ -574,7 +576,7 @@ def checkSqlInjection(place, parameter, value):
|
||||
page, headers, _ = Request.queryPage(reqPayload, place, content=True, raise404=False)
|
||||
output = extractRegexResult(check, page, re.DOTALL | re.IGNORECASE) \
|
||||
or extractRegexResult(check, threadData.lastHTTPError[2] if wasLastResponseHTTPError() else None, re.DOTALL | re.IGNORECASE) \
|
||||
or extractRegexResult(check, listToStrValue([headers[key] for key in headers.keys() if key.lower() != URI_HTTP_HEADER.lower()] if headers else None), re.DOTALL | re.IGNORECASE) \
|
||||
or extractRegexResult(check, listToStrValue((headers[key] for key in headers.keys() if key.lower() != URI_HTTP_HEADER.lower()) if headers else None), re.DOTALL | re.IGNORECASE) \
|
||||
or extractRegexResult(check, threadData.lastRedirectMsg[1] if threadData.lastRedirectMsg and threadData.lastRedirectMsg[0] == threadData.lastRequestUID else None, re.DOTALL | re.IGNORECASE)
|
||||
|
||||
if output:
|
||||
@@ -629,11 +631,12 @@ def checkSqlInjection(place, parameter, value):
|
||||
Backend.forceDbms(kb.dbmsFilter[0])
|
||||
elif not Backend.getIdentifiedDbms():
|
||||
if kb.heuristicDbms is None:
|
||||
warnMsg = "using unescaped version of the test "
|
||||
warnMsg += "because of zero knowledge of the "
|
||||
warnMsg += "back-end DBMS. You can try to "
|
||||
warnMsg += "explicitly set it with option '--dbms'"
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
if kb.heuristicTest == HEURISTIC_TEST.POSITIVE or injection.data:
|
||||
warnMsg = "using unescaped version of the test "
|
||||
warnMsg += "because of zero knowledge of the "
|
||||
warnMsg += "back-end DBMS. You can try to "
|
||||
warnMsg += "explicitly set it with option '--dbms'"
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
else:
|
||||
Backend.forceDbms(kb.heuristicDbms)
|
||||
|
||||
@@ -1143,16 +1146,16 @@ def checkDynamicContent(firstPage, secondPage):
|
||||
count += 1
|
||||
|
||||
if count > conf.retries:
|
||||
warnMsg = "target URL is too dynamic. "
|
||||
warnMsg = "target URL content appears to be too dynamic. "
|
||||
warnMsg += "Switching to '--text-only' "
|
||||
logger.warn(warnMsg)
|
||||
|
||||
conf.textOnly = True
|
||||
return
|
||||
|
||||
warnMsg = "target URL is heavily dynamic"
|
||||
warnMsg += ". sqlmap is going to retry the request"
|
||||
logger.critical(warnMsg)
|
||||
warnMsg = "target URL content appears to be heavily dynamic. "
|
||||
warnMsg += "sqlmap is going to retry the request(s)"
|
||||
singleTimeLogMessage(warnMsg, logging.CRITICAL)
|
||||
|
||||
secondPage, _, _ = Request.queryPage(content=True)
|
||||
findDynamicContent(firstPage, secondPage)
|
||||
@@ -1168,7 +1171,7 @@ def checkStability():
|
||||
like for instance string matching (--string).
|
||||
"""
|
||||
|
||||
infoMsg = "testing if the target URL is stable"
|
||||
infoMsg = "testing if the target URL content is stable"
|
||||
logger.info(infoMsg)
|
||||
|
||||
firstPage = kb.originalPage # set inside checkConnection()
|
||||
@@ -1186,7 +1189,7 @@ def checkStability():
|
||||
|
||||
if kb.pageStable:
|
||||
if firstPage:
|
||||
infoMsg = "target URL is stable"
|
||||
infoMsg = "target URL content is stable"
|
||||
logger.info(infoMsg)
|
||||
else:
|
||||
errMsg = "there was an error checking the stability of page "
|
||||
@@ -1196,12 +1199,11 @@ def checkStability():
|
||||
logger.error(errMsg)
|
||||
|
||||
else:
|
||||
warnMsg = "target URL is not stable. sqlmap will base the page "
|
||||
warnMsg = "target URL content is not stable. sqlmap will base the page "
|
||||
warnMsg += "comparison on a sequence matcher. If no dynamic nor "
|
||||
warnMsg += "injectable parameters are detected, or in case of "
|
||||
warnMsg += "junk results, refer to user's manual paragraph "
|
||||
warnMsg += "'Page comparison' and provide a string or regular "
|
||||
warnMsg += "expression to match on"
|
||||
warnMsg += "'Page comparison'"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
message = "how do you want to proceed? [(C)ontinue/(s)tring/(r)egex/(q)uit] "
|
||||
@@ -1454,7 +1456,7 @@ def checkNullConnection():
|
||||
if not page and HTTP_HEADER.CONTENT_LENGTH in (headers or {}):
|
||||
kb.nullConnection = NULLCONNECTION.HEAD
|
||||
|
||||
infoMsg = "NULL connection is supported with HEAD method (Content-Length)"
|
||||
infoMsg = "NULL connection is supported with HEAD method ('Content-Length')"
|
||||
logger.info(infoMsg)
|
||||
else:
|
||||
page, headers, _ = Request.getPage(auxHeaders={HTTP_HEADER.RANGE: "bytes=-1"})
|
||||
@@ -1462,11 +1464,10 @@ def checkNullConnection():
|
||||
if page and len(page) == 1 and HTTP_HEADER.CONTENT_RANGE in (headers or {}):
|
||||
kb.nullConnection = NULLCONNECTION.RANGE
|
||||
|
||||
infoMsg = "NULL connection is supported with GET method (Range)"
|
||||
infoMsg += "'%s'" % kb.nullConnection
|
||||
infoMsg = "NULL connection is supported with GET method ('Range')"
|
||||
logger.info(infoMsg)
|
||||
else:
|
||||
_, headers, _ = Request.getPage(skipRead = True)
|
||||
_, headers, _ = Request.getPage(skipRead=True)
|
||||
|
||||
if HTTP_HEADER.CONTENT_LENGTH in (headers or {}):
|
||||
kb.nullConnection = NULLCONNECTION.SKIP_READ
|
||||
|
||||
@@ -242,11 +242,13 @@ def _saveToResultsFile():
|
||||
for key, value in results.items():
|
||||
place, parameter, notes = key
|
||||
line = "%s,%s,%s,%s,%s%s" % (safeCSValue(kb.originalUrls.get(conf.url) or conf.url), place, parameter, "".join(techniques[_][0].upper() for _ in sorted(value)), notes, os.linesep)
|
||||
conf.resultsFP.writelines(line)
|
||||
conf.resultsFP.write(line)
|
||||
|
||||
if not results:
|
||||
line = "%s,,,,%s" % (conf.url, os.linesep)
|
||||
conf.resultsFP.writelines(line)
|
||||
conf.resultsFP.write(line)
|
||||
|
||||
conf.resultsFP.flush()
|
||||
|
||||
def start():
|
||||
"""
|
||||
@@ -581,11 +583,11 @@ def start():
|
||||
errMsg += "(e.g. GET parameter 'id' in 'www.site.com/index.php?id=1')"
|
||||
raise SqlmapNoneDataException(errMsg)
|
||||
else:
|
||||
errMsg = "all tested parameters appear to be not injectable."
|
||||
errMsg = "all tested parameters do not appear to be injectable."
|
||||
|
||||
if conf.level < 5 or conf.risk < 3:
|
||||
errMsg += " Try to increase '--level'/'--risk' values "
|
||||
errMsg += "to perform more tests."
|
||||
errMsg += " Try to increase values for '--level'/'--risk' options "
|
||||
errMsg += "if you wish to perform more tests."
|
||||
|
||||
if isinstance(conf.tech, list) and len(conf.tech) < 5:
|
||||
errMsg += " Rerun without providing the option '--technique'."
|
||||
@@ -608,15 +610,9 @@ def start():
|
||||
|
||||
if kb.heuristicTest == HEURISTIC_TEST.POSITIVE:
|
||||
errMsg += " As heuristic test turned out positive you are "
|
||||
errMsg += "strongly advised to continue on with the tests. "
|
||||
errMsg += "Please, consider usage of tampering scripts as "
|
||||
errMsg += "your target might filter the queries."
|
||||
errMsg += "strongly advised to continue on with the tests."
|
||||
|
||||
if not conf.string and not conf.notString and not conf.regexp:
|
||||
errMsg += " Also, you can try to rerun by providing "
|
||||
errMsg += "either a valid value for option '--string' "
|
||||
errMsg += "(or '--regexp')."
|
||||
elif conf.string:
|
||||
if conf.string:
|
||||
errMsg += " Also, you can try to rerun by providing a "
|
||||
errMsg += "valid value for option '--string' as perhaps the string you "
|
||||
errMsg += "have chosen does not match "
|
||||
@@ -629,8 +625,8 @@ def start():
|
||||
|
||||
if not conf.tamper:
|
||||
errMsg += " If you suspect that there is some kind of protection mechanism "
|
||||
errMsg += "involved (e.g. WAF) maybe you could retry "
|
||||
errMsg += "with an option '--tamper' (e.g. '--tamper=space2comment')"
|
||||
errMsg += "involved (e.g. WAF) maybe you could try to use "
|
||||
errMsg += "option '--tamper' (e.g. '--tamper=space2comment')"
|
||||
|
||||
raise SqlmapNotVulnerableException(errMsg.rstrip('.'))
|
||||
else:
|
||||
|
||||
+1
-11
@@ -105,7 +105,7 @@ class Agent(object):
|
||||
else:
|
||||
origValue = filter(None, (re.search(_, origValue.split(BOUNDED_INJECTION_MARKER)[0]) for _ in (r"\w+\Z", r"[^\"'><]+\Z", r"[^ ]+\Z")))[0].group(0)
|
||||
origValue = origValue[origValue.rfind('/') + 1:]
|
||||
for char in ('?', '=', ':'):
|
||||
for char in ('?', '=', ':', ','):
|
||||
if char in origValue:
|
||||
origValue = origValue[origValue.rfind(char) + 1:]
|
||||
elif place == PLACE.CUSTOM_POST:
|
||||
@@ -207,16 +207,6 @@ class Agent(object):
|
||||
|
||||
return retVal
|
||||
|
||||
def fullPayload(self, query):
|
||||
if conf.direct:
|
||||
return self.payloadDirect(query)
|
||||
|
||||
query = self.prefixQuery(query)
|
||||
query = self.suffixQuery(query)
|
||||
payload = self.payload(newValue=query)
|
||||
|
||||
return payload
|
||||
|
||||
def prefixQuery(self, expression, prefix=None, where=None, clause=None):
|
||||
"""
|
||||
This method defines how the input expression has to be escaped
|
||||
|
||||
@@ -14,10 +14,12 @@ import itertools
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import zlib
|
||||
|
||||
from lib.core.enums import MKSTEMP_PREFIX
|
||||
from lib.core.exception import SqlmapSystemException
|
||||
from lib.core.settings import BIGARRAY_CHUNK_SIZE
|
||||
from lib.core.settings import BIGARRAY_COMPRESS_LEVEL
|
||||
|
||||
DEFAULT_SIZE_OF = sys.getsizeof(object())
|
||||
|
||||
@@ -80,8 +82,8 @@ class BigArray(list):
|
||||
if len(self.chunks[-1]) < 1:
|
||||
self.chunks.pop()
|
||||
try:
|
||||
with open(self.chunks[-1], "rb") as fp:
|
||||
self.chunks[-1] = pickle.load(fp)
|
||||
with open(self.chunks[-1], "rb") as f:
|
||||
self.chunks[-1] = pickle.loads(zlib.decompress(f.read()))
|
||||
except IOError, ex:
|
||||
errMsg = "exception occurred while retrieving data "
|
||||
errMsg += "from a temporary file ('%s')" % ex.message
|
||||
@@ -101,8 +103,8 @@ class BigArray(list):
|
||||
handle, filename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.BIG_ARRAY)
|
||||
self.filenames.add(filename)
|
||||
os.close(handle)
|
||||
with open(filename, "w+b") as fp:
|
||||
pickle.dump(chunk, fp, pickle.HIGHEST_PROTOCOL)
|
||||
with open(filename, "w+b") as f:
|
||||
f.write(zlib.compress(pickle.dumps(chunk, pickle.HIGHEST_PROTOCOL), BIGARRAY_COMPRESS_LEVEL))
|
||||
return filename
|
||||
except (OSError, IOError), ex:
|
||||
errMsg = "exception occurred while storing data "
|
||||
@@ -119,8 +121,8 @@ class BigArray(list):
|
||||
|
||||
if not (self.cache and self.cache.index == index):
|
||||
try:
|
||||
with open(self.chunks[index], "rb") as fp:
|
||||
self.cache = Cache(index, pickle.load(fp), False)
|
||||
with open(self.chunks[index], "rb") as f:
|
||||
self.cache = Cache(index, pickle.loads(zlib.decompress(f.read())), False)
|
||||
except IOError, ex:
|
||||
errMsg = "exception occurred while retrieving data "
|
||||
errMsg += "from a temporary file ('%s')" % ex.message
|
||||
|
||||
+52
-56
@@ -28,6 +28,7 @@ import sys
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
import types
|
||||
import urllib
|
||||
import urllib2
|
||||
import urlparse
|
||||
@@ -104,7 +105,7 @@ from lib.core.settings import DEFAULT_GET_POST_DELIMITER
|
||||
from lib.core.settings import DEFAULT_MSSQL_SCHEMA
|
||||
from lib.core.settings import DEV_EMAIL_ADDRESS
|
||||
from lib.core.settings import DUMMY_USER_INJECTION
|
||||
from lib.core.settings import DYNAMICITY_MARK_LENGTH
|
||||
from lib.core.settings import DYNAMICITY_BOUNDARY_LENGTH
|
||||
from lib.core.settings import ERROR_PARSING_REGEXES
|
||||
from lib.core.settings import FILE_PATH_REGEXES
|
||||
from lib.core.settings import FORCE_COOKIE_EXPIRATION_TIME
|
||||
@@ -1017,16 +1018,16 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
|
||||
|
||||
retVal = default
|
||||
else:
|
||||
logging._acquireLock()
|
||||
|
||||
if conf.get("beep"):
|
||||
beep()
|
||||
|
||||
dataToStdout("\r%s" % message, forceOutput=True, bold=True)
|
||||
kb.prependFlag = False
|
||||
|
||||
try:
|
||||
retVal = raw_input() or default
|
||||
logging._acquireLock()
|
||||
|
||||
if conf.get("beep"):
|
||||
beep()
|
||||
|
||||
dataToStdout("\r%s" % message, forceOutput=True, bold=True)
|
||||
kb.prependFlag = False
|
||||
|
||||
retVal = raw_input().strip() or default
|
||||
retVal = getUnicode(retVal, encoding=sys.stdin.encoding) if retVal else retVal
|
||||
except:
|
||||
try:
|
||||
@@ -1839,8 +1840,7 @@ def getPageWordSet(page):
|
||||
|
||||
# only if the page's charset has been successfully identified
|
||||
if isinstance(page, unicode):
|
||||
_ = getFilteredPageContent(page)
|
||||
retVal = set(re.findall(r"\w+", _))
|
||||
retVal = set(_.group(0) for _ in re.finditer(r"\w+", getFilteredPageContent(page)))
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -2057,6 +2057,7 @@ def readXmlFile(xmlFile):
|
||||
|
||||
return retVal
|
||||
|
||||
@cachedmethod
|
||||
def stdev(values):
|
||||
"""
|
||||
Computes standard deviation of a list of numbers.
|
||||
@@ -2068,19 +2069,10 @@ def stdev(values):
|
||||
|
||||
if not values or len(values) < 2:
|
||||
return None
|
||||
|
||||
key = (values[0], values[-1], len(values))
|
||||
|
||||
if kb.get("cache") and key in kb.cache.stdev:
|
||||
retVal = kb.cache.stdev[key]
|
||||
else:
|
||||
avg = average(values)
|
||||
_ = reduce(lambda x, y: x + pow((y or 0) - avg, 2), values, 0.0)
|
||||
retVal = sqrt(_ / (len(values) - 1))
|
||||
if kb.get("cache"):
|
||||
kb.cache.stdev[key] = retVal
|
||||
|
||||
return retVal
|
||||
return sqrt(_ / (len(values) - 1))
|
||||
|
||||
def average(values):
|
||||
"""
|
||||
@@ -2240,7 +2232,7 @@ def goGoodSamaritan(prevValue, originalCharset):
|
||||
def getPartRun(alias=True):
|
||||
"""
|
||||
Goes through call stack and finds constructs matching conf.dbmsHandler.*.
|
||||
Returns it or its alias used in txt/common-outputs.txt
|
||||
Returns it or its alias used in 'txt/common-outputs.txt'
|
||||
"""
|
||||
|
||||
retVal = None
|
||||
@@ -2498,6 +2490,9 @@ def findLocalPort(ports):
|
||||
def findMultipartPostBoundary(post):
|
||||
"""
|
||||
Finds value for a boundary parameter in given multipart POST body
|
||||
|
||||
>>> findMultipartPostBoundary("-----------------------------9051914041544843365972754266\\nContent-Disposition: form-data; name=text\\n\\ndefault")
|
||||
'9051914041544843365972754266'
|
||||
"""
|
||||
|
||||
retVal = None
|
||||
@@ -2687,6 +2682,7 @@ def enumValueToNameLookup(type_, value_):
|
||||
|
||||
return retVal
|
||||
|
||||
@cachedmethod
|
||||
def extractRegexResult(regex, content, flags=0):
|
||||
"""
|
||||
Returns 'result' group value from a possible match with regex on a given
|
||||
@@ -2779,13 +2775,17 @@ def findDynamicContent(firstPage, secondPage):
|
||||
"""
|
||||
This function checks if the provided pages have dynamic content. If they
|
||||
are dynamic, proper markings will be made
|
||||
|
||||
>>> findDynamicContent("Lorem ipsum dolor sit amet, congue tation referrentur ei sed. Ne nec legimus habemus recusabo, natum reque et per. Facer tritani reprehendunt eos id, modus constituam est te. Usu sumo indoctum ad, pri paulo molestiae complectitur no.", "Lorem ipsum dolor sit amet, congue tation referrentur ei sed. Ne nec legimus habemus recusabo, natum reque et per. <script src='ads.js'></script>Facer tritani reprehendunt eos id, modus constituam est te. Usu sumo indoctum ad, pri paulo molestiae complectitur no.")
|
||||
>>> kb.dynamicMarkings
|
||||
[('natum reque et per. ', 'Facer tritani repreh')]
|
||||
"""
|
||||
|
||||
if not firstPage or not secondPage:
|
||||
return
|
||||
|
||||
infoMsg = "searching for dynamic content"
|
||||
logger.info(infoMsg)
|
||||
singleTimeLogMessage(infoMsg)
|
||||
|
||||
blocks = SequenceMatcher(None, firstPage, secondPage).get_matching_blocks()
|
||||
kb.dynamicMarkings = []
|
||||
@@ -2794,7 +2794,7 @@ def findDynamicContent(firstPage, secondPage):
|
||||
for block in blocks[:]:
|
||||
(_, _, length) = block
|
||||
|
||||
if length <= DYNAMICITY_MARK_LENGTH:
|
||||
if length <= 2 * DYNAMICITY_BOUNDARY_LENGTH:
|
||||
blocks.remove(block)
|
||||
|
||||
# Making of dynamic markings based on prefix/suffix principle
|
||||
@@ -2812,14 +2812,23 @@ def findDynamicContent(firstPage, secondPage):
|
||||
if suffix is None and (blocks[i][0] + blocks[i][2] >= len(firstPage)):
|
||||
continue
|
||||
|
||||
prefix = trimAlphaNum(prefix)
|
||||
suffix = trimAlphaNum(suffix)
|
||||
if prefix and suffix:
|
||||
prefix = prefix[-DYNAMICITY_BOUNDARY_LENGTH:]
|
||||
suffix = suffix[:DYNAMICITY_BOUNDARY_LENGTH]
|
||||
|
||||
kb.dynamicMarkings.append((prefix[-DYNAMICITY_MARK_LENGTH / 2:] if prefix else None, suffix[:DYNAMICITY_MARK_LENGTH / 2] if suffix else None))
|
||||
infix = max(re.search(r"(?s)%s(.+)%s" % (re.escape(prefix), re.escape(suffix)), _) for _ in (firstPage, secondPage)).group(1)
|
||||
|
||||
if infix[0].isalnum():
|
||||
prefix = trimAlphaNum(prefix)
|
||||
|
||||
if infix[-1].isalnum():
|
||||
suffix = trimAlphaNum(suffix)
|
||||
|
||||
kb.dynamicMarkings.append((prefix if prefix else None, suffix if suffix else None))
|
||||
|
||||
if len(kb.dynamicMarkings) > 0:
|
||||
infoMsg = "dynamic content marked for removal (%d region%s)" % (len(kb.dynamicMarkings), 's' if len(kb.dynamicMarkings) > 1 else '')
|
||||
logger.info(infoMsg)
|
||||
singleTimeLogMessage(infoMsg)
|
||||
|
||||
def removeDynamicContent(page):
|
||||
"""
|
||||
@@ -3374,6 +3383,9 @@ def createGithubIssue(errMsg, excMsg):
|
||||
def maskSensitiveData(msg):
|
||||
"""
|
||||
Masks sensitive data in the supplied message
|
||||
|
||||
>>> maskSensitiveData('python sqlmap.py -u "http://www.test.com/vuln.php?id=1" --banner')
|
||||
u'python sqlmap.py -u *********************************** --banner'
|
||||
"""
|
||||
|
||||
retVal = getUnicode(msg)
|
||||
@@ -3402,7 +3414,7 @@ def listToStrValue(value):
|
||||
'1, 2, 3'
|
||||
"""
|
||||
|
||||
if isinstance(value, (set, tuple)):
|
||||
if isinstance(value, (set, tuple, types.GeneratorType)):
|
||||
value = list(value)
|
||||
|
||||
if isinstance(value, list):
|
||||
@@ -3412,22 +3424,6 @@ def listToStrValue(value):
|
||||
|
||||
return retVal
|
||||
|
||||
def getExceptionFrameLocals():
|
||||
"""
|
||||
Returns dictionary with local variable content from frame
|
||||
where exception has been raised
|
||||
"""
|
||||
|
||||
retVal = {}
|
||||
|
||||
if sys.exc_info():
|
||||
trace = sys.exc_info()[2]
|
||||
while trace.tb_next:
|
||||
trace = trace.tb_next
|
||||
retVal = trace.tb_frame.f_locals
|
||||
|
||||
return retVal
|
||||
|
||||
def intersect(valueA, valueB, lowerCase=False):
|
||||
"""
|
||||
Returns intersection of the array-ized values
|
||||
@@ -3565,17 +3561,19 @@ def safeSQLIdentificatorNaming(name, isTable=False):
|
||||
_ = isTable and Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE)
|
||||
|
||||
if _:
|
||||
retVal = re.sub(r"(?i)\A%s\." % DEFAULT_MSSQL_SCHEMA, "", retVal)
|
||||
retVal = re.sub(r"(?i)\A\[?%s\]?\." % DEFAULT_MSSQL_SCHEMA, "", retVal)
|
||||
|
||||
if retVal.upper() in kb.keywords or (retVal or " ")[0].isdigit() or not re.match(r"\A[A-Za-z0-9_@%s\$]+\Z" % ('.' if _ else ""), retVal): # MsSQL is the only DBMS where we automatically prepend schema to table name (dot is normal)
|
||||
retVal = unsafeSQLIdentificatorNaming(retVal)
|
||||
|
||||
if retVal.upper() in kb.keywords or (retVal or " ")[0].isdigit() or not re.match(r"\A[A-Za-z0-9_@%s\$]+\Z" % ("." if _ else ""), retVal): # MsSQL is the only DBMS where we automatically prepend schema to table name (dot is normal)
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS):
|
||||
retVal = "`%s`" % retVal.strip("`")
|
||||
retVal = "`%s`" % retVal
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.SQLITE, DBMS.INFORMIX, DBMS.HSQLDB):
|
||||
retVal = "\"%s\"" % retVal.strip("\"")
|
||||
retVal = "\"%s\"" % retVal
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE,):
|
||||
retVal = "\"%s\"" % retVal.strip("\"").upper()
|
||||
retVal = "\"%s\"" % retVal.upper()
|
||||
elif Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) and ((retVal or " ")[0].isdigit() or not re.match(r"\A\w+\Z", retVal, re.U)):
|
||||
retVal = "[%s]" % retVal.strip("[]")
|
||||
retVal = "[%s]" % retVal
|
||||
|
||||
if _ and DEFAULT_MSSQL_SCHEMA not in retVal and '.' not in re.sub(r"\[[^]]+\]", "", retVal):
|
||||
retVal = "%s.%s" % (DEFAULT_MSSQL_SCHEMA, retVal)
|
||||
@@ -3600,9 +3598,7 @@ def unsafeSQLIdentificatorNaming(name):
|
||||
retVal = name.replace("[", "").replace("]", "")
|
||||
|
||||
if Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
|
||||
prefix = "%s." % DEFAULT_MSSQL_SCHEMA
|
||||
if retVal.startswith(prefix):
|
||||
retVal = retVal[len(prefix):]
|
||||
retVal = re.sub(r"(?i)\A\[?%s\]?\." % DEFAULT_MSSQL_SCHEMA, "", retVal)
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -4022,7 +4018,7 @@ def checkSameHost(*urls):
|
||||
elif len(urls) == 1:
|
||||
return True
|
||||
else:
|
||||
return all(urlparse.urlparse(url or "").netloc.split(':')[0] == urlparse.urlparse(urls[0] or "").netloc.split(':')[0] for url in urls[1:])
|
||||
return all(re.sub(r"(?i)\Awww\.", "", urlparse.urlparse(url or "").netloc.split(':')[0]) == re.sub(r"(?i)\Awww\.", "", urlparse.urlparse(urls[0] or "").netloc.split(':')[0]) for url in urls[1:])
|
||||
|
||||
def getHostHeader(url):
|
||||
"""
|
||||
|
||||
@@ -14,11 +14,11 @@ def cachedmethod(f, cache={}):
|
||||
|
||||
def _(*args, **kwargs):
|
||||
try:
|
||||
key = (f, tuple(args), frozenset(kwargs.items()))
|
||||
key = hash((f, tuple(args), frozenset(kwargs.items())))
|
||||
if key not in cache:
|
||||
cache[key] = f(*args, **kwargs)
|
||||
except:
|
||||
key = "".join(str(_) for _ in (f, args, kwargs))
|
||||
key = hash("".join(str(_) for _ in (f, args, kwargs)))
|
||||
if key not in cache:
|
||||
cache[key] = f(*args, **kwargs)
|
||||
|
||||
|
||||
+3
-3
@@ -2097,11 +2097,11 @@ def _useWizardInterface():
|
||||
choice = readInput(message, default='1')
|
||||
|
||||
if choice == '2':
|
||||
map(lambda x: conf.__setitem__(x, True), WIZARD.INTERMEDIATE)
|
||||
map(lambda _: conf.__setitem__(_, True), WIZARD.INTERMEDIATE)
|
||||
elif choice == '3':
|
||||
map(lambda x: conf.__setitem__(x, True), WIZARD.ALL)
|
||||
map(lambda _: conf.__setitem__(_, True), WIZARD.ALL)
|
||||
else:
|
||||
map(lambda x: conf.__setitem__(x, True), WIZARD.BASIC)
|
||||
map(lambda _: conf.__setitem__(_, True), WIZARD.BASIC)
|
||||
|
||||
logger.debug("muting sqlmap.. it will do the magic for you")
|
||||
conf.verbose = 0
|
||||
|
||||
+10
-7
@@ -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.11.0"
|
||||
VERSION = "1.1.12.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)
|
||||
@@ -76,7 +76,7 @@ CHAR_INFERENCE_MARK = "%c"
|
||||
PRINTABLE_CHAR_REGEX = r"[^\x00-\x1f\x7f-\xff]"
|
||||
|
||||
# Regular expression used for extraction of table names (useful for (e.g.) MsAccess)
|
||||
SELECT_FROM_TABLE_REGEX = r"\bSELECT .+? FROM (?P<result>([\w.]|`[^`<>]+`)+)"
|
||||
SELECT_FROM_TABLE_REGEX = r"\bSELECT\b.+?\bFROM\s+(?P<result>([\w.]|`[^`<>]+`)+)"
|
||||
|
||||
# Regular expression used for recognition of textual content-type
|
||||
TEXT_CONTENT_TYPE_REGEX = r"(?i)(text|form|message|xml|javascript|ecmascript|json)"
|
||||
@@ -193,8 +193,8 @@ UNKNOWN_DBMS = "Unknown"
|
||||
# String used for representation of unknown DBMS version
|
||||
UNKNOWN_DBMS_VERSION = "Unknown"
|
||||
|
||||
# Dynamicity mark length used in dynamicity removal engine
|
||||
DYNAMICITY_MARK_LENGTH = 32
|
||||
# Dynamicity boundary length used in dynamicity removal engine
|
||||
DYNAMICITY_BOUNDARY_LENGTH = 20
|
||||
|
||||
# Dummy user prefix used in dictionary attack
|
||||
DUMMY_USER_PREFIX = "__dummy__"
|
||||
@@ -301,7 +301,7 @@ BLANK = "<blank>"
|
||||
CURRENT_DB = "CD"
|
||||
|
||||
# Regular expressions used for finding file paths in error messages
|
||||
FILE_PATH_REGEXES = (r"<b>(?P<result>[^<>]+?)</b> on line \d+", r"(?P<result>[^<>'\"]+?)['\"]? on line \d+", r"(?:[>(\[\s])(?P<result>[A-Za-z]:[\\/][\w. \\/-]*)", r"(?:[>(\[\s])(?P<result>/\w[/\w.-]+)", r"href=['\"]file://(?P<result>/[^'\"]+)")
|
||||
FILE_PATH_REGEXES = (r"<b>(?P<result>[^<>]+?)</b> on line \d+", r"(?P<result>[^<>'\"]+?)['\"]? on line \d+", r"(?:[>(\[\s])(?P<result>[A-Za-z]:[\\/][\w. \\/-]*)", r"(?:[>(\[\s])(?P<result>/\w[/\w.~-]+)", r"href=['\"]file://(?P<result>/[^'\"]+)")
|
||||
|
||||
# Regular expressions used for parsing error messages (--parse-errors)
|
||||
ERROR_PARSING_REGEXES = (
|
||||
@@ -479,7 +479,7 @@ PICKLE_REDUCE_WHITELIST = (types.BooleanType, types.DictType, types.FloatType, t
|
||||
DUMMY_SQL_INJECTION_CHARS = ";()'"
|
||||
|
||||
# Simple check against dummy users
|
||||
DUMMY_USER_INJECTION = r"(?i)[^\w](AND|OR)\s+[^\s]+[=><]|\bUNION\b.+\bSELECT\b|\bSELECT\b.+\bFROM\b|\b(CONCAT|information_schema|SLEEP|DELAY)\b"
|
||||
DUMMY_USER_INJECTION = r"(?i)[^\w](AND|OR)\s+[^\s]+[=><]|\bUNION\b.+\bSELECT\b|\bSELECT\b.+\bFROM\b|\b(CONCAT|information_schema|SLEEP|DELAY|FLOOR\(RAND)\b"
|
||||
|
||||
# Extensions skipped by crawler
|
||||
CRAWL_EXCLUDE_EXTENSIONS = ("3ds", "3g2", "3gp", "7z", "DS_Store", "a", "aac", "adp", "ai", "aif", "aiff", "apk", "ar", "asf", "au", "avi", "bak", "bin", "bk", "bmp", "btif", "bz2", "cab", "caf", "cgm", "cmx", "cpio", "cr2", "dat", "deb", "djvu", "dll", "dmg", "dmp", "dng", "doc", "docx", "dot", "dotx", "dra", "dsk", "dts", "dtshd", "dvb", "dwg", "dxf", "ear", "ecelp4800", "ecelp7470", "ecelp9600", "egg", "eol", "eot", "epub", "exe", "f4v", "fbs", "fh", "fla", "flac", "fli", "flv", "fpx", "fst", "fvt", "g3", "gif", "gz", "h261", "h263", "h264", "ico", "ief", "image", "img", "ipa", "iso", "jar", "jpeg", "jpg", "jpgv", "jpm", "jxr", "ktx", "lvp", "lz", "lzma", "lzo", "m3u", "m4a", "m4v", "mar", "mdi", "mid", "mj2", "mka", "mkv", "mmr", "mng", "mov", "movie", "mp3", "mp4", "mp4a", "mpeg", "mpg", "mpga", "mxu", "nef", "npx", "o", "oga", "ogg", "ogv", "otf", "pbm", "pcx", "pdf", "pea", "pgm", "pic", "png", "pnm", "ppm", "pps", "ppt", "pptx", "ps", "psd", "pya", "pyc", "pyo", "pyv", "qt", "rar", "ras", "raw", "rgb", "rip", "rlc", "rz", "s3m", "s7z", "scm", "scpt", "sgi", "shar", "sil", "smv", "so", "sub", "swf", "tar", "tbz2", "tga", "tgz", "tif", "tiff", "tlz", "ts", "ttf", "uvh", "uvi", "uvm", "uvp", "uvs", "uvu", "viv", "vob", "war", "wav", "wax", "wbmp", "wdp", "weba", "webm", "webp", "whl", "wm", "wma", "wmv", "wmx", "woff", "woff2", "wvx", "xbm", "xif", "xls", "xlsx", "xlt", "xm", "xpi", "xpm", "xwd", "xz", "z", "zip", "zipx")
|
||||
@@ -520,6 +520,9 @@ ROTATING_CHARS = ('\\', '|', '|', '/', '-')
|
||||
# Approximate chunk length (in bytes) used by BigArray objects (only last chunk and cached one are held in memory)
|
||||
BIGARRAY_CHUNK_SIZE = 1024 * 1024
|
||||
|
||||
# Compress (zlib) level used for storing BigArray chunks to disk (0-9)
|
||||
BIGARRAY_COMPRESS_LEVEL = 9
|
||||
|
||||
# Maximum number of socket pre-connects
|
||||
SOCKET_PRE_CONNECT_QUEUE_SIZE = 3
|
||||
|
||||
@@ -639,7 +642,7 @@ VALID_TIME_CHARS_RUN_THRESHOLD = 100
|
||||
CHECK_ZERO_COLUMNS_THRESHOLD = 10
|
||||
|
||||
# Boldify all logger messages containing these "patterns"
|
||||
BOLD_PATTERNS = ("' injectable", "provided empty", "leftover chars", "might be injectable", "' is vulnerable", "is not injectable", "does not seem to be", "test failed", "test passed", "live test final result", "test shows that", "the back-end DBMS is", "created Github", "blocked by the target server", "protection is involved", "CAPTCHA", "specific response")
|
||||
BOLD_PATTERNS = ("' injectable", "provided empty", "leftover chars", "might be injectable", "' is vulnerable", "is not injectable", "does not seem to be", "test failed", "test passed", "live test final result", "test shows that", "the back-end DBMS is", "created Github", "blocked by the target server", "protection is involved", "CAPTCHA", "specific response", "NULL connection is supported")
|
||||
|
||||
# Generic www root directory names
|
||||
GENERIC_DOC_ROOT_DIRECTORY_NAMES = ("htdocs", "httpdocs", "public", "wwwroot", "www")
|
||||
|
||||
+1
-1
@@ -545,7 +545,7 @@ def _setResultsFile():
|
||||
if not conf.resultsFP:
|
||||
conf.resultsFilename = os.path.join(paths.SQLMAP_OUTPUT_PATH, time.strftime(RESULTS_FILE_FORMAT).lower())
|
||||
try:
|
||||
conf.resultsFP = openFile(conf.resultsFilename, "w+", UNICODE_ENCODING, buffering=0)
|
||||
conf.resultsFP = openFile(conf.resultsFilename, "a", UNICODE_ENCODING, buffering=0)
|
||||
except (OSError, IOError), ex:
|
||||
try:
|
||||
warnMsg = "unable to create results file '%s' ('%s'). " % (conf.resultsFilename, getUnicode(ex))
|
||||
|
||||
@@ -64,9 +64,6 @@ class _ThreadData(threading.local):
|
||||
|
||||
ThreadData = _ThreadData()
|
||||
|
||||
def getCurrentThreadUID():
|
||||
return hash(threading.currentThread())
|
||||
|
||||
def readInput(message, default=None, checkBatch=True, boolean=False):
|
||||
# It will be overwritten by original from lib.core.common
|
||||
pass
|
||||
|
||||
+14
-4
@@ -254,12 +254,22 @@ def decodePage(page, contentEncoding, contentType):
|
||||
if not page or (conf.nullConnection and len(page) < 2):
|
||||
return getUnicode(page)
|
||||
|
||||
if isinstance(contentEncoding, basestring) and contentEncoding.lower() in ("gzip", "x-gzip", "deflate"):
|
||||
if isinstance(contentEncoding, basestring) and contentEncoding:
|
||||
contentEncoding = contentEncoding.lower()
|
||||
else:
|
||||
contentEncoding = ""
|
||||
|
||||
if isinstance(contentType, basestring) and contentType:
|
||||
contentType = contentType.lower()
|
||||
else:
|
||||
contentType = ""
|
||||
|
||||
if contentEncoding in ("gzip", "x-gzip", "deflate"):
|
||||
if not kb.pageCompress:
|
||||
return None
|
||||
|
||||
try:
|
||||
if contentEncoding.lower() == "deflate":
|
||||
if contentEncoding == "deflate":
|
||||
data = StringIO.StringIO(zlib.decompress(page, -15)) # Reference: http://stackoverflow.com/questions/1089662/python-inflate-and-deflate-implementations
|
||||
else:
|
||||
data = gzip.GzipFile("", "rb", 9, StringIO.StringIO(page))
|
||||
@@ -284,7 +294,7 @@ def decodePage(page, contentEncoding, contentType):
|
||||
httpCharset, metaCharset = None, None
|
||||
|
||||
# Reference: http://stackoverflow.com/questions/1020892/python-urllib2-read-to-unicode
|
||||
if contentType and (contentType.find("charset=") != -1):
|
||||
if contentType.find("charset=") != -1:
|
||||
httpCharset = checkCharEncoding(contentType.split("charset=")[-1])
|
||||
|
||||
metaCharset = checkCharEncoding(extractRegexResult(META_CHARSET_REGEX, page))
|
||||
@@ -300,7 +310,7 @@ def decodePage(page, contentEncoding, contentType):
|
||||
kb.pageEncoding = conf.encoding
|
||||
|
||||
# can't do for all responses because we need to support binary files too
|
||||
if contentType and not isinstance(page, unicode) and "text/" in contentType.lower():
|
||||
if not isinstance(page, unicode) and "text/" in contentType:
|
||||
if kb.heuristicMode:
|
||||
kb.pageEncoding = kb.pageEncoding or checkCharEncoding(getHeuristicCharEncoding(page))
|
||||
page = getUnicode(page, kb.pageEncoding)
|
||||
|
||||
@@ -49,7 +49,7 @@ def _comparison(page, headers, code, getRatioValue, pageLength):
|
||||
threadData = getCurrentThreadData()
|
||||
|
||||
if kb.testMode:
|
||||
threadData.lastComparisonHeaders = listToStrValue([_ for _ in headers.headers if not _.startswith("%s:" % URI_HTTP_HEADER)]) if headers else ""
|
||||
threadData.lastComparisonHeaders = listToStrValue(_ for _ in headers.headers if not _.startswith("%s:" % URI_HTTP_HEADER)) if headers else ""
|
||||
threadData.lastComparisonPage = page
|
||||
threadData.lastComparisonCode = code
|
||||
|
||||
@@ -57,7 +57,7 @@ def _comparison(page, headers, code, getRatioValue, pageLength):
|
||||
return None
|
||||
|
||||
if any((conf.string, conf.notString, conf.regexp)):
|
||||
rawResponse = "%s%s" % (listToStrValue([_ for _ in headers.headers if not _.startswith("%s:" % URI_HTTP_HEADER)]) if headers else "", page)
|
||||
rawResponse = "%s%s" % (listToStrValue(_ for _ in headers.headers if not _.startswith("%s:" % URI_HTTP_HEADER)) if headers else "", page)
|
||||
|
||||
# String to match in page when the query is True and/or valid
|
||||
if conf.string:
|
||||
|
||||
@@ -796,6 +796,8 @@ class Connect(object):
|
||||
raise404 = place != PLACE.URI if raise404 is None else raise404
|
||||
method = method or conf.method
|
||||
|
||||
postUrlEncode = kb.postUrlEncode
|
||||
|
||||
value = agent.adjustLateValues(value)
|
||||
payload = agent.extractPayload(value)
|
||||
threadData = getCurrentThreadData()
|
||||
@@ -804,8 +806,8 @@ class Connect(object):
|
||||
headers = OrderedDict(conf.httpHeaders)
|
||||
contentType = max(headers[_] if _.upper() == HTTP_HEADER.CONTENT_TYPE.upper() else None for _ in headers.keys())
|
||||
|
||||
if (kb.postHint or conf.skipUrlEncode) and kb.postUrlEncode:
|
||||
kb.postUrlEncode = False
|
||||
if (kb.postHint or conf.skipUrlEncode) and postUrlEncode:
|
||||
postUrlEncode = False
|
||||
conf.httpHeaders = [_ for _ in conf.httpHeaders if _[1] != contentType]
|
||||
contentType = POST_HINT_CONTENT_TYPES.get(kb.postHint, PLAIN_TEXT_CONTENT_TYPE)
|
||||
conf.httpHeaders.append((HTTP_HEADER.CONTENT_TYPE, contentType))
|
||||
@@ -849,7 +851,7 @@ class Connect(object):
|
||||
value = agent.replacePayload(value, payload)
|
||||
else:
|
||||
# GET, POST, URI and Cookie payload needs to be thoroughly URL encoded
|
||||
if (place in (PLACE.GET, PLACE.URI, PLACE.COOKIE) or place == PLACE.CUSTOM_HEADER and value.split(',')[0] == HTTP_HEADER.COOKIE) and not conf.skipUrlEncode or place in (PLACE.POST, PLACE.CUSTOM_POST) and kb.postUrlEncode:
|
||||
if (place in (PLACE.GET, PLACE.URI, PLACE.COOKIE) or place == PLACE.CUSTOM_HEADER and value.split(',')[0] == HTTP_HEADER.COOKIE) and not conf.skipUrlEncode or place in (PLACE.POST, PLACE.CUSTOM_POST) and postUrlEncode:
|
||||
skip = False
|
||||
|
||||
if place == PLACE.COOKIE or place == PLACE.CUSTOM_HEADER and value.split(',')[0] == HTTP_HEADER.COOKIE:
|
||||
@@ -862,6 +864,7 @@ class Connect(object):
|
||||
if not skip:
|
||||
payload = urlencode(payload, '%', False, place != PLACE.URI) # spaceplus is handled down below
|
||||
value = agent.replacePayload(value, payload)
|
||||
postUrlEncode = False
|
||||
|
||||
if conf.hpp:
|
||||
if not any(conf.url.lower().endswith(_.lower()) for _ in (WEB_API.ASP, WEB_API.ASPX)):
|
||||
@@ -1129,7 +1132,7 @@ class Connect(object):
|
||||
found = True
|
||||
uri = re.sub(regex.replace(r"\A", r"\?"), "\g<1>%s\g<3>" % value.replace('\\', r'\\'), uri)
|
||||
|
||||
regex = r"((\A|%s)%s=).+?(%s|\Z)" % (re.escape(conf.cookieDel or DEFAULT_COOKIE_DELIMITER), name, re.escape(conf.cookieDel or DEFAULT_COOKIE_DELIMITER))
|
||||
regex = r"((\A|%s)%s=).+?(%s|\Z)" % (re.escape(conf.cookieDel or DEFAULT_COOKIE_DELIMITER), re.escape(name), re.escape(conf.cookieDel or DEFAULT_COOKIE_DELIMITER))
|
||||
if re.search(regex, (cookie or "")):
|
||||
found = True
|
||||
cookie = re.sub(regex, "\g<1>%s\g<3>" % value.replace('\\', r'\\'), cookie)
|
||||
@@ -1148,7 +1151,7 @@ class Connect(object):
|
||||
if post is not None:
|
||||
if place not in (PLACE.POST, PLACE.CUSTOM_POST) and hasattr(post, UNENCODED_ORIGINAL_VALUE):
|
||||
post = getattr(post, UNENCODED_ORIGINAL_VALUE)
|
||||
elif kb.postUrlEncode:
|
||||
elif postUrlEncode:
|
||||
post = urlencode(post, spaceplus=kb.postSpaceToPlus)
|
||||
|
||||
if timeBasedCompare and not conf.disableStats:
|
||||
|
||||
+3
-3
@@ -266,9 +266,9 @@ class Web:
|
||||
directories = _
|
||||
|
||||
backdoorName = "tmpb%s.%s" % (randomStr(lowercase=True), self.webApi)
|
||||
backdoorContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "backdoor.%s_" % self.webApi))
|
||||
backdoorContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "backdoors", "backdoor.%s_" % self.webApi))
|
||||
|
||||
stagerContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "stager.%s_" % self.webApi))
|
||||
stagerContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "stagers", "stager.%s_" % self.webApi))
|
||||
|
||||
for directory in directories:
|
||||
if not directory:
|
||||
@@ -323,7 +323,7 @@ class Web:
|
||||
os.close(handle)
|
||||
|
||||
with open(filename, "w+b") as f:
|
||||
_ = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "stager.%s_" % self.webApi))
|
||||
_ = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "stagers", "stager.%s_" % self.webApi))
|
||||
_ = _.replace("WRITABLE_DIR", utf8encode(directory.replace('/', '\\\\') if Backend.isOs(OS.WINDOWS) else directory))
|
||||
f.write(_)
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||
|
||||
if partialValue:
|
||||
firstChar = len(partialValue)
|
||||
elif "LENGTH(" in expression.upper() or "LEN(" in expression.upper():
|
||||
elif re.search(r"(?i)\b(LENGTH|LEN)\(", expression):
|
||||
firstChar = 0
|
||||
elif (kb.fileReadMode or dump) and conf.firstChar is not None and (isinstance(conf.firstChar, int) or (isinstance(conf.firstChar, basestring) and conf.firstChar.isdigit())):
|
||||
firstChar = int(conf.firstChar) - 1
|
||||
@@ -121,7 +121,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||
else:
|
||||
firstChar = 0
|
||||
|
||||
if "LENGTH(" in expression.upper() or "LEN(" in expression.upper():
|
||||
if re.search(r"(?i)\b(LENGTH|LEN)\(", expression):
|
||||
lastChar = 0
|
||||
elif dump and conf.lastChar is not None and (isinstance(conf.lastChar, int) or (isinstance(conf.lastChar, basestring) and conf.lastChar.isdigit())):
|
||||
lastChar = int(conf.lastChar)
|
||||
@@ -343,7 +343,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||
if result:
|
||||
minValue = posValue
|
||||
|
||||
if type(charTbl) != xrange:
|
||||
if not isinstance(charTbl, xrange):
|
||||
charTbl = charTbl[position:]
|
||||
else:
|
||||
# xrange() - extended virtual charset used for memory/space optimization
|
||||
@@ -351,7 +351,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||
else:
|
||||
maxValue = posValue
|
||||
|
||||
if type(charTbl) != xrange:
|
||||
if not isinstance(charTbl, xrange):
|
||||
charTbl = charTbl[:position]
|
||||
else:
|
||||
charTbl = xrange(charTbl[0], charTbl[position])
|
||||
@@ -390,7 +390,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||
if timeBasedCompare:
|
||||
if kb.adjustTimeDelay is not ADJUST_TIME_DELAY.DISABLE:
|
||||
conf.timeSec += 1
|
||||
warnMsg = "increasing time delay to %d second%s " % (conf.timeSec, 's' if conf.timeSec > 1 else '')
|
||||
warnMsg = "increasing time delay to %d second%s" % (conf.timeSec, 's' if conf.timeSec > 1 else '')
|
||||
logger.warn(warnMsg)
|
||||
|
||||
if kb.adjustTimeDelay is ADJUST_TIME_DELAY.YES:
|
||||
@@ -461,18 +461,15 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||
threadData = getCurrentThreadData()
|
||||
|
||||
while kb.threadContinue:
|
||||
kb.locks.index.acquire()
|
||||
with kb.locks.index:
|
||||
if threadData.shared.index[0] - firstChar >= length:
|
||||
return
|
||||
|
||||
if threadData.shared.index[0] - firstChar >= length:
|
||||
kb.locks.index.release()
|
||||
return
|
||||
|
||||
threadData.shared.index[0] += 1
|
||||
currentCharIndex = threadData.shared.index[0]
|
||||
kb.locks.index.release()
|
||||
threadData.shared.index[0] += 1
|
||||
currentCharIndex = threadData.shared.index[0]
|
||||
|
||||
if kb.threadContinue:
|
||||
charStart = time.time()
|
||||
start = time.time()
|
||||
val = getChar(currentCharIndex, asciiTbl, not(charsetType is None and conf.charset))
|
||||
if val is None:
|
||||
val = INFERENCE_UNKNOWN_CHAR
|
||||
@@ -485,7 +482,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||
|
||||
if kb.threadContinue:
|
||||
if showEta:
|
||||
progress.progress(time.time() - charStart, threadData.shared.index[0])
|
||||
progress.progress(calculateDeltaSeconds(start), threadData.shared.index[0])
|
||||
elif conf.verbose >= 1:
|
||||
startCharIndex = 0
|
||||
endCharIndex = 0
|
||||
@@ -553,7 +550,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||
|
||||
while True:
|
||||
index += 1
|
||||
charStart = time.time()
|
||||
start = time.time()
|
||||
|
||||
# Common prediction feature (a.k.a. "good samaritan")
|
||||
# NOTE: to be used only when multi-threading is not set for
|
||||
@@ -578,7 +575,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||
# Did we have luck?
|
||||
if result:
|
||||
if showEta:
|
||||
progress.progress(time.time() - charStart, len(commonValue))
|
||||
progress.progress(calculateDeltaSeconds(start), len(commonValue))
|
||||
elif conf.verbose in (1, 2) or conf.api:
|
||||
dataToStdout(filterControlChars(commonValue[index - 1:]))
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ def _oneShotErrorUse(expression, field=None, chunkTest=False):
|
||||
output = reduce(lambda x, y: x if x is not None else y, (\
|
||||
extractRegexResult(check, page), \
|
||||
extractRegexResult(check, threadData.lastHTTPError[2] if wasLastResponseHTTPError() else None), \
|
||||
extractRegexResult(check, listToStrValue([headers[header] for header in headers if header.lower() != HTTP_HEADER.URI.lower()] if headers else None)), \
|
||||
extractRegexResult(check, listToStrValue((headers[header] for header in headers if header.lower() != HTTP_HEADER.URI.lower()) if headers else None)), \
|
||||
extractRegexResult(check, threadData.lastRedirectMsg[1] if threadData.lastRedirectMsg and threadData.lastRedirectMsg[0] == threadData.lastRequestUID else None)), \
|
||||
None)
|
||||
|
||||
@@ -142,7 +142,7 @@ def _oneShotErrorUse(expression, field=None, chunkTest=False):
|
||||
else:
|
||||
trimmed = extractRegexResult(trimcheck, page) \
|
||||
or extractRegexResult(trimcheck, threadData.lastHTTPError[2] if wasLastResponseHTTPError() else None) \
|
||||
or extractRegexResult(trimcheck, listToStrValue([headers[header] for header in headers if header.lower() != HTTP_HEADER.URI.lower()] if headers else None)) \
|
||||
or extractRegexResult(trimcheck, listToStrValue((headers[header] for header in headers if header.lower() != HTTP_HEADER.URI.lower()) if headers else None)) \
|
||||
or extractRegexResult(trimcheck, threadData.lastRedirectMsg[1] if threadData.lastRedirectMsg and threadData.lastRedirectMsg[0] == threadData.lastRequestUID else None)
|
||||
|
||||
if trimmed:
|
||||
|
||||
+1
-1
@@ -278,7 +278,7 @@ def columnExists(columnFile, regex=None):
|
||||
|
||||
kb.data.cachedColumns[conf.db] = {conf.tbl: columns}
|
||||
|
||||
for _ in map(lambda x: (conf.db, conf.tbl, x[0], x[1]), columns.items()):
|
||||
for _ in ((conf.db, conf.tbl, item[0], item[1]) for item in columns.items()):
|
||||
if _ not in kb.brute.columns:
|
||||
kb.brute.columns.append(_)
|
||||
|
||||
|
||||
@@ -64,14 +64,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 " % getSafeExString(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 " % getSafeExString(ex)
|
||||
errMsg = "invalid URL detected ('%s'). skipping " % getSafeExString(ex)
|
||||
errMsg += "URL '%s'" % current
|
||||
logger.critical(errMsg)
|
||||
|
||||
|
||||
+9
-3
@@ -153,7 +153,7 @@ def mssql_passwd(password, salt, uppercase=False):
|
||||
"""
|
||||
|
||||
binsalt = hexdecode(salt)
|
||||
unistr = "".join(map(lambda c: ("%s\0" if ord(c) < 256 else "%s") % utf8encode(c), password))
|
||||
unistr = "".join(("%s\0" if ord(_) < 256 else "%s") % utf8encode(_) for _ in password)
|
||||
|
||||
retVal = "0100%s%s" % (salt, sha1(unistr + binsalt).hexdigest())
|
||||
|
||||
@@ -171,7 +171,7 @@ def mssql_old_passwd(password, salt, uppercase=True): # prior to version '2005'
|
||||
"""
|
||||
|
||||
binsalt = hexdecode(salt)
|
||||
unistr = "".join(map(lambda c: ("%s\0" if ord(c) < 256 else "%s") % utf8encode(c), password))
|
||||
unistr = "".join(("%s\0" if ord(_) < 256 else "%s") % utf8encode(_) for _ in password)
|
||||
|
||||
retVal = "0100%s%s%s" % (salt, sha1(unistr + binsalt).hexdigest(), sha1(unistr.upper() + binsalt).hexdigest())
|
||||
|
||||
@@ -187,7 +187,7 @@ def mssql_new_passwd(password, salt, uppercase=False):
|
||||
"""
|
||||
|
||||
binsalt = hexdecode(salt)
|
||||
unistr = "".join(map(lambda c: ("%s\0" if ord(c) < 256 else "%s") % utf8encode(c), password))
|
||||
unistr = "".join(("%s\0" if ord(_) < 256 else "%s") % utf8encode(_) for _ in password)
|
||||
|
||||
retVal = "0200%s%s" % (salt, sha512(unistr + binsalt).hexdigest())
|
||||
|
||||
@@ -366,6 +366,12 @@ def unix_md5_passwd(password, salt, magic="$1$", **kwargs):
|
||||
if isinstance(password, unicode):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
|
||||
if isinstance(magic, unicode):
|
||||
magic = magic.encode(UNICODE_ENCODING)
|
||||
|
||||
if isinstance(salt, unicode):
|
||||
salt = salt.encode(UNICODE_ENCODING)
|
||||
|
||||
salt = salt[:8]
|
||||
ctx = password + magic + salt
|
||||
final = md5(password + salt + password).digest()
|
||||
|
||||
+1
-1
@@ -122,7 +122,7 @@ def _search(dork):
|
||||
elif choice == '2':
|
||||
url = "https://www.bing.com/search?q=%s&first=%d" % (urlencode(dork, convall=True), (gpage - 1) * 10 + 1)
|
||||
regex = BING_REGEX
|
||||
elif choice == '1':
|
||||
else:
|
||||
url = "https://duckduckgo.com/d.js?"
|
||||
url += "q=%s&p=%d&s=100" % (urlencode(dork, convall=True), gpage)
|
||||
regex = DUCKDUCKGO_REGEX
|
||||
|
||||
@@ -279,7 +279,7 @@ class Filesystem:
|
||||
self.checkDbmsOs()
|
||||
|
||||
if localFile.endswith('_'):
|
||||
localFile = decloakToTemp(localFile)
|
||||
localFile = getUnicode(decloakToTemp(localFile))
|
||||
|
||||
if conf.direct or isStackingAvailable():
|
||||
if isStackingAvailable():
|
||||
|
||||
+1
-5
@@ -1,8 +1,4 @@
|
||||
Due to the anti-virus positive detection of shell scripts stored inside
|
||||
this folder, we needed to somehow circumvent this. As from the plain
|
||||
sqlmap users perspective nothing has to be done prior to their usage by
|
||||
sqlmap, but if you want to have access to their original source code use
|
||||
the decrypt functionality of the ../extra/cloak/cloak.py utility.
|
||||
Due to the anti-virus positive detection of shell scripts stored inside this folder, we needed to somehow circumvent this. As from the plain sqlmap users perspective nothing has to be done prior to their usage by sqlmap, but if you want to have access to their original source code use the decrypt functionality of the ../extra/cloak/cloak.py utility.
|
||||
|
||||
To prepare the original scripts to the cloaked form use this command:
|
||||
find backdoor.* stager.* -type f -exec python ../extra/cloak/cloak.py -i '{}' \;
|
||||
|
||||
@@ -36,7 +36,6 @@ warnings.filterwarnings(action="ignore", category=DeprecationWarning)
|
||||
from lib.core.data import logger
|
||||
|
||||
try:
|
||||
from lib.controller.controller import start
|
||||
from lib.core.common import banner
|
||||
from lib.core.common import checkIntegrity
|
||||
from lib.core.common import createGithubIssue
|
||||
@@ -58,15 +57,12 @@ try:
|
||||
from lib.core.exception import SqlmapUserQuitException
|
||||
from lib.core.option import initOptions
|
||||
from lib.core.option import init
|
||||
from lib.core.profiling import profile
|
||||
from lib.core.settings import GIT_PAGE
|
||||
from lib.core.settings import IS_WIN
|
||||
from lib.core.settings import LEGAL_DISCLAIMER
|
||||
from lib.core.settings import THREAD_FINALIZATION_TIMEOUT
|
||||
from lib.core.settings import UNICODE_ENCODING
|
||||
from lib.core.settings import VERSION
|
||||
from lib.core.testing import smokeTest
|
||||
from lib.core.testing import liveTest
|
||||
from lib.parse.cmdline import cmdLineParser
|
||||
except KeyboardInterrupt:
|
||||
errMsg = "user aborted"
|
||||
@@ -144,13 +140,18 @@ def main():
|
||||
|
||||
init()
|
||||
|
||||
# Postponed imports (faster start)
|
||||
if conf.profile:
|
||||
from lib.core.profiling import profile
|
||||
profile()
|
||||
elif conf.smokeTest:
|
||||
from lib.core.testing import smokeTest
|
||||
smokeTest()
|
||||
elif conf.liveTest:
|
||||
from lib.core.testing import liveTest
|
||||
liveTest()
|
||||
else:
|
||||
from lib.controller.controller import start
|
||||
try:
|
||||
start()
|
||||
except thread.error as ex:
|
||||
@@ -262,6 +263,12 @@ def main():
|
||||
logger.error(errMsg)
|
||||
raise SystemExit
|
||||
|
||||
elif all(_ in excMsg for _ in ("twophase", "sqlalchemy")):
|
||||
errMsg = "please update the 'sqlalchemy' package"
|
||||
errMsg += "(Reference: https://github.com/apache/incubator-superset/issues/3447)"
|
||||
logger.error(errMsg)
|
||||
raise SystemExit
|
||||
|
||||
elif "can't start new thread" in excMsg:
|
||||
errMsg = "there has been a problem while creating new thread instance. "
|
||||
errMsg += "Please make sure that you are not running too many processes"
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
#!/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.HIGHEST
|
||||
|
||||
def dependencies():
|
||||
pass
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces instances like 'IFNULL(A, B)' with 'CASE WHEN ISNULL(A) THEN (B) ELSE (A) END'
|
||||
|
||||
Requirement:
|
||||
* MySQL
|
||||
* SQLite (possibly)
|
||||
* SAP MaxDB (possibly)
|
||||
|
||||
Tested against:
|
||||
* MySQL 5.0 and 5.5
|
||||
|
||||
Notes:
|
||||
* Useful to bypass very weak and bespoke web application firewalls
|
||||
that filter the IFNULL() functions
|
||||
|
||||
>>> tamper('IFNULL(1, 2)')
|
||||
'CASE WHEN ISNULL(1) THEN (2) ELSE (1) END'
|
||||
"""
|
||||
|
||||
if payload and payload.find("IFNULL") > -1:
|
||||
while payload.find("IFNULL(") > -1:
|
||||
index = payload.find("IFNULL(")
|
||||
depth = 1
|
||||
comma, end = None, None
|
||||
|
||||
for i in xrange(index + len("IFNULL("), len(payload)):
|
||||
if depth == 1 and payload[i] == ',':
|
||||
comma = i
|
||||
|
||||
elif depth == 1 and payload[i] == ')':
|
||||
end = i
|
||||
break
|
||||
|
||||
elif payload[i] == '(':
|
||||
depth += 1
|
||||
|
||||
elif payload[i] == ')':
|
||||
depth -= 1
|
||||
|
||||
if comma and end:
|
||||
_ = payload[index + len("IFNULL("):comma]
|
||||
__ = payload[comma + 1:end].lstrip()
|
||||
newVal = "CASE WHEN ISNULL(%s) THEN (%s) ELSE (%s) END" % (_, __, _)
|
||||
payload = payload[:index] + newVal + payload[end + 1:]
|
||||
else:
|
||||
break
|
||||
|
||||
return payload
|
||||
|
||||
|
||||
+37
-34
@@ -21,17 +21,17 @@ f96467fc5cd1d87f52dd7966c8ae6e79 extra/shutils/regressiontest.py
|
||||
5fb9aaf874daa47ea2b672a22740e56b extra/sqlharvest/__init__.py
|
||||
1fc7772edce5a01c31f3932b2fc4c1c6 extra/sqlharvest/sqlharvest.py
|
||||
21bf2b3a7a22b8cd5d96a6457a1b4997 lib/controller/action.py
|
||||
9eadf57517a6064d462b1f5ba9a3280d lib/controller/checks.py
|
||||
91c9ef44927b270ea53b6739ff5b2e76 lib/controller/controller.py
|
||||
beb3207c65d01c1e5d959cd6393cd420 lib/controller/checks.py
|
||||
2db2666dba713c710d248a62b2c1c1fe lib/controller/controller.py
|
||||
d2cdb9e832e18a81e936ca3348144b16 lib/controller/handler.py
|
||||
5fb9aaf874daa47ea2b672a22740e56b lib/controller/__init__.py
|
||||
3672210ed0043fe094df8615e4c5c0c0 lib/core/agent.py
|
||||
d55b4b58019d6dbfddd40ec919f9f172 lib/core/bigarray.py
|
||||
8731cbd68d44f4edbd3b183988f32a40 lib/core/common.py
|
||||
fd69e56ce20a5a49ce10a7a745022378 lib/core/agent.py
|
||||
8d9d771f7e67582c56a96a8d0ccbe4fc lib/core/bigarray.py
|
||||
27d55009305e6409dc17f9c58cb87065 lib/core/common.py
|
||||
54326d3a690f8b26fe5a5da1a589b369 lib/core/convert.py
|
||||
90b1b08368ac8a859300e6fa6a8c796e lib/core/data.py
|
||||
1c14bdbf47b8dba31f73da9ad731a54a lib/core/datatype.py
|
||||
70d60d7a9518083cfa8900b97c065f7a lib/core/decorators.py
|
||||
2c16cdbbccbfcfc0ddac2cff876ce9f3 lib/core/decorators.py
|
||||
d3ed5f9baa074df33390d33164d9d8b5 lib/core/defaults.py
|
||||
96fe4769b6e3e68635fa82cd59cc49fc lib/core/dicts.py
|
||||
956be8ca65c7f04f08c6f2dce710b3b2 lib/core/dump.py
|
||||
@@ -40,18 +40,18 @@ d3ed5f9baa074df33390d33164d9d8b5 lib/core/defaults.py
|
||||
5fb9aaf874daa47ea2b672a22740e56b lib/core/__init__.py
|
||||
f872699e948d0692ce11b54781da814c lib/core/log.py
|
||||
5adb07b2771f26822e94c75c2cb9db0b lib/core/optiondict.py
|
||||
ec6a778b0e74749b916caead78ba88b7 lib/core/option.py
|
||||
e1c000db9be27f973569b1a430629037 lib/core/option.py
|
||||
8764d2d8610fff5f4aef897b2b1f1006 lib/core/profiling.py
|
||||
2de91262fcc6bd51c987fd2f8a59ff31 lib/core/readlineng.py
|
||||
760d9df2a27ded29109b390ab202e72d lib/core/replication.py
|
||||
a2466b62e67f8b31736bac4dac590e51 lib/core/revision.py
|
||||
02d4762140a72fd44668d3dab5eabda9 lib/core/session.py
|
||||
b29170b2a9f29588c3930952a99b2e76 lib/core/settings.py
|
||||
3f8a858155092e17d146cd6021057338 lib/core/settings.py
|
||||
35bffbad762eb9e03db9e93b1c991103 lib/core/shell.py
|
||||
a59ec28371ae067a6fdd8f810edbee3d lib/core/subprocessng.py
|
||||
7c9f2af3c0a8dd89223cfe07b0a0b826 lib/core/target.py
|
||||
d5a04d672a18f78deb2839c3745ff83c lib/core/target.py
|
||||
df8f6475a53d83400c1a3967c0a21bd7 lib/core/testing.py
|
||||
20ae9917fa959ea423d8c28c297b37fe lib/core/threads.py
|
||||
632538fe50f6b3179e1a5a85e8b79741 lib/core/threads.py
|
||||
a119989ca03f8c8fbdf7d3035084eb31 lib/core/unescaper.py
|
||||
e7fb8c09fe7520c32895b859c4edf77a lib/core/update.py
|
||||
c976dd450b663cb4455cd9efbbcf625b lib/core/wordlist.py
|
||||
@@ -66,9 +66,9 @@ e07930095e56de11c297d7ac1a1706f2 lib/parse/html.py
|
||||
d8d9bcf9e7107a5e2cf2dd10f115ac28 lib/parse/payloads.py
|
||||
2b87577dc6d3609e96fc1e049def5b4f lib/parse/sitemap.py
|
||||
d2f13a0e2fef5273d419d06e516122e1 lib/request/basicauthhandler.py
|
||||
669e8cf941bba4a2e987045b3002b8e3 lib/request/basic.py
|
||||
67bcf2499db566ebf46f9a6122399fe6 lib/request/comparison.py
|
||||
a253670611499bc159879122e05622de lib/request/connect.py
|
||||
9ef264b5c0f9e7989b8c2ab91d40400d lib/request/basic.py
|
||||
28348595147a731677c8bef470c6f57a lib/request/comparison.py
|
||||
5a2d97c7b672228e695855ff43fb7960 lib/request/connect.py
|
||||
ad6f76839408d827abfcdc57813f8518 lib/request/direct.py
|
||||
4853bd0d523646315607a6a9a4c0b745 lib/request/dns.py
|
||||
effa0c3e4efceaf4932855e8e6677bf7 lib/request/httpshandler.py
|
||||
@@ -85,33 +85,33 @@ a53a068f7b5651fca1ae8da932ba4d96 lib/takeover/icmpsh.py
|
||||
ac3f47b2f8d2cd530512405b4a23a9db lib/takeover/metasploit.py
|
||||
3309f439e0cb68a707dc3a3c807645b0 lib/takeover/registry.py
|
||||
21b6eff33f5d28c5e167a948976817cb lib/takeover/udf.py
|
||||
916917ef27d12544fdc68265ba28f70e lib/takeover/web.py
|
||||
e49d1213f9ae0c0f922c5aef4febe205 lib/takeover/web.py
|
||||
d3080bf68b4b85ed2c98af5de74e8b73 lib/takeover/xp_cmdshell.py
|
||||
4ec8685f767dc2419e46380320273ff9 lib/techniques/blind/inference.py
|
||||
ca47f20b11f58ce60a0ddfcfca242d3f lib/techniques/blind/inference.py
|
||||
5fb9aaf874daa47ea2b672a22740e56b lib/techniques/blind/__init__.py
|
||||
5fb9aaf874daa47ea2b672a22740e56b lib/techniques/dns/__init__.py
|
||||
95331b2826f28db9ff962670391aa7d6 lib/techniques/dns/test.py
|
||||
82cc907fb335250703072337d8f8cceb lib/techniques/dns/use.py
|
||||
5fb9aaf874daa47ea2b672a22740e56b lib/techniques/error/__init__.py
|
||||
e9e3e8ad72a9cd981e76d6debec05185 lib/techniques/error/use.py
|
||||
5953b814b91e6a03d26f319203b48d01 lib/techniques/error/use.py
|
||||
5fb9aaf874daa47ea2b672a22740e56b lib/techniques/__init__.py
|
||||
5fb9aaf874daa47ea2b672a22740e56b lib/techniques/union/__init__.py
|
||||
fcc3a6ac3b5f7aad86686e5f9adc7a43 lib/techniques/union/test.py
|
||||
505682f95cb23573dd60bf6d0063a632 lib/techniques/union/use.py
|
||||
452cb280aa51a4ddf38d94534a6e8d5f lib/utils/api.py
|
||||
d9d62fa5d7367e7fb23180240c8d03f4 lib/utils/brute.py
|
||||
95e4eab120640fd9330d569a29a25be4 lib/utils/crawler.py
|
||||
48c3f8216b64825c50f5304cb4dadd95 lib/utils/brute.py
|
||||
7e0078da1dff59530d64f9b1e2f68607 lib/utils/crawler.py
|
||||
a2d2087353fb64a8441c3247ae0ad719 lib/utils/deps.py
|
||||
b806de9710a02436e576ac9065816021 lib/utils/getch.py
|
||||
fe3a38f820ae05a95f92ab53e22b46d0 lib/utils/har.py
|
||||
1bdd3e6483d3d7c4fd6ec59e9526b542 lib/utils/hashdb.py
|
||||
e0e8a641c28552ca6794a71b5f12a2fb lib/utils/hash.py
|
||||
193c294d960c310808495a63167eab00 lib/utils/hash.py
|
||||
f20ae1aa6a8d1d5373ace1f7ed3476a7 lib/utils/htmlentities.py
|
||||
5fb9aaf874daa47ea2b672a22740e56b lib/utils/__init__.py
|
||||
06cd61b634ca6142281da699a504cc85 lib/utils/pivotdumptable.py
|
||||
56c922696bd3d05d7be96e73b0650c4e lib/utils/progress.py
|
||||
a861c303293e2e6665b02a57f67fc050 lib/utils/purge.py
|
||||
f6652791bf98a42e3e1532180a0710cf lib/utils/search.py
|
||||
760290393e35e5f53f15ba46e09d59dd lib/utils/search.py
|
||||
b6898e77038842c853932a6662c011be lib/utils/sqlalchemy.py
|
||||
36b95bc7fa2cf4f005a86e516a8cba68 lib/utils/timeout.py
|
||||
a3b51d28b0824d4d2333a3dd792497ac lib/utils/versioncheck.py
|
||||
@@ -206,7 +206,7 @@ c811c9267896033a1d206bdec774782b plugins/generic/custom.py
|
||||
43f19ede05350b42704b55d237f3d715 plugins/generic/databases.py
|
||||
d769db0ec3586855a8197229c2a27ffa plugins/generic/entries.py
|
||||
16882f2840da3161ed4dbf4a7ff8fc8b plugins/generic/enumeration.py
|
||||
c1a3f3c21d17d74298be8c3bf4fa4e66 plugins/generic/filesystem.py
|
||||
ed82a43b822e265919b6164c628e433c plugins/generic/filesystem.py
|
||||
c4f4c6754e09a2418a08d1002184f260 plugins/generic/fingerprint.py
|
||||
5fb9aaf874daa47ea2b672a22740e56b plugins/generic/__init__.py
|
||||
3e9a5909f250dfefd1e51abbf69d3973 plugins/generic/misc.py
|
||||
@@ -215,16 +215,16 @@ f65197bb16a0c7b243a322cf89715891 plugins/generic/syntax.py
|
||||
659b5821b3bfc4c8ef94759bbf968b25 plugins/generic/takeover.py
|
||||
65524d3fc3373c4ec241a6358f634bbd plugins/generic/users.py
|
||||
5fb9aaf874daa47ea2b672a22740e56b plugins/__init__.py
|
||||
b04db3e861edde1f9dd0a3850d5b96c8 shell/backdoor.asp_
|
||||
158bfa168128393dde8d6ed11fe9a1b8 shell/backdoor.aspx_
|
||||
1add5a9a67539e7fd1999c8c20a69d15 shell/backdoor.jsp_
|
||||
09fc3ed6543f4d1885e338b271e5e97a shell/backdoor.php_
|
||||
0e7aba05423c272f051f31165b0e416d shell/stager.asp_
|
||||
c3cc8b7727161e64ab59f312c33b541a shell/stager.aspx_
|
||||
1f7f125f30e0e800beb21e2ebbab18e1 shell/stager.jsp_
|
||||
01e3505e796edf19aad6a996101c81c9 shell/stager.php_
|
||||
b04db3e861edde1f9dd0a3850d5b96c8 shell/backdoors/backdoor.asp_
|
||||
158bfa168128393dde8d6ed11fe9a1b8 shell/backdoors/backdoor.aspx_
|
||||
1add5a9a67539e7fd1999c8c20a69d15 shell/backdoors/backdoor.jsp_
|
||||
09fc3ed6543f4d1885e338b271e5e97a shell/backdoors/backdoor.php_
|
||||
0e7aba05423c272f051f31165b0e416d shell/stagers/stager.asp_
|
||||
c3cc8b7727161e64ab59f312c33b541a shell/stagers/stager.aspx_
|
||||
1f7f125f30e0e800beb21e2ebbab18e1 shell/stagers/stager.jsp_
|
||||
01e3505e796edf19aad6a996101c81c9 shell/stagers/stager.php_
|
||||
c737efc0afe782c5dcfec9d27e827515 sqlmapapi.py
|
||||
e1741dbdee31788ee93dea911faa4ebe sqlmap.py
|
||||
5055a9d152e379fd7d55cbbf06025834 sqlmap.py
|
||||
ba9bb7b0fbfbd408c24bc99b3c8f0fd9 tamper/apostrophemask.py
|
||||
aa046ea026a3c72b714e726a2e775cd4 tamper/apostrophenullencode.py
|
||||
0418d808878bf7cac4a28350116e64d0 tamper/appendnullbyte.py
|
||||
@@ -244,6 +244,7 @@ e9d64dc52b02ae141bca2b2c69540ccc tamper/concat2concatws.py
|
||||
573e3304d0dd5977e5a8a93d24fa3f99 tamper/greatest.py
|
||||
fe4ce7c1d5219fce225048ef8b00a272 tamper/halfversionedmorekeywords.py
|
||||
458fae54979d388da14c3ca23d532830 tamper/htmlencode.py
|
||||
3d78732865cd12e5f490470babd289f6 tamper/ifnull2casewhenisnull.py
|
||||
ccc5edfba7532a27809a80a7606b226f tamper/ifnull2ifisnull.py
|
||||
6a7e92664dff80fe48b1a6f99fcc71b7 tamper/informationschemacomment.py
|
||||
5fb9aaf874daa47ea2b672a22740e56b tamper/__init__.py
|
||||
@@ -391,7 +392,7 @@ ca3ab78d6ed53b7f2c07ed2530d47efd udf/postgresql/windows/32/8.4/lib_postgresqlud
|
||||
58faaa04de90a44c306e862bbbe0ed83 waf/aws.py
|
||||
2347b494b91dc50d93d1437e1302f9f1 waf/baidu.py
|
||||
72fd38a1fa212fb154f74d0c978d489a waf/barracuda.py
|
||||
02aa8b095f7fabd439a3afda0430ca84 waf/bigip.py
|
||||
5c55654a7611e767dd2be797716e2d75 waf/bigip.py
|
||||
5430f2a681071e894fa3c152eebf68e4 waf/binarysec.py
|
||||
2ce52bac62825acd4456817af6f10b14 waf/blockdos.py
|
||||
fe60962fc1d80e557b1d602fbe4934dc waf/ciscoacexml.py
|
||||
@@ -428,11 +429,11 @@ e353eb40d21be9e5ac6ea98f5c71a2f3 waf/radware.py
|
||||
de671bbe9acee86d5e3a66fd4126b4e3 waf/safedog.py
|
||||
b03fdbf8f427ab614303a03416970927 waf/secureiis.py
|
||||
877ea097e56abf01868945a00c2afdea waf/senginx.py
|
||||
2c24d9e5c80ad51cb74f1c4b124d8974 waf/sitelock.py
|
||||
2dee94358969c6b8dab8acb2e9560417 waf/sonicwall.py
|
||||
90f3c0c895d5d564b6614e25549b6355 waf/sitelock.py
|
||||
664f73359b87bfb684fb49df1e0b1fa4 waf/sonicwall.py
|
||||
b384581ce833d147690c7c77c9509bdc waf/sophos.py
|
||||
e9127a67621440fba41e1cd176890851 waf/stingray.py
|
||||
6c87858fc902d272d5effc9ebb944deb waf/sucuri.py
|
||||
b9ede1695617c883e4230e6018753ba4 waf/sucuri.py
|
||||
313245e511fbe1ee6fb5fd344be88240 waf/tencent.py
|
||||
64c0e9c4c32adfd3c230705a7f17a63a waf/teros.py
|
||||
9df516cb9793ba7f906dc0597fdd73a0 waf/trafficshield.py
|
||||
@@ -440,11 +441,13 @@ a4fca90afde376962f09ac10c965b6e7 waf/urlscan.py
|
||||
2952dadc49a810bde918ae70ca9bb042 waf/uspses.py
|
||||
e0e9afe5330645bcf63103cf7df6ef56 waf/varnish.py
|
||||
c6b044f4f29680e0767b36c893b9346b waf/wallarm.py
|
||||
fe451f569a88c198adda6d22b39c9a4b waf/watchguard.py
|
||||
dc78bd60735f4c2b2cfc05dc8b148a56 waf/webappsecure.py
|
||||
755709c2c28da8dc612ce0d277d8ba02 waf/webknight.py
|
||||
07ca74cd2e76310caacb709c5304999b waf/wordfence.py
|
||||
d347378166b781e39569eaaa036268d5 waf/yundun.py
|
||||
c32f8c216fab0a0672f734a48da8d6ff waf/yunsuo.py
|
||||
fd87445df19ad9e58b5ffff464bd7413 waf/zenedge.py
|
||||
e87d59af23b7b18cd56c9883e5f02d5c xml/banner/generic.xml
|
||||
d8925c034263bf1b83e7d8e1c78eec57 xml/banner/mssql.xml
|
||||
b8b56f4aa34bf65365808919b97119a7 xml/banner/mysql.xml
|
||||
|
||||
+2
-1
@@ -16,13 +16,14 @@ def detect(get_page):
|
||||
retval = False
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
_, headers, _ = get_page(get=vector)
|
||||
_, headers, code = get_page(get=vector)
|
||||
retval = headers.get("X-Cnection", "").lower() == "close"
|
||||
retval |= headers.get("X-WA-Info") is not None
|
||||
retval |= re.search(r"\ATS\w{4,}=", headers.get(HTTP_HEADER.SET_COOKIE, ""), re.I) is not None
|
||||
retval |= re.search(r"BigIP|BIGipServer", headers.get(HTTP_HEADER.SET_COOKIE, ""), re.I) is not None
|
||||
retval |= re.search(r"BigIP|BIGipServer", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
retval |= re.search(r"\AF5\Z", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
retval &= code >= 400
|
||||
if retval:
|
||||
break
|
||||
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, _, _ = get_page(get=vector)
|
||||
retval = "SiteLock Incident ID" in (page or "")
|
||||
retval |= any(_ in (page or "") for _ in ("SiteLock Incident ID", "sitelock-site-verification", "sitelock_shield_logo"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ def detect(get_page):
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, _ = get_page(get=vector)
|
||||
retval = "This request is blocked by the SonicWALL" in (page or "")
|
||||
retval |= all(_ in page or "" for _ in ("#shd", "#nsa_banner"))
|
||||
retval |= re.search(r"Web Site Blocked.+\bnsa_banner", page or "", re.I) is not None
|
||||
retval |= re.search(r"SonicWALL", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
if retval:
|
||||
|
||||
@@ -18,6 +18,7 @@ def detect(get_page):
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, code = get_page(get=vector)
|
||||
retval = code == 403 and re.search(r"Sucuri/Cloudproxy", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
retval |= "Access Denied - Sucuri Website Firewall" in (page or "")
|
||||
retval |= "Sucuri WebSite Firewall - CloudProxy - Access Denied" in (page or "")
|
||||
retval |= re.search(r"Questions\?.+cloudproxy@sucuri\.net", (page or "")) is not None
|
||||
if retval:
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2017 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from lib.core.enums import HTTP_HEADER
|
||||
from lib.core.settings import WAF_ATTACK_VECTORS
|
||||
|
||||
__product__ = "WatchGuard (WatchGuard Technologies)"
|
||||
|
||||
def detect(get_page):
|
||||
retval = False
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
_, headers, code = get_page(get=vector)
|
||||
retval = code >= 400 and re.search(r"\AWatchGuard", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
if retval:
|
||||
break
|
||||
|
||||
return retval
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2017 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from lib.core.enums import HTTP_HEADER
|
||||
from lib.core.settings import WAF_ATTACK_VECTORS
|
||||
|
||||
__product__ = "Zenedge Web Application Firewall (Zenedge)"
|
||||
|
||||
def detect(get_page):
|
||||
retval = False
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
_, headers, code = get_page(get=vector)
|
||||
retval = code >= 400 and re.search(r"\AZENEDGE", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
if retval:
|
||||
break
|
||||
|
||||
return retval
|
||||
Reference in New Issue
Block a user