Merge remote-tracking branch 'sqlmapproject/master'

This commit is contained in:
cxh852456 2015-09-07 11:04:09 +08:00
commit c09ae16137
9 changed files with 125 additions and 74 deletions

View File

@ -24,17 +24,19 @@ def hideAscii(data):
return retVal
def cloak(inputFile):
f = open(inputFile, 'rb')
data = zlib.compress(f.read())
f.close()
def cloak(inputFile=None, data=None):
if data is None:
with open(inputFile, "rb") as f:
data = f.read()
return hideAscii(data)
return hideAscii(zlib.compress(data))
def decloak(inputFile):
f = open(inputFile, 'rb')
def decloak(inputFile=None, data=None):
if data is None:
with open(inputFile, "rb") as f:
data = f.read()
try:
data = zlib.decompress(hideAscii(f.read()))
data = zlib.decompress(hideAscii(data))
except:
print 'ERROR: the provided input file \'%s\' does not contain valid cloaked content' % inputFile
sys.exit(1)

View File

@ -3556,7 +3556,7 @@ def findPageForms(content, url, raise_=False, addToTargets=False):
for form in forms:
try:
for control in form.controls:
if hasattr(control, "items") and not control.disabled:
if hasattr(control, "items") and not any((control.disabled, control.readonly)):
# if control has selectable items select first non-disabled
for item in control.items:
if not item.disabled:

View File

@ -75,6 +75,12 @@ GOOGLE_REGEX = r"url\?\w+=((?![^>]+webcache\.googleusercontent\.com)http[^>]+)&(
# Regular expression used for extracting results from DuckDuckGo search
DUCKDUCKGO_REGEX = r'"u":"([^"]+)'
# Regular expression used for extracting results from Disconnect Search
DISCONNECT_SEARCH_REGEX = r'<p class="url wrapword">([^<]+)</p>'
# Dummy user agent for search (if default one returns different results)
DUMMY_SEARCH_USER_AGENT = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:40.0) Gecko/20100101 Firefox/40.0"
# Regular expression used for extracting content from "textual" tags
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>[^<]+)"
@ -437,6 +443,9 @@ BRUTE_COLUMN_EXISTS_TEMPLATE = "EXISTS(SELECT %s FROM %s)"
# Payload used for checking of existence of IDS/WAF (dummier the better)
IDS_WAF_CHECK_PAYLOAD = "AND 1=1 UNION ALL SELECT 1,2,3,table_name FROM information_schema.tables WHERE 2>1-- ../../../etc/passwd"
# Data inside shellcodeexec to be filled with random string
SHELLCODEEXEC_RANDOM_STRING_MARKER = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
# Vectors used for provoking specific WAF/IDS/IPS behavior(s)
WAF_ATTACK_VECTORS = (
"", # NIL

View File

@ -92,8 +92,8 @@ def _setRequestParams():
# Perform checks on POST parameters
if conf.method == HTTPMETHOD.POST and conf.data is None:
errMsg = "HTTP POST method depends on HTTP data value to be posted"
raise SqlmapSyntaxException(errMsg)
logger.warn("detected empty POST body")
conf.data = ""
if conf.data is not None:
conf.method = HTTPMETHOD.POST if not conf.method or conf.method == HTTPMETHOD.GET else conf.method
@ -223,11 +223,11 @@ def _setRequestParams():
message += "in the target URL itself? [Y/n/q] "
test = readInput(message, default="Y")
if not test or test[0] not in ("n", "N"):
if test and test[0] in ("q", "Q"):
raise SqlmapUserQuitException
elif not test or test[0] not in ("n", "N"):
conf.url = "%s%s" % (conf.url, CUSTOM_INJECTION_MARK_CHAR)
kb.processUserMarks = True
elif test[0] in ("q", "Q"):
raise SqlmapUserQuitException
for place, value in ((PLACE.URI, conf.url), (PLACE.CUSTOM_POST, conf.data), (PLACE.CUSTOM_HEADER, str(conf.httpHeaders))):
_ = re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value or "") if place == PLACE.CUSTOM_HEADER else value or ""

View File

