|
7 | 7 |
|
8 | 8 | from __future__ import division |
9 | 9 |
|
10 | | -import codecs |
11 | 10 | import doctest |
12 | 11 | import logging |
13 | 12 | import os |
14 | 13 | import random |
15 | 14 | import re |
16 | | -import shutil |
17 | 15 | import socket |
18 | 16 | import sqlite3 |
19 | 17 | import sys |
20 | 18 | import tempfile |
21 | 19 | import threading |
22 | 20 | import time |
23 | | -import traceback |
24 | 21 |
|
25 | 22 | from extra.vulnserver import vulnserver |
26 | | -from lib.controller.controller import start |
27 | 23 | from lib.core.common import clearColors |
28 | 24 | from lib.core.common import clearConsoleLine |
29 | 25 | from lib.core.common import dataToStdout |
| 26 | +from lib.core.common import randomInt |
| 27 | +from lib.core.common import randomStr |
30 | 28 | from lib.core.common import shellExec |
31 | 29 | from lib.core.compat import round |
32 | 30 | from lib.core.compat import xrange |
33 | 31 | from lib.core.convert import encodeBase64 |
34 | | -from lib.core.convert import getUnicode |
35 | | -from lib.core.data import conf |
36 | 32 | from lib.core.data import kb |
37 | 33 | from lib.core.data import logger |
38 | 34 | from lib.core.data import paths |
39 | 35 | from lib.core.data import queries |
40 | | -from lib.core.enums import MKSTEMP_PREFIX |
41 | | -from lib.core.exception import SqlmapBaseException |
42 | | -from lib.core.log import LOGGER_HANDLER |
43 | | -from lib.core.option import init |
44 | | -from lib.core.option import initOptions |
45 | | -from lib.core.optiondict import optDict |
46 | | -from lib.core.settings import UNICODE_ENCODING |
47 | | -from lib.parse.cmdline import cmdLineParser |
48 | | - |
49 | | -class Failures(object): |
50 | | - failedItems = None |
51 | | - failedParseOn = None |
52 | | - failedTraceBack = None |
53 | | - |
54 | | -_failures = Failures() |
| 36 | + |
55 | 37 | _rand = 0 |
56 | 38 |
|
57 | 39 | def vulnTest(): |
@@ -154,6 +136,63 @@ def _thread(): |
154 | 136 |
|
155 | 137 | return retVal |
156 | 138 |
|
| 139 | +def fuzzTest(): |
| 140 | + count = 0 |
| 141 | + address, port = "127.0.0.10", random.randint(1025, 65535) |
| 142 | + |
| 143 | + def _thread(): |
| 144 | + vulnserver.init(quiet=True) |
| 145 | + vulnserver.run(address=address, port=port) |
| 146 | + |
| 147 | + thread = threading.Thread(target=_thread) |
| 148 | + thread.daemon = True |
| 149 | + thread.start() |
| 150 | + |
| 151 | + while True: |
| 152 | + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| 153 | + try: |
| 154 | + s.connect((address, port)) |
| 155 | + break |
| 156 | + except: |
| 157 | + time.sleep(1) |
| 158 | + |
| 159 | + handle, config = tempfile.mkstemp(suffix=".conf") |
| 160 | + os.close(handle) |
| 161 | + |
| 162 | + url = "http://%s:%d/?id=1" % (address, port) |
| 163 | + |
| 164 | + content = open(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.conf"))).read().replace("url =", "url = %s" % url) |
| 165 | + open(config, "w+").write(content) |
| 166 | + |
| 167 | + while True: |
| 168 | + lines = content.split("\n") |
| 169 | + |
| 170 | + for i in xrange(20): |
| 171 | + j = random.randint(0, len(lines) - 1) |
| 172 | + if lines[j].strip().endswith('='): |
| 173 | + lines[j] += random.sample(("True", "False", randomStr(), str(randomInt())), 1)[0] |
| 174 | + |
| 175 | + k = random.randint(0, len(lines) - 1) |
| 176 | + if '=' in lines[k]: |
| 177 | + lines[k] += chr(random.randint(0, 255)) |
| 178 | + |
| 179 | + open(config, "w+").write("\n".join(lines)) |
| 180 | + |
| 181 | + 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]) |
| 182 | + output = shellExec(cmd) |
| 183 | + |
| 184 | + if "Traceback" in output: |
| 185 | + dataToStdout("---\n\n$ %s\n" % cmd) |
| 186 | + dataToStdout("%s---\n" % clearColors(output)) |
| 187 | + else: |
| 188 | + handle, config = tempfile.mkstemp(prefix="sqlmapcrash", suffix=".conf") |
| 189 | + os.close(handle) |
| 190 | + open(config, "w+").write("\n".join(lines)) |
| 191 | + |
| 192 | + dataToStdout("\r%d\r" % count) |
| 193 | + |
| 194 | + count += 1 |
| 195 | + |
157 | 196 | def dirtyPatchRandom(): |
158 | 197 | """ |
159 | 198 | Unifying random generated data across different Python versions |
@@ -274,109 +313,3 @@ def _(node): |
274 | 313 | logger.error("smoke test final result: FAILED") |
275 | 314 |
|
276 | 315 | return retVal |
277 | | - |
278 | | -def adjustValueType(tagName, value): |
279 | | - for family in optDict: |
280 | | - for name, type_ in optDict[family].items(): |
281 | | - if type(type_) == tuple: |
282 | | - type_ = type_[0] |
283 | | - if tagName == name: |
284 | | - if type_ == "boolean": |
285 | | - value = (value == "True") |
286 | | - elif type_ == "integer": |
287 | | - value = int(value) |
288 | | - elif type_ == "float": |
289 | | - value = float(value) |
290 | | - break |
291 | | - return value |
292 | | - |
293 | | -def initCase(switches, count): |
294 | | - _failures.failedItems = [] |
295 | | - _failures.failedParseOn = None |
296 | | - _failures.failedTraceBack = None |
297 | | - |
298 | | - paths.SQLMAP_OUTPUT_PATH = tempfile.mkdtemp(prefix="%s%d-" % (MKSTEMP_PREFIX.TESTING, count)) |
299 | | - paths.SQLMAP_DUMP_PATH = os.path.join(paths.SQLMAP_OUTPUT_PATH, "%s", "dump") |
300 | | - paths.SQLMAP_FILES_PATH = os.path.join(paths.SQLMAP_OUTPUT_PATH, "%s", "files") |
301 | | - |
302 | | - logger.debug("using output directory '%s' for this test case" % paths.SQLMAP_OUTPUT_PATH) |
303 | | - |
304 | | - LOGGER_HANDLER.stream = sys.stdout = tempfile.SpooledTemporaryFile(max_size=0, mode="w+b", prefix="sqlmapstdout-") |
305 | | - |
306 | | - cmdLineOptions = cmdLineParser() |
307 | | - |
308 | | - if switches: |
309 | | - for key, value in switches.items(): |
310 | | - if key in cmdLineOptions.__dict__: |
311 | | - cmdLineOptions.__dict__[key] = value |
312 | | - |
313 | | - initOptions(cmdLineOptions, True) |
314 | | - init() |
315 | | - |
316 | | -def cleanCase(): |
317 | | - shutil.rmtree(paths.SQLMAP_OUTPUT_PATH, True) |
318 | | - |
319 | | -def runCase(parse): |
320 | | - retVal = True |
321 | | - handled_exception = None |
322 | | - unhandled_exception = None |
323 | | - result = False |
324 | | - console = "" |
325 | | - |
326 | | - try: |
327 | | - result = start() |
328 | | - except KeyboardInterrupt: |
329 | | - pass |
330 | | - except SqlmapBaseException as ex: |
331 | | - handled_exception = ex |
332 | | - except Exception as ex: |
333 | | - unhandled_exception = ex |
334 | | - finally: |
335 | | - sys.stdout.seek(0) |
336 | | - console = sys.stdout.read() |
337 | | - LOGGER_HANDLER.stream = sys.stdout = sys.__stdout__ |
338 | | - |
339 | | - if unhandled_exception: |
340 | | - _failures.failedTraceBack = "unhandled exception: %s" % str(traceback.format_exc()) |
341 | | - retVal = None |
342 | | - elif handled_exception: |
343 | | - _failures.failedTraceBack = "handled exception: %s" % str(traceback.format_exc()) |
344 | | - retVal = None |
345 | | - elif result is False: # this means no SQL injection has been detected - if None, ignore |
346 | | - retVal = False |
347 | | - |
348 | | - console = getUnicode(console, encoding=sys.stdin.encoding) |
349 | | - |
350 | | - if parse and retVal: |
351 | | - with codecs.open(conf.dumper.getOutputFile(), "rb", UNICODE_ENCODING) as f: |
352 | | - content = f.read() |
353 | | - |
354 | | - for item, parse_from_console_output in parse: |
355 | | - parse_on = console if parse_from_console_output else content |
356 | | - |
357 | | - if item.startswith("r'") and item.endswith("'"): |
358 | | - if not re.search(item[2:-1], parse_on, re.DOTALL): |
359 | | - retVal = None |
360 | | - _failures.failedItems.append(item) |
361 | | - |
362 | | - elif item not in parse_on: |
363 | | - retVal = None |
364 | | - _failures.failedItems.append(item) |
365 | | - |
366 | | - if _failures.failedItems: |
367 | | - _failures.failedParseOn = console |
368 | | - |
369 | | - elif retVal is False: |
370 | | - _failures.failedParseOn = console |
371 | | - |
372 | | - return retVal |
373 | | - |
374 | | -def replaceVars(item, vars_): |
375 | | - retVal = item |
376 | | - |
377 | | - if item and vars_: |
378 | | - for var in re.findall(r"\$\{([^}]+)\}", item): |
379 | | - if var in vars_: |
380 | | - retVal = retVal.replace("${%s}" % var, vars_[var]) |
381 | | - |
382 | | - return retVal |
0 commit comments