BitcoinAbuse Deprecated
Deprecated. No available replacement.
Data Enrichment & Threat Intelligence · BitcoinAbuse Feed (Deprecated) · Feed
Details
| ID | BitcoinAbuse |
|---|---|
| Provider | BitcoinAbuse |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 5.5.0 |
| Docker Image | demisto/python3:3.10.12.63474 |
| Supported Modules | Agentix XSIAM |
README
BitcoinAbuse.com is a public database of bitcoin addresses used by hackers and criminals.
Supported Cortex XSOAR versions: 5.5.0 and later.
Get Your API Key
In order to use Bitcoin Abuse service, you need to get your API key.
The API key is free and can be achieved by doing the following:
- Navigate to https://www.bitcoinabuse.com and click on “Register” on top right corner of your screen.
- Fill in your details (Name, Email, Password, etc…)
- After your account have been set, go to Settings, and click on “API” section.
- Give your API token a name, and click on “Create”, a screen containing your generated API key
will appear.
Configure BitcoinAbuse in Cortex
| Parameter | Description | Required |
|---|---|---|
| feed | Fetch indicators | False |
| api_key | API Key | True |
| insecure | Trust any certificate (not secure) | False |
| proxy | Use system proxy settings | False |
| initial_fetch_interval | First Fetch Time | True |
| feedReputation | Indicator Reputation | False |
| feedReliability | Source Reliability | True |
| feedExpirationPolicy | False | |
| tlp_color | Traffic Light Protocol Color | False |
| feedFetchInterval | Feed Fetch Interval | False |
| feedExpirationInterval | False | |
| feedBypassExclusionList | Bypass exclusion list | False |
| feedTags | Tags | False |
Fetching indicators
Initial Fetch
When configuring an integration instance, you will be required to enter the first fetch parameter which will set the timeframe to pull Indicators in the first fetch, Two options are available:
- 30 Days - Indicators recorded in the last 30 days (updates every Sunday between 2am-3am UTC.)
- Forever - All recorded indicators (updates every 15th of the month between 2am-3am UTC.)
Note:
- Whenever Forever is selected, in order to bring as much data as possible in the first fetch, we merge the Forever CSV together the 30 Days CSV file to avoid missing as much data as possible.
- Restrictions will be that any data reported between Sunday (after 30 Days file update) to the day of the first fetch
will not be fetched
Each fetch after the initial fetch
Each fetch after the initial fetch will return indicators reported on the previous day (updates once a day between 2am-3am UTC). Therefore, fetching more than once a day will not have any effect.
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
bitcoinabuse-report-address
Reports an abuser to Bitcoin Abuse service. ‘abuse_type_other’ field is required when ‘abuse_type’ is other
Base Command
bitcoinabuse-report-address
Input
| Argument Name | Description | Required |
|---|---|---|
| address | Address of the abuser. | Required |
| abuser | Information about the abuser. | Required |
| description | Description of the abuse. | Optional |
| abuse_type | Type of abuse. The “abuse_type_other” field is required when the value of the “abuse_type” field is “other”. Possible values are “ransomware”, “darknet market”, “bitcoin tumber”, “blackmail scam”, “sextortion”, and “other”. Possible values are: ransomware, darknet market, bitcoin tumbler, blackmail scam, sextortion, other. | Required |
| abuse_type_other | Description of the abuse type. The “abuse_type_other” field is required when the value of the “abuse_type” field is “other”. | Optional |
Context Output
There is no context output for this command.
Command Example
!bitcoinabuse-report-address address=abcde12345 abuser=abuser@abuse.net abuse_type="bitcoin tumbler" description="this is a description of the abuse"
Human Readable Output
Bitcoin address abcde12345 by abuse bitcoin user abuser@abuse.net was reported to BitcoinAbuse API
bitcoinabuse-get-indicators
Gets indicators from the feed.
Base Command
bitcoinabuse-get-indicators
Input
| Argument Name | Description | Required |
|---|---|---|
| limit | The maximum number of results to return. Default is 50. | Optional |
Context Output
There is no context output for this command.
Command Example
!bitcoinabuse-get-indicators limit=1
Context Example
{}
Human Readable Output
Indicators
value type fields bitcoin:1MfhfDZdv2QXmBBZMom5ZnZzp8VVrJUENw Cryptocurrency Address Value: bitcoin:1MfhfDZdv2QXmBBZMom5ZnZzp8VVrJUENw
rawaddress: 1MfhfDZdv2QXmBBZMom5ZnZzp8VVrJUENw
countryname: Australia
creationdate: 2021-01-17T00:30:36.000000Z
description: I know **** is one of your password on day of hack..
Lets get directly to the point.
Not one person has paid me to check about you.
You do not know me and you’re probably thinking why you are getting this email?
in fact, i actually placed a malware on the adult vids (adult porn) website and you know what, you visited this site to experience fun (you know what i mean).
When you were viewing videos, your browser started out operating as a RDP having a key logger which provided me with accessibility to your display and web cam.
immediately after that, my malware obtained every one of your contacts from your Messenger, FB, as well as email account.
after that i created a double-screen video. 1st part shows the video you were viewing (you have a nice taste omg), and 2nd part displays the recording of your cam, and its you.
Best solution would be to pay me $2763.
We are going to refer to it as a donation. in this situation, i most certainly will without delay remove your video.
Bitcoin address: 1MfhfDZdv2QXmBBZMom5ZnZzp8VVrJUENw
[case SeNSiTiVe, copy & paste it]
You could go on your life like this never happened and you will not ever hear back again from me.
You’ll make the payment via Bitcoin (if you do not know this, search ‘how to buy bitcoin’ in Google).
if you are planning on going to the law, surely, this e-mail can not be traced back to me, because it’s hacked too.
I have taken care of my actions. i am not looking to ask you for a lot, i simply want to be paid.
if i do not receive the bitcoin;, i definitely will send out your video recording to all of your contacts including friends and family, co-workers, and so on.
Nevertheless, if i do get paid, i will destroy the recording immediately.
If you need proof, reply with Yeah then i will send out your video recording to your 8 friends.
it’s a nonnegotiable offer and thus please don’t waste mine time & yours by replying to this message.
abusetype: ransomware
tags:
reportscount: 1
cryptocurrencyaddresstype: bitcoin
Configuration parameters
feed— Fetch indicatorsapi_key— API Keycredentials_api_key—insecure— Trust any certificate (not secure)proxy— Use system proxy settingsinitial_fetch_interval— First Fetch Time (required)feedReputation— Indicator ReputationfeedReliability— Source Reliability (required)feedExpirationPolicy—tlp_color— Traffic Light Protocol ColorfeedFetchInterval— Feed Fetch IntervalfeedExpirationInterval—feedBypassExclusionList— Bypass exclusion listfeedTags— Tags
Commands (2)
-
bitcoinabuse-get-indicatorsDeprecatedGets indicators from the feed.
-
bitcoinabuse-report-addressDeprecatedReports an abuser to Bitcoin Abuse service. 'abuse_type_other' field is required when 'abuse_type' is other
import demistomock as demisto # noqa: F401 from CSVFeedApiModule import * from CommonServerPython import * # noqa: F401 # disable insecure warnings urllib3.disable_warnings() ''' CONSTANTS ''' SERVER_URL = 'https://www.bitcoinabuse.com/api/' ABUSE_TYPE_ID_TO_NAME: Dict[str, str] = { '1': 'ransomware', '2': 'darknet market', '3': 'bitcoin tumbler', '4': 'blackmail scam', '5': 'sextortio', '99': 'other' } READER_CONFIG = { 'fieldnames': ['id', 'address', 'abuse_type_id', 'abuse_type_other', 'abuser', 'description', 'from_country', 'from_country_code', 'created_at'], 'skip_first_line': True, 'indicator_type': 'Cryptocurrency Address', 'mapping': { 'Value': ('address', None, 'bitcoin:{}'), 'rawaddress': 'address', 'countryname': 'from_country', 'creationdate': 'created_at', 'description': 'description', 'abusetype': ('abuse_type_id', lambda abuse_type_id: ABUSE_TYPE_ID_TO_NAME.get(abuse_type_id)) } } ABUSE_TYPE_NAME_TO_ID = { 'ransomware': 1, 'darknet market': 2, 'bitcoin tumbler': 3, 'blackmail scam': 4, 'sextortio': 5, 'other': 99 } class BitcoinAbuseClient(BaseClient): FIRST_FETCH_INTERVAL_TO_URL_SUFFIX: Dict[str, str] = { 'Forever': 'forever', '30 Days': '30d' } def __init__(self, base_url, insecure, proxy, api_key, initial_fetch_interval, reader_config, feed_tags, tlp_color, have_fetched_first_time): super().__init__(base_url=base_url, verify=not insecure, proxy=proxy) self.server_url = base_url self.api_key = api_key self.initial_fetch_interval = initial_fetch_interval self.reader_config = reader_config self.have_fetched_first_time = have_fetched_first_time self.insecure = insecure self.feed_tags = feed_tags self.tlp_color = tlp_color def report_address(self, address: str, abuse_type_id: int, abuse_type_other: Optional[str], abuser: str, description: str) -> Dict: """ Sends a post request to report an abuse to BitcoinAbuse servers. Args: address (str): The address of the abuser. abuse_type_id (int): An id which indicates which type of abuse was made. abuse_type_other (Optional[str]): In case abuse_type_id was other, holds information describing the abuse type. abuser (str): Information about the abuser (email, name, ...). description (str): Description of the abuse (may include email sent, etc). Returns: Returns if post request was successful. """ return self._http_request( method='POST', url_suffix='reports/create', params=assign_params( api_token=self.api_key, address=address, abuse_type_id=abuse_type_id, abuser=abuser, description=description, abuse_type_other=abuse_type_other ) ) def get_indicators(self) -> Tuple[List[Dict], bool]: """ Builds CSV module client and performs the API call to Bitcoin Abuse service. If the call was successful, returns list of indicators. Args: Returns: - Throws exception if an invalid api key was given or error occurred during the call to Bitcoin Abuse service. - Returns indicators list if the call to Bitcoin Abuse service was successful. """ bitcoin_address_count_dict: Dict[str, int] = dict() params = self.build_params_for_csv_module() csv_module_client = Client(**params) indicators, no_update = fetch_indicators_command( client=csv_module_client, default_indicator_type='Cryptocurrency Address', auto_detect=False, limit=0 ) self.assure_valid_response(indicators) indicators_without_duplicates = [] # in every fetch apart from first fetch, we are only fetching one csv file, so we know there aren't any # duplicates if self.have_fetched_first_time: for indicator in indicators: update_indicator_occurrences(indicator, bitcoin_address_count_dict) indicators_without_duplicates = indicators # in first fetch according to configurations, we might fetch more than one csv file, so we need to remove # duplicates else: indicators_ids = set() for indicator in indicators: try: indicator_id = int(indicator['rawJSON']['id']) if indicator_id not in indicators_ids: update_indicator_occurrences(indicator, bitcoin_address_count_dict) indicators_without_duplicates.append(indicator) indicators_ids.add(indicator_id) except ValueError: demisto.debug(f'The following indicator was found invalid and was skipped: {indicator}') for indicator in indicators_without_duplicates: indicator_count = bitcoin_address_count_dict.get(indicator['value']) indicator['fields']['reportscount'] = indicator_count indicator['fields']['cryptocurrencyaddresstype'] = 'bitcoin' return indicators_without_duplicates, no_update def build_fetch_indicators_url_suffixes(self) -> Set[str]: """ Builds the URL suffix fo the fetch. Default is 'download/1d' unless this is a first fetch which will be determined by the user parameter - initial_fetch_interval. - If initial_fetch_interval is 'forever' - then suffixes will include 30d and forever, in order to extract the most updated data by the Bitcoin Abuse service, as 'forever' csv file only updates on 15 of each month (see Complete Download in https://www.bitcoinabuse.com/api-docs). - If initial_fetch_interval is '30d' - suffixes will only include '30d' suffix. Args: Returns: - Set of the url suffixes to be used in the fetch process. """ feed_endpoint_suffix = 'download/' first_feed_interval_url_suffix = self.FIRST_FETCH_INTERVAL_TO_URL_SUFFIX.get( self.initial_fetch_interval, '30d') if self.have_fetched_first_time: return {f'{feed_endpoint_suffix}1d'} else: return {feed_endpoint_suffix + first_feed_interval_url_suffix, feed_endpoint_suffix + '30d'} def build_params_for_csv_module(self): """ Builds needed params for CSV Module client in order to fetch indicators from Bitcoin Abuse service. Args: Returns: - Params for building the CSVFeedApiModule client. """ params: Dict[str, Any] = dict() urls_suffixes = self.build_fetch_indicators_url_suffixes() urls = [f'{self.server_url}{url_suffix}?api_token={self.api_key}' for url_suffix in urls_suffixes] feed_url_to_config = {url: self.reader_config for url in urls} params['url'] = urls params['feed_url_to_config'] = feed_url_to_config params['delimiter'] = ',' params['encoding'] = 'utf-8' params['insecure'] = self.insecure params['feedTags'] = self.feed_tags params['tlp_color'] = self.tlp_color return params @staticmethod def assure_valid_response(indicators: List[Dict]) -> None: """ Receives the indicators fetched from Bitcoin Abuse service, and checks if the response received is valid. When an incorrect api key is inserted, Bitcoin Abuse returns response of their login page. This function checks if the api key given is incorrect by checking if the received response was the login page. Throws DemistoException to inform the user of incorrect api key. Args: indicators (List[Dict]): The array of indicators fetched. Returns: - Throws DemistoException in case an incorrect api key was given. """ if indicators and '<html lang="en">' == indicators[0].get('value'): raise DemistoException('api token inserted is not valid') ''' HELPER FUNCTIONS ''' def update_indicator_occurrences(indicator_obj: Dict, bitcoin_address_count_dict: Dict[str, int]) -> None: """ Receives an indicator object 'indicator_obj' and a dict 'bitcoin_address_count_dict' which counts occurrences of bitcoin addresses. Updates the occurrences in 'bitcoin_address_count_dict' according to 'indicator_obj' address. Args: indicator_obj (Dict): The indicator. bitcoin_address_count_dict(Dict[str, int]): Bitcoin addresses to occurrences dict. Returns: """ indicator_name = indicator_obj['value'] updated_count = bitcoin_address_count_dict.get(indicator_name, 0) + 1 bitcoin_address_count_dict[indicator_name] = updated_count ''' COMMAND FUNCTIONS ''' def bitcoin_abuse_report_address_command(bitcoin_client: BitcoinAbuseClient, args: Dict) -> CommandResults: """ Reports a bitcoin abuse to Bitcoin Abuse service. Args: bitcoin_client (BitcoinAbuseClient): Client object to perform request. args (Dict): Demisto args for report address command. Returns: str: 'bitcoin address (address reported) by abuser (abuser reported) was reported to BitcoinAbuse API' if http request was successful'. """ abuse_type_id = ABUSE_TYPE_NAME_TO_ID.get(args.get('abuse_type', '')) abuse_type_other = args.get('abuse_type_other') address = args.get('address', '') abuser = args.get('abuser', '') description = args.get('description', '') if abuse_type_id is None: raise DemistoException('Bitcoin Abuse: invalid type of abuse, please insert a correct abuse type') if abuse_type_id == ABUSE_TYPE_NAME_TO_ID['other'] and abuse_type_other is None: raise DemistoException('Bitcoin Abuse: abuse_type_other is mandatory when abuse type is other') http_response = bitcoin_client.report_address(address=address, abuse_type_id=abuse_type_id, abuse_type_other=abuse_type_other, abuser=abuser, description=description) if argToBoolean(http_response.get('success', False)): return CommandResults( readable_output=f'Bitcoin address {address} by abuse bitcoin user {abuser}' f' was reported to BitcoinAbuse service' ) else: failure_message = http_response.get('response', 'Unknown failure reason') raise DemistoException(f'bitcoin report address did not succeed: {failure_message}') def test_module_command(bitcoin_client: BitcoinAbuseClient): """ Performs a fetch indicators flow to validate the configuration params. Args: bitcoin_client (BitcoinAbuseClient): Client object. Returns: 'ok' if the call to Bitcoin Abuse service was successful and command is test_module. """ bitcoin_client.get_indicators() return 'ok' def bitcoin_abuse_fetch_indicators_command(bitcoin_client: BitcoinAbuseClient) -> None: """ Wrapper for fetching indicators from Bitcoin Abuse service. Args: bitcoin_client (BitcoinAbuseClient): Client object. Returns: """ indicators, no_update = bitcoin_client.get_indicators() if is_demisto_version_ge('6.5.0'): for b in batch(indicators, batch_size=2000): demisto.createIndicators(b, noUpdate=no_update) # type: ignore else: for b in batch(indicators, batch_size=2000): demisto.createIndicators(b, noUpdate=no_update) # type: ignore demisto.setIntegrationContext({'have_fetched_first_time': True}) def bitcoin_abuse_get_indicators_command(bitcoin_client: BitcoinAbuseClient, args: Dict): """ Wrapper for retrieving indicators from the feed to the war-room. Args: bitcoin_client (BitcoinAbuseClient): Client object. args (Dict): Demsisto args. Returns: CommandResults. """ indicators, _ = bitcoin_client.get_indicators() limit = arg_to_number(args.get('limit', 50), 'limit') truncated_indicators_list = indicators[:limit] return CommandResults( readable_output=tableToMarkdown('Indicators', truncated_indicators_list, headers=['value', 'type', 'fields']), raw_response=truncated_indicators_list ) def main() -> None: params = demisto.params() command = demisto.command() demisto.debug(f'Bitcoin Abuse: Command being called is {demisto.command()}') api_key = params.get('credentials_api_key', {}).get('password') or params.get('api_key', '') if not api_key: raise DemistoException('API Key must be provided.') insecure = params.get('insecure', False) proxy = params.get('proxy', False) feed_tags = argToList(params.get('feedTags')) tlp_color = params.get('tlp_color') initial_fetch_interval = params.get('initial_fetch_interval', '30 Days') have_fetched_first_time = argToBoolean(demisto.getIntegrationContext().get('have_fetched_first_time', False)) try: bitcoin_client = BitcoinAbuseClient( base_url=SERVER_URL, insecure=insecure, proxy=proxy, api_key=api_key, initial_fetch_interval=initial_fetch_interval, reader_config=READER_CONFIG, feed_tags=feed_tags, tlp_color=tlp_color, have_fetched_first_time=have_fetched_first_time) if command == 'test-module': return_results(test_module_command(bitcoin_client)) elif command == 'fetch-indicators': bitcoin_abuse_fetch_indicators_command(bitcoin_client) elif command == 'bitcoinabuse-get-indicators': return_results(bitcoin_abuse_get_indicators_command(bitcoin_client, demisto.args())) elif command == 'bitcoinabuse-report-address': return_results(bitcoin_abuse_report_address_command(bitcoin_client, demisto.args())) # Log exceptions and return errors except Exception as e: return_error(f'Failed to execute {demisto.command()} command.\nError:\n{str(e)}') if __name__ in ('__main__', '__builtin__', 'builtins'): main()