@ -32,14 +32,26 @@ class ICMPsh:
self._icmpslave = normalizePath(os.path.join(paths.SQLMAP_EXTRAS_PATH, "icmpsh", "icmpsh.exe_"))
def _selectRhost(self):
message = "what is the back-end DBMS address? [%s] " % self.remoteIP
address = readInput(message, default=self.remoteIP)
address = None
message = "what is the back-end DBMS address? "
if self.remoteIP:
message += "[Enter for '%s' (detected)] " % self.remoteIP
while not address:
address = readInput(message, default=self.remoteIP)
return address
def _selectLhost(self):
message = "what is the local address? [%s] " % self.localIP
address = readInput(message, default=self.localIP)
address = None
message = "what is the local address? "
if self.localIP:
message += "[Enter for '%s' (detected)] " % self.localIP
while not address:
address = readInput(message, default=self.localIP)
return address

View File

@ -8,10 +8,13 @@ See the file 'doc/COPYING' for copying permission
import os
import re
import sys
import tempfile
import time
from subprocess import PIPE
from extra.cloak.cloak import cloak
from extra.cloak.cloak import decloak
from lib.core.common import dataToStdout
from lib.core.common import Backend
from lib.core.common import getLocalIP
@ -34,6 +37,7 @@ from lib.core.exception import SqlmapFilePathException
from lib.core.exception import SqlmapGenericException
from lib.core.settings import IS_WIN
from lib.core.settings import METASPLOIT_SESSION_TIMEOUT
from lib.core.settings import SHELLCODEEXEC_RANDOM_STRING_MARKER
from lib.core.settings import UNICODE_ENCODING
from lib.core.subprocessng import blockingReadFromFD
from lib.core.subprocessng import blockingWriteToFD
@ -288,7 +292,7 @@ class Metasploit:
def _selectRhost(self):
if self.connectionStr.startswith("bind"):
message = "what is the back-end DBMS address? [%s] " % self.remoteIP
message = "what is the back-end DBMS address? [Enter for '%s' (detected)] " % self.remoteIP
address = readInput(message, default=self.remoteIP)
if not address:
@ -304,7 +308,7 @@ class Metasploit:
def _selectLhost(self):
if self.connectionStr.startswith("reverse"):
message = "what is the local address? [%s] " % self.localIP
message = "what is the local address? [Enter for '%s' (detected)] " % self.localIP
address = readInput(message, default=self.localIP)
if not address:
@ -640,6 +644,14 @@ class Metasploit:
if Backend.isOs(OS.WINDOWS):
self.shellcodeexecLocal = os.path.join(self.shellcodeexecLocal, "windows", "shellcodeexec.x%s.exe_" % "32")
content = decloak(self.shellcodeexecLocal)
if SHELLCODEEXEC_RANDOM_STRING_MARKER in content:
content = content.replace(SHELLCODEEXEC_RANDOM_STRING_MARKER, randomStr(len(SHELLCODEEXEC_RANDOM_STRING_MARKER)))
_ = cloak(data=content)
handle, self.shellcodeexecLocal = tempfile.mkstemp(suffix="%s.exe_" % "32")
os.close(handle)
with open(self.shellcodeexecLocal, "w+b") as f:
f.write(_)
else:
self.shellcodeexecLocal = os.path.join(self.shellcodeexecLocal, "linux", "shellcodeexec.x%s_" % Backend.getArch())

View File

