예제 #1
0
 def activate(self):
     logger.debug('Activating %s' % self.__class__.__name__)
     self.service = ThreatConnect(settings.THREATCONNECT_ACCESS_ID,
                                  settings.THREATCONNECT_SECRET_KEY,
                                  settings.THREATCONNECT_DEFAULT_ORG,
                                  settings.THREATCONNECT_BASE_URL)
     self.service.set_api_result_limit(100)
예제 #2
0
def get_client():
    params = demisto.params()
    access = params['accessId']
    secret = params['secretKey']
    default_org = params.get('defaultOrg')
    url = params['baseUrl']
    proxy_ip = params['proxyIp']
    proxy_port = params['proxyPort']

    tc = ThreatConnect(access, secret, default_org, url)
    if proxy_ip and proxy_port and len(proxy_ip) > 0 and len(proxy_port) > 0:
        tc.set_proxies(proxy_ip, int(proxy_port))

    return tc
예제 #3
0
def test_ip_get_indicators_multiple_owners(mocker):
    mocker.patch('ThreatConnect_v2.get_xindapi',
                 side_effect=[GET_XINDAPI_OWNER1, GET_XINDAPI_OWNER2])
    mocker.patch('ThreatConnect_v2.get_client', return_value=ThreatConnect())
    indicators = get_indicators('127.0.0.1', 'Address',
                                'Demisto Inc.,PhishTank', -1, -1)
    assert indicators == EXPECTED_INDOCATORS_OUTPUT
def test_associate_indicator_request(indicator_type, indicator, expected_url, mocker):
    mocker.patch.object(Response, 'json', return_value={})
    api_request = mocker.patch.object(ThreatConnect, 'api_request', return_value=Response())
    mocker.patch('ThreatConnect_v2.get_client', return_value=ThreatConnect())
    associate_indicator_request(indicator_type, indicator, 'test', '0')
    url = f'/v2/indicators/{expected_url}/groups/test/0'
    assert api_request.call_args[0][0].request_uri == url
예제 #5
0
 def activate(self):
     logger.debug('Activating %s' % self.__class__.__name__)
     self.service = ThreatConnect(
         settings.THREATCONNECT_ACCESS_ID,
         settings.THREATCONNECT_SECRET_KEY,
         settings.THREATCONNECT_DEFAULT_ORG,
         settings.THREATCONNECT_BASE_URL)
     self.service.set_api_result_limit(100)
# retrieve configuration file
config = ConfigParser.RawConfigParser()
config.read(config_file)

try:
    api_access_id = config.get('threatconnect', 'api_access_id')
    api_secret_key = config.get('threatconnect', 'api_secret_key')
    api_default_org = config.get('threatconnect', 'api_default_org')
    api_base_url = config.get('threatconnect', 'api_base_url')
    api_result_limit = int(config.get('threatconnect', 'api_result_limit'))
except ConfigParser.NoOptionError:
    print('Could not retrieve configuration file.')
    sys.exit(1)

tc = ThreatConnect(api_access_id, api_secret_key, api_default_org, api_base_url)
tc.set_api_result_limit(api_result_limit)
tc.report_enable()

#
# CHANGE FOR YOUR TESTING ENVIRONMENT
# - These victims must be created before running this script
#
owner = 'Example Community'  # org or community
lu_id = 1  # adversary id for loop update
mu_id = 4  # adversary id for manual update
# dl_id = 999999  # adversary id to delete
email_id = 17  # email resource id to associate with adversary
email_address = '*****@*****.**'  # email address to associate to adversary
rn = randint(1, 1000)  # random number generator for testing
# retrieve configuration file
config = ConfigParser.RawConfigParser()
config.read(config_file)

try:
    api_access_id = config.get('threatconnect', 'api_access_id')
    api_secret_key = config.get('threatconnect', 'api_secret_key')
    api_default_org = config.get('threatconnect', 'api_default_org')
    api_base_url = config.get('threatconnect', 'api_base_url')
    api_result_limit = int(config.get('threatconnect', 'api_result_limit'))
except ConfigParser.NoOptionError:
    print('Could not retrieve configuration file.')
    sys.exit(1)

tc = ThreatConnect(api_access_id, api_secret_key, api_default_org,
                   api_base_url)
tc.set_api_result_limit(api_result_limit)
tc.report_enable()

