mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-05-21 13:26:07 +03:00
Some testing stuff
This commit is contained in:
parent
57f17794c4
commit
0e9dd9b0be
|
@ -191,7 +191,7 @@ class ReqHandler(BaseHTTPRequestHandler):
|
||||||
length = int(self.headers.get("Content-length", 0))
|
length = int(self.headers.get("Content-length", 0))
|
||||||
if length:
|
if length:
|
||||||
data = self.rfile.read(length)
|
data = self.rfile.read(length)
|
||||||
data = unquote_plus(data.decode(UNICODE_ENCODING))
|
data = unquote_plus(data.decode(UNICODE_ENCODING, "ignore"))
|
||||||
self.data = data
|
self.data = data
|
||||||
self.do_REQUEST()
|
self.do_REQUEST()
|
||||||
|
|
||||||
|
|
|
@ -252,8 +252,6 @@ optDict = {
|
||||||
"forceDns": "boolean",
|
"forceDns": "boolean",
|
||||||
"murphyRate": "integer",
|
"murphyRate": "integer",
|
||||||
"smokeTest": "boolean",
|
"smokeTest": "boolean",
|
||||||
"stopFail": "boolean",
|
|
||||||
"runCase": "string",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"API": {
|
"API": {
|
||||||
|
|
|
@ -18,7 +18,7 @@ from lib.core.enums import OS
|
||||||
from thirdparty.six import unichr as _unichr
|
from thirdparty.six import unichr as _unichr
|
||||||
|
|
||||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||||
VERSION = "1.4.1.11"
|
VERSION = "1.4.1.12"
|
||||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||||
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
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)
|
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
||||||
|
|
|
@ -7,51 +7,33 @@ See the file 'LICENSE' for copying permission
|
||||||
|
|
||||||
from __future__ import division
|
from __future__ import division
|
||||||
|
|
||||||
import codecs
|
|
||||||
import doctest
|
import doctest
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
import shutil
|
|
||||||
import socket
|
import socket
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import traceback
|
|
||||||
|
|
||||||
from extra.vulnserver import vulnserver
|
from extra.vulnserver import vulnserver
|
||||||
from lib.controller.controller import start
|
|
||||||
from lib.core.common import clearColors
|
from lib.core.common import clearColors
|
||||||
from lib.core.common import clearConsoleLine
|
from lib.core.common import clearConsoleLine
|
||||||
from lib.core.common import dataToStdout
|
from lib.core.common import dataToStdout
|
||||||
|
from lib.core.common import randomInt
|
||||||
|
from lib.core.common import randomStr
|
||||||
from lib.core.common import shellExec
|
from lib.core.common import shellExec
|
||||||
from lib.core.compat import round
|
from lib.core.compat import round
|
||||||
from lib.core.compat import xrange
|
from lib.core.compat import xrange
|
||||||
from lib.core.convert import encodeBase64
|
from lib.core.convert import encodeBase64
|
||||||
from lib.core.convert import getUnicode
|
|
||||||
from lib.core.data import conf
|
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.data import paths
|
from lib.core.data import paths
|
||||||
from lib.core.data import queries
|
from lib.core.data import queries
|
||||||
from lib.core.enums import MKSTEMP_PREFIX
|
|
||||||
from lib.core.exception import SqlmapBaseException
|
|
||||||
from lib.core.log import LOGGER_HANDLER
|
|
||||||
from lib.core.option import init
|
|
||||||
from lib.core.option import initOptions
|
|
||||||
from lib.core.optiondict import optDict
|
|
||||||
from lib.core.settings import UNICODE_ENCODING
|
|
||||||
from lib.parse.cmdline import cmdLineParser
|
|
||||||
|
|
||||||
class Failures(object):
|
|
||||||
failedItems = None
|
|
||||||
failedParseOn = None
|
|
||||||
failedTraceBack = None
|
|
||||||
|
|
||||||
_failures = Failures()
|
|
||||||
_rand = 0
|
_rand = 0
|
||||||
|
|
||||||
def vulnTest():
|
def vulnTest():
|
||||||
|
@ -154,6 +136,63 @@ def vulnTest():
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
|
def fuzzTest():
|
||||||
|
count = 0
|
||||||
|
address, port = "127.0.0.10", random.randint(1025, 65535)
|
||||||
|
|
||||||
|
def _thread():
|
||||||
|
vulnserver.init(quiet=True)
|
||||||
|
vulnserver.run(address=address, port=port)
|
||||||
|
|
||||||
|
thread = threading.Thread(target=_thread)
|
||||||
|
thread.daemon = True
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
try:
|
||||||
|
s.connect((address, port))
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
handle, config = tempfile.mkstemp(suffix=".conf")
|
||||||
|
os.close(handle)
|
||||||
|
|
||||||
|
url = "http://%s:%d/?id=1" % (address, port)
|
||||||
|
|
||||||
|
content = open(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.conf"))).read().replace("url =", "url = %s" % url)
|
||||||
|
open(config, "w+").write(content)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
lines = content.split("\n")
|
||||||
|
|
||||||
|
for i in xrange(20):
|
||||||
|
j = random.randint(0, len(lines) - 1)
|
||||||
|
if lines[j].strip().endswith('='):
|
||||||
|
lines[j] += random.sample(("True", "False", randomStr(), str(randomInt())), 1)[0]
|
||||||
|
|
||||||
|
k = random.randint(0, len(lines) - 1)
|
||||||
|
if '=' in lines[k]:
|
||||||
|
lines[k] += chr(random.randint(0, 255))
|
||||||
|
|
||||||
|
open(config, "w+").write("\n".join(lines))
|
||||||
|
|
||||||
|
cmd = "%s %s -c %s --batch --flush-session --technique=%s --banner" % (sys.executable, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.py")), config, random.sample("BEUQ", 1)[0])
|
||||||
|
output = shellExec(cmd)
|
||||||
|
|
||||||
|
if "Traceback" in output:
|
||||||
|
dataToStdout("---\n\n$ %s\n" % cmd)
|
||||||
|
dataToStdout("%s---\n" % clearColors(output))
|
||||||
|
else:
|
||||||
|
handle, config = tempfile.mkstemp(prefix="sqlmapcrash", suffix=".conf")
|
||||||
|
os.close(handle)
|
||||||
|
open(config, "w+").write("\n".join(lines))
|
||||||
|
|
||||||
|
dataToStdout("\r%d\r" % count)
|
||||||
|
|
||||||
|
count += 1
|
||||||
|
|
||||||
def dirtyPatchRandom():
|
def dirtyPatchRandom():
|
||||||
"""
|
"""
|
||||||
Unifying random generated data across different Python versions
|
Unifying random generated data across different Python versions
|
||||||
|
@ -274,109 +313,3 @@ def smokeTest():
|
||||||
logger.error("smoke test final result: FAILED")
|
logger.error("smoke test final result: FAILED")
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
def adjustValueType(tagName, value):
|
|
||||||
for family in optDict:
|
|
||||||
for name, type_ in optDict[family].items():
|
|
||||||
if type(type_) == tuple:
|
|
||||||
type_ = type_[0]
|
|
||||||
if tagName == name:
|
|
||||||
if type_ == "boolean":
|
|
||||||
value = (value == "True")
|
|
||||||
elif type_ == "integer":
|
|
||||||
value = int(value)
|
|
||||||
elif type_ == "float":
|
|
||||||
value = float(value)
|
|
||||||
break
|
|
||||||
return value
|
|
||||||
|
|
||||||
def initCase(switches, count):
|
|
||||||
_failures.failedItems = []
|
|
||||||
_failures.failedParseOn = None
|
|
||||||
_failures.failedTraceBack = None
|
|
||||||
|
|
||||||
paths.SQLMAP_OUTPUT_PATH = tempfile.mkdtemp(prefix="%s%d-" % (MKSTEMP_PREFIX.TESTING, count))
|
|
||||||
paths.SQLMAP_DUMP_PATH = os.path.join(paths.SQLMAP_OUTPUT_PATH, "%s", "dump")
|
|
||||||
paths.SQLMAP_FILES_PATH = os.path.join(paths.SQLMAP_OUTPUT_PATH, "%s", "files")
|
|
||||||
|
|
||||||
logger.debug("using output directory '%s' for this test case" % paths.SQLMAP_OUTPUT_PATH)
|
|
||||||
|
|
||||||
LOGGER_HANDLER.stream = sys.stdout = tempfile.SpooledTemporaryFile(max_size=0, mode="w+b", prefix="sqlmapstdout-")
|
|
||||||
|
|
||||||
cmdLineOptions = cmdLineParser()
|
|
||||||
|
|
||||||
if switches:
|
|
||||||
for key, value in switches.items():
|
|
||||||
if key in cmdLineOptions.__dict__:
|
|
||||||
cmdLineOptions.__dict__[key] = value
|
|
||||||
|
|
||||||
initOptions(cmdLineOptions, True)
|
|
||||||
init()
|
|
||||||
|
|
||||||
def cleanCase():
|
|
||||||
shutil.rmtree(paths.SQLMAP_OUTPUT_PATH, True)
|
|
||||||
|
|
||||||
def runCase(parse):
|
|
||||||
retVal = True
|
|
||||||
handled_exception = None
|
|
||||||
unhandled_exception = None
|
|
||||||
result = False
|
|
||||||
console = ""
|
|
||||||
|
|
||||||
try:
|
|
||||||
result = start()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
pass
|
|
||||||
except SqlmapBaseException as ex:
|
|
||||||
handled_exception = ex
|
|
||||||
except Exception as ex:
|
|
||||||
unhandled_exception = ex
|
|
||||||
finally:
|
|
||||||
sys.stdout.seek(0)
|
|
||||||
console = sys.stdout.read()
|
|
||||||
LOGGER_HANDLER.stream = sys.stdout = sys.__stdout__
|
|
||||||
|
|
||||||
if unhandled_exception:
|
|
||||||
_failures.failedTraceBack = "unhandled exception: %s" % str(traceback.format_exc())
|
|
||||||
retVal = None
|
|
||||||
elif handled_exception:
|
|
||||||
_failures.failedTraceBack = "handled exception: %s" % str(traceback.format_exc())
|
|
||||||
retVal = None
|
|
||||||
elif result is False: # this means no SQL injection has been detected - if None, ignore
|
|
||||||
retVal = False
|
|
||||||
|
|
||||||
console = getUnicode(console, encoding=sys.stdin.encoding)
|
|
||||||
|
|
||||||
if parse and retVal:
|
|
||||||
with codecs.open(conf.dumper.getOutputFile(), "rb", UNICODE_ENCODING) as f:
|
|
||||||
content = f.read()
|
|
||||||
|
|
||||||
for item, parse_from_console_output in parse:
|
|
||||||
parse_on = console if parse_from_console_output else content
|
|
||||||
|
|
||||||
if item.startswith("r'") and item.endswith("'"):
|
|
||||||
if not re.search(item[2:-1], parse_on, re.DOTALL):
|
|
||||||
retVal = None
|
|
||||||
_failures.failedItems.append(item)
|
|
||||||
|
|
||||||
elif item not in parse_on:
|
|
||||||
retVal = None
|
|
||||||
_failures.failedItems.append(item)
|
|
||||||
|
|
||||||
if _failures.failedItems:
|
|
||||||
_failures.failedParseOn = console
|
|
||||||
|
|
||||||
elif retVal is False:
|
|
||||||
_failures.failedParseOn = console
|
|
||||||
|
|
||||||
return retVal
|
|
||||||
|
|
||||||
def replaceVars(item, vars_):
|
|
||||||
retVal = item
|
|
||||||
|
|
||||||
if item and vars_:
|
|
||||||
for var in re.findall(r"\$\{([^}]+)\}", item):
|
|
||||||
if var in vars_:
|
|
||||||
retVal = retVal.replace("${%s}" % var, vars_[var])
|
|
||||||
|
|
||||||
return retVal
|
|
||||||
|
|
|
@ -790,10 +790,7 @@ def cmdLineParser(argv=None):
|
||||||
parser.add_argument("--vuln-test", dest="vulnTest", action="store_true",
|
parser.add_argument("--vuln-test", dest="vulnTest", action="store_true",
|
||||||
help=SUPPRESS)
|
help=SUPPRESS)
|
||||||
|
|
||||||
parser.add_argument("--stop-fail", dest="stopFail", action="store_true",
|
parser.add_argument("--fuzz-test", dest="fuzzTest", action="store_true",
|
||||||
help=SUPPRESS)
|
|
||||||
|
|
||||||
parser.add_argument("--run-case", dest="runCase",
|
|
||||||
help=SUPPRESS)
|
help=SUPPRESS)
|
||||||
|
|
||||||
# API options
|
# API options
|
||||||
|
@ -1002,7 +999,7 @@ def cmdLineParser(argv=None):
|
||||||
if args.dummy:
|
if args.dummy:
|
||||||
args.url = args.url or DUMMY_URL
|
args.url = args.url or DUMMY_URL
|
||||||
|
|
||||||
if not any((args.direct, args.url, args.logFile, args.bulkFile, args.googleDork, args.configFile, args.requestFile, args.updateAll, args.smokeTest, args.vulnTest, args.wizard, args.dependencies, args.purge, args.listTampers, args.hashFile)):
|
if not any((args.direct, args.url, args.logFile, args.bulkFile, args.googleDork, args.configFile, args.requestFile, args.updateAll, args.smokeTest, args.vulnTest, args.fuzzTest, args.wizard, args.dependencies, args.purge, args.listTampers, args.hashFile)):
|
||||||
errMsg = "missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, --list-tampers, --wizard, --update, --purge or --dependencies). "
|
errMsg = "missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, --list-tampers, --wizard, --update, --purge or --dependencies). "
|
||||||
errMsg += "Use -h for basic and -hh for advanced help\n"
|
errMsg += "Use -h for basic and -hh for advanced help\n"
|
||||||
parser.error(errMsg)
|
parser.error(errMsg)
|
||||||
|
|
|
@ -173,6 +173,9 @@ def main():
|
||||||
elif conf.vulnTest:
|
elif conf.vulnTest:
|
||||||
from lib.core.testing import vulnTest
|
from lib.core.testing import vulnTest
|
||||||
os._exitcode = 1 - (vulnTest() or 0)
|
os._exitcode = 1 - (vulnTest() or 0)
|
||||||
|
elif conf.fuzzTest:
|
||||||
|
from lib.core.testing import fuzzTest
|
||||||
|
fuzzTest()
|
||||||
else:
|
else:
|
||||||
from lib.controller.controller import start
|
from lib.controller.controller import start
|
||||||
if conf.profile and six.PY2:
|
if conf.profile and six.PY2:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user