@ -21,8 +21,11 @@ from lib.core.enums import CUSTOM_LOGGING
from lib.core.enums import HTTP_HEADER
from lib.core.exception import SqlmapConnectionException
from lib.core.exception import SqlmapGenericException
from lib.core.settings import GOOGLE_REGEX
from lib.core.exception import SqlmapUserQuitException
from lib.core.settings import DUMMY_SEARCH_USER_AGENT
from lib.core.settings import DUCKDUCKGO_REGEX
from lib.core.settings import DISCONNECT_SEARCH_REGEX
from lib.core.settings import GOOGLE_REGEX
from lib.core.settings import HTTP_ACCEPT_ENCODING_HEADER_VALUE
from lib.core.settings import UNICODE_ENCODING
from lib.request.basic import decodePage
@ -96,7 +99,7 @@ class Google(object):
warnMsg += "to get error page information (%d)" % e.code
logger.critical(warnMsg)
return None
except (urllib2.URLError, socket.error, socket.timeout):
except (urllib2.URLError, httplib.error, socket.error, socket.timeout):
errMsg = "unable to connect to Google"
raise SqlmapConnectionException(errMsg)
@ -108,54 +111,67 @@ class Google(object):
raise SqlmapGenericException(warnMsg)
if not retVal:
message = "no usable links found. "
message += "do you want to (re)try with DuckDuckGo? [Y/n] "
output = readInput(message, default="Y")
message = "no usable links found. What do you want to do?"
message += "\n[1] (re)try with DuckDuckGo (default)"
message += "\n[2] (re)try with Disconnect Search"
message += "\n[3] quit"
choice = readInput(message, default="1").strip().upper()
if output.strip().lower() != 'n':
if choice == "Q":
raise SqlmapUserQuitException
elif choice == "2":
url = "https://search.disconnect.me/searchTerms/search?"
url += "start=nav&option=Web"
url += "&query=%s" % urlencode(dork, convall=True)
url += "&ses=Google&location_option=US"
url += "&nextDDG=%s" % urlencode("/search?q=&num=100&hl=en&start=%d&sa=N" % ((gpage - 1) * 10), convall=True)
url += "&sa=N&showIcons=false&filterIcons=none&js_enabled=1"
regex = DISCONNECT_SEARCH_REGEX
else:
url = "https://duckduckgo.com/d.js?"
url += "q=%s&p=%d&s=100" % (urlencode(dork, convall=True), gpage)
regex = DUCKDUCKGO_REGEX
if not conf.randomAgent:
self.opener.addheaders = [_ for _ in self.opener.addheaders if _[0].lower() != HTTP_HEADER.USER_AGENT.lower()]
self.opener.addheaders.append((HTTP_HEADER.USER_AGENT, "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0"))
if not conf.randomAgent:
self.opener.addheaders = [_ for _ in self.opener.addheaders if _[0].lower() != HTTP_HEADER.USER_AGENT.lower()]
self.opener.addheaders.append((HTTP_HEADER.USER_AGENT, DUMMY_SEARCH_USER_AGENT))
self.opener.addheaders = [_ for _ in self.opener.addheaders if _[0].lower() != HTTP_HEADER.ACCEPT_ENCODING.lower()]
self.opener.addheaders.append((HTTP_HEADER.ACCEPT_ENCODING, HTTP_ACCEPT_ENCODING_HEADER_VALUE))
self.opener.addheaders = [_ for _ in self.opener.addheaders if _[0].lower() != HTTP_HEADER.ACCEPT_ENCODING.lower()]
self.opener.addheaders.append((HTTP_HEADER.ACCEPT_ENCODING, HTTP_ACCEPT_ENCODING_HEADER_VALUE))
try:
conn = self.opener.open(url)
requestMsg = "HTTP request:\nGET %s" % url
requestMsg += " %s" % httplib.HTTPConnection._http_vsn_str
logger.log(CUSTOM_LOGGING.TRAFFIC_OUT, requestMsg)
page = conn.read()
code = conn.code
status = conn.msg
responseHeaders = conn.info()
page = decodePage(page, responseHeaders.get("Content-Encoding"), responseHeaders.get("Content-Type"))
responseMsg = "HTTP response (%s - %d):\n" % (status, code)
if conf.verbose <= 4:
responseMsg += getUnicode(responseHeaders, UNICODE_ENCODING)
elif conf.verbose > 4:
responseMsg += "%s\n%s\n" % (responseHeaders, page)
logger.log(CUSTOM_LOGGING.TRAFFIC_IN, responseMsg)
except urllib2.HTTPError, e:
try:
conn = self.opener.open(url)
page = e.read()
except socket.timeout:
warnMsg = "connection timed out while trying "
warnMsg += "to get error page information (%d)" % e.code
logger.critical(warnMsg)
return None
except:
errMsg = "unable to connect"
raise SqlmapConnectionException(errMsg)
requestMsg = "HTTP request:\nGET %s" % url
requestMsg += " %s" % httplib.HTTPConnection._http_vsn_str
logger.log(CUSTOM_LOGGING.TRAFFIC_OUT, requestMsg)
page = conn.read()
code = conn.code
status = conn.msg
responseHeaders = conn.info()
page = decodePage(page, responseHeaders.get("Content-Encoding"), responseHeaders.get("Content-Type"))
responseMsg = "HTTP response (%s - %d):\n" % (status, code)
if conf.verbose <= 4:
responseMsg += getUnicode(responseHeaders, UNICODE_ENCODING)
elif conf.verbose > 4:
responseMsg += "%s\n%s\n" % (responseHeaders, page)
logger.log(CUSTOM_LOGGING.TRAFFIC_IN, responseMsg)
except urllib2.HTTPError, e:
try:
page = e.read()
except socket.timeout:
warnMsg = "connection timed out while trying "
warnMsg += "to get error page information (%d)" % e.code
logger.critical(warnMsg)
return None
except:
errMsg = "unable to connect to DuckDuckGo"
raise SqlmapConnectionException(errMsg)
retVal = [urllib.unquote(match.group(1)) for match in re.finditer(DUCKDUCKGO_REGEX, page, re.I | re.S)]
retVal = [urllib.unquote(match.group(1)) for match in re.finditer(regex, page, re.I | re.S)]
return retVal