#
# CHANGE FOR YOUR TESTING ENVIRONMENT
# - These adversaries must be created before running this script
#
lu_id = 22  # task id for loop update
mu_id = 23  # task id for manual update
# dl_id = 999999  # adversary id to delete
email_id = 27  # email resource id to associate with adversary
victim_id = 2  # victim resource id to associate with adversary
ip_address = '10.121.82.247'  # ip address to associate to adversary
rn = randint(1, 1000)  # random number generator for testing
예제 #8
0
import sys

from threatconnect import ThreatConnect

config = ConfigParser.RawConfigParser()
config.read('./tc.conf')

try:
    api_access_id = config.get('threatconnect', 'api_access_id')
    api_secret_key = config.get('threatconnect', 'api_secret_key')
    api_default_org = config.get('threatconnect', 'api_default_org')
    api_base_url = config.get('threatconnect', 'api_base_url')
except ConfigParser.NoOptionError:
    print('Could not read configuration file.')
    sys.exit(1)
tc = ThreatConnect(api_access_id, api_secret_key, api_default_org,
                   api_base_url)
owners = tc.owners()

try:
    # retrieve the Owners
    owners.retrieve()
except RuntimeError as e:
    print('Error: {0}'.format(e))
    sys.exit(1)


def getOwnerNames():
    namelist = []
    for owner in owners:
        namelist.append(owner.name)
    return namelist
    def __init__(self,
                 access_id="",
                 secret_key="",
                 default_org="",
                 base_url="",
                 out_file="tc.json",
                 sources="",
                 ioc_types="",
                 custom_ioc_key="",
                 feed_url="",
                 cb_server_token="",
                 cb_server_url="https://127.0.0.1",
                 cb_server_ssl_verify=False,
                 ioc_min=None,
                 niceness=None,
                 debug=False,
                 log_file=None,
                 max_iocs=5000):

        logger.info("ThreatConnect Base URL: {0}".format(base_url))

        self.tcapi = ThreatConnect(api_aid=access_id,
                                   api_sec=secret_key,
                                   api_url=base_url,
                                   api_org=default_org)

        self.sources = sources

        self.ioc_min = ioc_min

        self.ioc_types = ioc_types

        logger.info("Configured IOC Types are : {0}".format(self.ioc_types))
        logger.info("Configured IOC Min is  : {0}".format(self.ioc_min))

        self.custom_ioc_key = custom_ioc_key

        self.max_iocs = max_iocs

        if self.sources[0] == "*":
            owners = self.tcapi.owners()
            try:
                # retrieve the Owners
                owners.retrieve()
            except RuntimeError as e:
                logger.error(traceback.format_exc())
                sys.exit(1)
            # iterate through the Owners
            self.sources = [owner.name for owner in owners]

        logger.info("Sources = {0}".format(self.sources))

        self.niceness = niceness
        if self.niceness is not None:
            os.nice(self.niceness)

        self.debug = debug
        if self.debug:
            logger.setLevel(logging.DEBUG)

        self.log_file = log_file

        self.out_file = out_file

        self.feed = None

        self.cb = CbResponseAPI(url=cb_server_url,
                                token=cb_server_token,
                                ssl_verify=cb_server_ssl_verify)

        self.feed_url = feed_url
class CbThreatConnectConnector(object):
    def __init__(self,
                 access_id="",
                 secret_key="",
                 default_org="",
                 base_url="",
                 out_file="tc.json",
                 sources="",
                 ioc_types="",
                 custom_ioc_key="",
                 feed_url="",
                 cb_server_token="",
                 cb_server_url="https://127.0.0.1",
                 cb_server_ssl_verify=False,
                 ioc_min=None,
                 niceness=None,
                 debug=False,
                 log_file=None,
                 max_iocs=5000):

        logger.info("ThreatConnect Base URL: {0}".format(base_url))

        self.tcapi = ThreatConnect(api_aid=access_id,
                                   api_sec=secret_key,
                                   api_url=base_url,
                                   api_org=default_org)

        self.sources = sources

        self.ioc_min = ioc_min

        self.ioc_types = ioc_types

        logger.info("Configured IOC Types are : {0}".format(self.ioc_types))
        logger.info("Configured IOC Min is  : {0}".format(self.ioc_min))

        self.custom_ioc_key = custom_ioc_key

        self.max_iocs = max_iocs

        if self.sources[0] == "*":
            owners = self.tcapi.owners()
            try:
                # retrieve the Owners
                owners.retrieve()
            except RuntimeError as e:
                logger.error(traceback.format_exc())
                sys.exit(1)
            # iterate through the Owners
            self.sources = [owner.name for owner in owners]

        logger.info("Sources = {0}".format(self.sources))

        self.niceness = niceness
        if self.niceness is not None:
            os.nice(self.niceness)

        self.debug = debug
        if self.debug:
            logger.setLevel(logging.DEBUG)

        self.log_file = log_file

        self.out_file = out_file

        self.feed = None

        self.cb = CbResponseAPI(url=cb_server_url,
                                token=cb_server_token,
                                ssl_verify=cb_server_ssl_verify)

        self.feed_url = feed_url

    def stop(self):
        self.stopEvent.set()

    def getDebugMode(self):
        return self._debug

    def setDebugMode(self, debugOn):
        self._debug = debugOn
        if self._debug == True:
            logger.setLevel(logging.DEBUG)
        else:
            logger.setLevel(logging.INFO)

    debug = property(getDebugMode, setDebugMode)

    def _PollThreatConnect(self):
        self.generate_feed_from_threatconnect()
        self.createFeed()
        last = None
        while (True):
            if self.stopEvent.isSet():
                logger.info(
                    "Threatconnect Connector was signalled to stop...stopping")
                return
            else:
                #poll threat connect if the time delta has passed since the last time we did
                now = datetime.now()
                delta = now - last if last is not None else self.interval
                last = now
                if delta >= self.interval:
                    self.generate_feed_from_threatconnect()
                else:
                    time.sleep(self.interval.seconds + 1)
                    logger.debug("Done sleeping...")

    def RunForever(self):
        logger.info("ThreatConnect agent starting...")
        threading.Thread(target=self._PollThreatConnect).start()

    def createFeed(self):
        if self.feed is not None:
            self.feed.upload(self.cb, self.feed_url)

    def generate_feed_from_threatconnect(self):
        first = True
        reports = []
        feedinfo = {
            'name': 'threatconnect',
            'display_name': "ThreatConnect",
            'provider_url': "http://www.threatconnect.com",
            'summary':
            "Sends threat intelligence from Threatconnect platform to Carbon Black Response",
            'tech_data':
            "There are no requirements to share any data with Carbon Black to use this feed.",
            'icon': 'threatconnect-logo.png',
            'category': "Connectors",
        }

        feedinfo = CbFeedInfo(**feedinfo)
        self.feed = CbFeed(feedinfo, reports)
        created_feed = self.feed.dump(validate=False, indent=0)
        with open(self.out_file, 'w') as fp:
            fp.write(created_feed)

            fp.seek(0)

            offset = len(created_feed) - 1

            # create an Indicators object
            for source in self.sources:
                for t in self.ioc_types:
                    indicators = self.tcapi.indicators()
                    filter1 = indicators.add_filter()
                    # filter1.add_owner(source)
                    filter1.add_pf_type(t, FilterOperator.EQ)
                    if self.ioc_min is not None:
                        filter1.add_pf_rating(self.ioc_min, FilterOperator.GE)
                    try:
                        # retrieve Indicators
                        indicators.retrieve()
                    except RuntimeError as e:
                        print('Error: {0}'.format(e))

                    logger.info("Number of indicators:{0}".format(
                        len(indicators)))

                    for index, indicator in enumerate(indicators):

                        if index > self.max_iocs:
                            logger.info("Max number of IOCs reached")
                            break
                        # print (indicator.type)
                        score = indicator.rating * 20 if indicator.rating is not None else 0
                        # int(row.get('rating', 0)) * 20
                        # Many entries are missing a description so I placed this here to default them
                        # to the IOC value in the absence of a description.
                        title = indicator.description if indicator.description is not None else "{0}-{1}".format(
                            source,
                            indicator.id)  # row.get('description', None)
                        # if not title:
                        #    title = row.get('summary')
                        fields = {
                            'iocs': {},
                            'id':
                            str(indicator.id),
                            'link':
                            indicator.weblink,
                            'title':
                            title,
                            'score':
                            int(score),
                            'timestamp':
                            int(
                                datetime.strptime(
                                    indicator.date_added,
                                    "%Y-%m-%dT%H:%M:%SZ").timestamp()),
                        }
                        # The next few lines are designed to insert the Cb supported IOCs into the record.
                        logger.debug("Indacator is {0}".format(indicator))
                        if indicator.type == "File":
                            fields['iocs'] = {
                                k: [indicator.indicator[k]]
                                for k in indicator.indicator
                                if indicator.indicator[k] is not None
                            }
                        elif indicator.type == "Address":
                            fields['iocs']['ipv4'] = [indicator.indicator]
                        elif indicator.type == "Host":
                            fields['iocs']['dns'] = [indicator.indicator]
                        else:
                            squery = urllib.parse.urlencode({
                                "cb.urlver":
                                "1",
                                "q":
                                indicator.indicator[self.custom_ioc_key]
                            })
                            fields['iocs']['query'] = [{
                                'index_type': 'modules',
                                'search_query': squery
                            }]

                        report = CbReport(**fields)
                        try:
                            report.dump(validate=True)
                        except:
                            logger.info("This query is not valid: {0}".format(
                                indicator.indicator[self.custom_ioc_key]))
                            continue
                        # APPEND EACH NEW REPORT ONTO THE LIST IN THE JSON FEED
                        # THIS METHOD IS VERY LONG LIVED
                        # THIS METHOD CALL WILL LAST FOR
                        #  HOURS -> DAYS IN LARGE ORGS
                        reports.append(report)
                        self.feed = CbFeed(feedinfo, reports)
                    fp.write(self.feed.dump(validate=False, indent=0))