View File

@ -55,10 +55,10 @@ class Filesystem:
localFileSize = os.path.getsize(localFile)
if fileRead and Backend.isDbms(DBMS.PGSQL):
logger.info("length of read file %s cannot be checked on PostgreSQL" % remoteFile)
logger.info("length of read file '%s' cannot be checked on PostgreSQL" % remoteFile)
sameFile = True
else:
logger.debug("checking the length of the remote file %s" % remoteFile)
logger.debug("checking the length of the remote file '%s'" % remoteFile)
remoteFileSize = inject.getValue(lengthQuery, resumeValue=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
sameFile = None
@ -69,14 +69,14 @@ class Filesystem:
if localFileSize == remoteFileSize:
sameFile = True
infoMsg = "the local file %s and the remote file " % localFile
infoMsg += "%s have the same size (%db)" % (remoteFile, localFileSize)
infoMsg = "the local file '%s' and the remote file " % localFile
infoMsg += "'%s' have the same size (%d B)" % (remoteFile, localFileSize)
elif remoteFileSize > localFileSize:
infoMsg = "the remote file %s is larger (%db) than " % (remoteFile, remoteFileSize)
infoMsg += "the local file %s (%db)" % (localFile, localFileSize)
infoMsg = "the remote file '%s' is larger (%d B) than " % (remoteFile, remoteFileSize)
infoMsg += "the local file '%s' (%dB)" % (localFile, localFileSize)
else:
infoMsg = "the remote file %s is smaller (%db) than " % (remoteFile, remoteFileSize)
infoMsg += "file %s (%db)" % (localFile, localFileSize)
infoMsg = "the remote file '%s' is smaller (%d B) than " % (remoteFile, remoteFileSize)
infoMsg += "file '%s' (%d B)" % (localFile, localFileSize)
logger.info(infoMsg)
else:
@ -153,7 +153,7 @@ class Filesystem:
if forceCheck is not True:
message = "do you want confirmation that the local file '%s' " % localFile
message += "has been successfully written on the back-end DBMS "
message += "file system (%s)? [Y/n] " % remoteFile
message += "file system ('%s')? [Y/n] " % remoteFile
output = readInput(message, default="Y")
if forceCheck or (output and output.lower() == "y"):
@ -276,14 +276,14 @@ class Filesystem:
if conf.direct or isStackingAvailable():
if isStackingAvailable():
debugMsg = "going to upload the %s file with " % fileType
debugMsg = "going to upload the file '%s' with " % fileType
debugMsg += "stacked query SQL injection technique"
logger.debug(debugMsg)
written = self.stackedWriteFile(localFile, remoteFile, fileType, forceCheck)
self.cleanup(onlyFileTbl=True)
elif isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) and Backend.isDbms(DBMS.MYSQL):
debugMsg = "going to upload the %s file with " % fileType
debugMsg = "going to upload the file '%s' with " % fileType
debugMsg += "UNION query SQL injection technique"
logger.debug(debugMsg)