예제 #11
0
import ConfigParser
from threatconnect import ThreatConnect

config = ConfigParser.RawConfigParser()
config.read(config_file)

try:
    api_access_id = config.get('threatconnect', 'api_access_id')
    api_secret_key = config.get('threatconnect', 'api_secret_key')
    api_default_org = config.get('threatconnect', 'api_default_org')
    api_base_url = config.get('threatconnect', 'api_base_url')
except ConfigParser.NoOptionError:
    print('Could not read configuration file.')
    sys.exit(1)

tc = ThreatConnect(api_access_id, api_secret_key, api_default_org, api_base_url)

owners = tc.owners()

try:
    owners.retrieve()
except RunTimeErrors as e:
    print('Error: {0}'.format(e))
    sys.exit(1)

for owner in owners:
    print(owner.id)
    print(owner.name)
    print(owner.type)
예제 #12
0
class ThreatConnectPlugin(Plugin):
    @property
    def enabled(self):
        return settings.THREATCONNECT_ACCESS_ID is not None and \
            settings.THREATCONNECT_SECRET_KEY is not None

    def activate(self):
        logger.debug('Activating %s' % self.__class__.__name__)
        self.service = ThreatConnect(settings.THREATCONNECT_ACCESS_ID,
                                     settings.THREATCONNECT_SECRET_KEY,
                                     settings.THREATCONNECT_DEFAULT_ORG,
                                     settings.THREATCONNECT_BASE_URL)
        self.service.set_api_result_limit(100)

    def retrieve_indicator(self, indicator, indicator_type=None):
        indicators = self.service.indicators()
        if indicator_type:
            f = indicators.add_filter(indicator_type)
        else:
            f = indicators.add_filter()
        f.add_owner(['Common Community'])
        f.add_indicator(indicator)
        results = sorted(indicators.retrieve(), key=lambda x: x.rating)
        return results[-1] if results else None

    def threshold_met(self, report):
        return hasattr(report, 'rating') and report.rating >= 1 and \
            hasattr(report, 'confidence') and report.confidence >= 50

    def react(self):
        if not any(self.reports.values()):
            return
        rating = max([0] + [
            r.rating for r in self.reports.values()
            if r and hasattr(r, 'rating') and r.rating
        ])
        return self.reaction(rating)

    def reaction(self, score):
        if score == 0:
            return 'sunny'
        elif 0 <= score < 0.5:
            return 'mostly_sunny'
        elif 0.5 <= score < 1:
            return 'partly_sunny'
        elif 1 <= score < 2:
            return 'barely_sunny'
        elif 2 <= score < 2.5:
            return 'cloud'
        elif 2.5 <= score < 3:
            return 'rain_cloud'
        elif 3 <= score < 3.5:
            return 'thunder_cloud_and_rain'
        elif 3.5 <= score < 4:
            return 'lightning'
        elif score >= 4:
            return 'tornado'

    def risk_level(self, score):
        try:
            score = float(score)
        except TypeError:
            return 'UNKNOWN'

        if score == 0:
            return 'UNKNOWN'
        elif 0 < score < 1:
            return 'VERY LOW'
        elif 1 <= score < 2:
            return 'LOW'
        elif 2 <= score < 3:
            return 'MODERATE'
        elif 3 <= score < 4:
            return 'HIGH'
        elif score >= 4:
            return 'VERY HIGH'
예제 #13
0
class ThreatConnectPlugin(Plugin):
    @property
    def enabled(self):
        return settings.THREATCONNECT_ACCESS_ID is not None and \
            settings.THREATCONNECT_SECRET_KEY is not None

    def activate(self):
        logger.debug('Activating %s' % self.__class__.__name__)
        self.service = ThreatConnect(
            settings.THREATCONNECT_ACCESS_ID,
            settings.THREATCONNECT_SECRET_KEY,
            settings.THREATCONNECT_DEFAULT_ORG,
            settings.THREATCONNECT_BASE_URL)
        self.service.set_api_result_limit(100)

    def retrieve_indicator(self, indicator, indicator_type=None):
        indicators = self.service.indicators()
        if indicator_type:
            f = indicators.add_filter(indicator_type)
        else:
            f = indicators.add_filter()
        f.add_owner(['Common Community'])
        f.add_indicator(indicator)
        results = sorted(indicators.retrieve(), key=lambda x: x.rating)
        return results[-1] if results else None

    def threshold_met(self, report):
        return hasattr(report, 'rating') and report.rating >= 1 and \
            hasattr(report, 'confidence') and report.confidence >= 50

    def react(self):
        if not any(self.reports.values()):
            return
        rating = max([0] + [r.rating for r in self.reports.values()
                     if r and hasattr(r, 'rating') and r.rating])
        return self.reaction(rating)

    def reaction(self, score):
        if score == 0:
            return 'sunny'
        elif 0 <= score < 0.5:
            return 'mostly_sunny'
        elif 0.5 <= score < 1:
            return 'partly_sunny'
        elif 1 <= score < 2:
            return 'barely_sunny'
        elif 2 <= score < 2.5:
            return 'cloud'
        elif 2.5 <= score < 3:
            return 'rain_cloud'
        elif 3 <= score < 3.5:
            return 'thunder_cloud_and_rain'
        elif 3.5 <= score < 4:
            return 'lightning'
        elif score >= 4:
            return 'tornado'

    def risk_level(self, score):
        try:
            score = float(score)
        except TypeError:
            return 'UNKNOWN'

        if score == 0:
            return 'UNKNOWN'
        elif 0 < score < 1:
            return 'VERY LOW'
        elif 1 <= score < 2:
            return 'LOW'
        elif 2 <= score < 3:
            return 'MODERATE'
        elif 3 <= score < 4:
            return 'HIGH'
        elif score >= 4:
            return 'VERY HIGH'
예제 #14
0
config_file = "tc.conf"
config = ConfigParser.RawConfigParser()
config.read(config_file)

try:
    api_access_id = config.get('threatconnect', 'api_access_id')
    api_secret_key = config.get('threatconnect', 'api_secret_key')
    api_default_org = config.get('threatconnect', 'api_default_org')
    api_base_url = config.get('threatconnect', 'api_base_url')
    api_result_limit = int(config.get('threatconnect', 'api_result_limit'))
    api_export_days = int(config.get('threatconnect', 'api_export_days'))
except ConfigParser.NoOptionError:
    print('Could not retrieve configuration file.')
    sys.exit(1)

tc = ThreatConnect(api_access_id, api_secret_key, api_default_org,
                   api_base_url)
tc.set_api_result_limit(api_result_limit)

# initializing stuff
csv = tocsv.csv()

# directory configurations // idea: set it in config file
# if you are running this in the linux server with ML, change r"\csv" to r"\mhscript"
f_name_directory = os.getcwd() + r"\csv"
n_files = len(os.listdir(f_name_directory))
if n_files > 0:
    print("CSV file already exists in {}".format(f_name_directory))
    print("Deleting csv file")
    if not bool((input("Press ENTER to continue...\n"))):
        os.remove(path=f_name_directory + r"\0.csv")
    else:
예제 #15
0
# https://docs.threatconnect.com/en/latest/python/quick_start.html#standard-script-heading
config = ConfigParser.RawConfigParser()
config.read('./tc.conf')

try:
    api_access_id = config.get('threatconnect', 'api_access_id')
    api_secret_key = config.get('threatconnect', 'api_secret_key')
    api_default_org = config.get('threatconnect', 'api_default_org')
    api_base_url = config.get('threatconnect', 'api_base_url')

    api_result_limit = config.get('threatconnect', 'api_result_limit')
except ConfigParser.NoOptionError:
    print('Could not read configuration file.')
    sys.exit(1)

tc = ThreatConnect(api_access_id, api_secret_key, api_default_org,
                   api_base_url)
tc.set_api_result_limit(1000)

# instantiate Owners object
#owners = tc.owners()
owners = ['ThreatConnect Intelligence', 'Common Community']

groups = tc.groups()

filter1 = groups.add_filter()
# only retrieve Groups from the given owner(s)
filter1.add_owner(owners)

try:
    groups.retrieve()
except RuntimeError as e: