MalwareBazaar Feed
Use the MalwareBazaar Feed integration to get the list of malware samples added to MalwareBazaar within the last 60 minutes.
Data Enrichment & Threat Intelligence · MalwareBazaar Feed · Feed
Details
| ID | MalwareBazaar Feed |
|---|---|
| Provider | AbuseCh |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 6.0.0 |
| Docker Image | demisto/py3-tools:1.0.0.10120494 |
| Supported Modules | Agentix XSIAM |
README
The MalwareBazaar Feed integration leverages abuse.ch to get the list of malware samples added to MalwareBazaar within the last 60 minutes.
Configure MalwareBazaar Feed in Cortex
| Parameter | Description | Required |
|---|---|---|
| Server URL | True | |
| Fetch indicators | False | |
| Auth Key | Auth Key for authentication with abuser.ch | True |
| Indicator Reputation | Indicators from this integration instance will be marked with this reputation. | False |
| Source Reliability | Reliability of the source providing the intelligence data. | True |
| Traffic Light Protocol Color | The Traffic Light Protocol (TLP) designation to apply to indicators fetched from the feed. | False |
| Feed Fetch Interval | False | |
| Bypass exclusion list | When selected, the exclusion list is ignored for indicators from this feed. This means that if an indicator from this feed is on the exclusion list, the indicator might still be added to the system. | False |
| Tags | Supports CSV values. | False |
| Create relationships | False | |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False |
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.
malwarebazzar-get-indicators
Gets the feed indicators.
Base Command
malwarebazzar-get-indicators
Input
| Argument Name | Description | Required |
|---|---|---|
| limit | The maximum number of results to return. The default value is 50. Default is 50. | Optional |
Context Output
There is no context output for this command.
Command Example
!malwarebazzar-get-indicators limit=3
Human Readable Output
Indicators
value type rawJSON 2fd9985380a92fa918df25189e1023c27052355dc1c7f8a2d11339be7ddfc7d3 File sha256_hash: 2fd9985380a92fa918df25189e1023c27052355dc1c7f8a2d11339be7ddfc7d3
sha3_384_hash: be865100f4cb963d9dbe6cd10b453cdfc7f5ee7f22975e7c7c8120a9631b797880f58ae842d02761f074429aeb160057
sha1_hash: 4068065df0d806c05b1bd6138bdb32f483c816a2
md5_hash: a76e2cdba762de201e0668178b03bec4
first_seen: 2021-10-04 11:26:00
last_seen: null
file_name: a76e2cdba762de201e0668178b03bec4.exe
file_size: 119016
file_type_mime: application/x-dosexec
file_type: exe
reporter: abuse_ch
origin_country: FR
anonymous: 0
signature: RedLineStealer
imphash: f34d5f2d4577ed6d9ceec516c1f5a744
tlsh: T1BBC33B3553DC8A28EBFE1F75B071120047F0D1CB6512EB5B9EC26CEA5E73B825A512E2
telfhash: null
ssdeep: 1536:5e1zHb1iaNk5mXKSr7y9zjbuRNdsnhuyq/dMV1dbknEjG6qTaoigNK:0S0X7y978snYyOdM9kEW9K
dhash_icon: null
tags: exe,
RedLineStealer
code_sign:
intelligence: {“clamav”: null, “downloads”: “1”, “uploads”: “1”, “mail”: null}e9dc15fdcf77dd8dde52392b63a79e43e39d85431434198f5103ced790f9034a File sha256_hash: e9dc15fdcf77dd8dde52392b63a79e43e39d85431434198f5103ced790f9034a
sha3_384_hash: 362f8c4a885bacc2158dd1b1f3f96848b982ac94df8e67b930b0dc766369d08bdbb0c97b713a9a561d3f72be4c65f27c
sha1_hash: f59a1e433565255d52720f49ce0f4e52c29b78bf
md5_hash: f0e38ba220616f3b94a5f71712d52817
first_seen: 2021-10-04 11:13:59
last_seen: 2021-10-04 11:14:29
file_name: swift art.pdf.exe
file_size: 422912
file_type_mime: application/x-dosexec
file_type: exe
reporter: cocaman
origin_country: FR
anonymous: 0
signature: AgentTesla
imphash: f34d5f2d4577ed6d9ceec516c1f5a744
tlsh: T1CB94026823A7D314DE3483F43C18A69127FA742B151DD37C5E89E4ED3E52B748AE0A87
telfhash: null
ssdeep: 6144:6Axt05ERQ+3HwO0adBqsB9+U1eqjRISdJOyYge708qlv5/Mf76oAeEHm9E0:iESoZ4C9AWIzJgeCvlY5AeEKh
dhash_icon: null
tags: AgentTesla,
exe,
SWIFT
code_sign:
intelligence: {“clamav”: null, “downloads”: “30”, “uploads”: “2”, “mail”: null}3e1a48cb4283d83c729670dbdc69d6a8d5290a50bebc621baf7e0a72cd56ffb6 File sha256_hash: 3e1a48cb4283d83c729670dbdc69d6a8d5290a50bebc621baf7e0a72cd56ffb6
sha3_384_hash: 1104c8634247f86d15f3e61faa68d7232f797936e3cf838b21052d4a9ebf52a6a523462e9e1ce3bdb9a13f5e51a5da86
sha1_hash: a5035ff9bd7264431a254a0b973864febfb19c7f
md5_hash: ca13a97b94b0e17f5d863a2290f10931
first_seen: 2021-10-04 11:13:49
last_seen: 2021-10-04 11:14:20
file_name: swift art.pdf.zip
file_size: 372101
file_type_mime: application/zip
file_type: zip
reporter: cocaman
origin_country: US
anonymous: 0
signature: AgentTesla
imphash: null
tlsh: T15A842305488BE237E7433679D60D0A4173D9399B0F15F6FAEC1B9B67AE811108EF49CA
telfhash: null
ssdeep: 6144:aI84xUdNqsB9+U1eq7RUSdROy8g27o8qpv5hM3N6sAIEPmh7hF8:Z84xyUA9gwUNng2avz2ZAImA/8
dhash_icon: null
tags: AgentTesla,
SWIFT,
zip
code_sign:
intelligence: {“clamav”: null, “downloads”: “25”, “uploads”: “2”, “mail”: null}
Create an Auth Key
for abuse.ch
- Sign up for an abuse.ch account by using an existing account that you may already have on X, LinkedIn, Google or Github. Just log in with the authentication provider of your choice here: https://auth.abuse.ch/
- Once you’ve logged in to abuse.ch, add at least one more way to log in. This helps ensure you can always access our platforms, even if one of your login methods stops working.
- Click the Save profile button. In the Optional section, you can now create an Auth-Key. This is your personal authentication key that you can use to query any abuse.ch APIs.
If you already have a profile, you only need to follow step 3. There’s nothing further to do for your authentication set up.
Configuration parameters
url— Server URL (required)credentials—feed— Fetch indicatorsfeedReputation— Indicator ReputationfeedReliability— Source Reliability (required)tlp_color— Traffic Light Protocol ColorfeedExpirationPolicy—feedExpirationInterval—feedFetchInterval— Feed Fetch IntervalfeedBypassExclusionList— Bypass exclusion listfeedTags— Tagscreate_relationships— Create relationshipsinsecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (1)
-
malwarebazzar-get-indicatorsGets the feed indicators.
import demistomock as demisto import pytest from pytest_mock import MockerFixture from requests import HTTPError def test_fetch_indicators_main(mocker: MockerFixture): """ Given - indicators response from malware bazzar feed When - Running main flow for fetching indicators command Then - Ensure that all indicators values exist and are not 'None' """ from JSONFeedApiModule import Client from MalwareBazaarFeed import main mocker.patch.object( demisto, "params", return_value={ "feed": True, "feedBypassExclusionList": False, "feedExpirationInterval": "20160", "feedExpirationPolicy": "suddenDeath", "feedFetchInterval": 1, "feedReliability": "A - Completely reliable", "feedReputation": "None", "feedTags": None, "insecure": True, "ip_ranges": "All available Google IP ranges", "proxy": False, "tlp_color": None, "url": "https://mb-api.abuse.ch", "credentials": {"password": "test"}, }, ) mocker.patch.object(demisto, "command", return_value="fetch-indicators") create_indicators_mocker = mocker.patch.object(demisto, "createIndicators") mocker.patch.object( Client, "build_iterator", side_effect=[([{"sha256_hash": "1234"}, {"sha256_hash": "12345"}, {"sha256_hash": "123456"}], True), ([], True)], ) main() assert create_indicators_mocker.call_args.args[0] == [ { "type": "File", "fields": {"tags": [], "downloadurl": "https://bazaar.abuse.ch/sample/1234/"}, "value": "1234", "rawJSON": {"sha256_hash": "1234"}, }, { "type": "File", "fields": {"tags": [], "downloadurl": "https://bazaar.abuse.ch/sample/12345/"}, "value": "12345", "rawJSON": {"sha256_hash": "12345"}, }, { "type": "File", "fields": {"tags": [], "downloadurl": "https://bazaar.abuse.ch/sample/123456/"}, "value": "123456", "rawJSON": {"sha256_hash": "123456"}, }, ] def test_custom_build_relationships(): """ Given - no feed config When - Running custom_build_relationships function Then - Ensure the relationship list is empty """ from MalwareBazaarFeed import custom_build_relationships assert custom_build_relationships(feed_config={}, _mapping={}, indicator_data={}) == [] def test_custom_mapping_function(): """ Given - mapping, attributes and indicators When - Running custom_mapping_function function Then - Ensure indicator dict is updated """ from MalwareBazaarFeed import custom_mapping_function mapping = {"a": "a.b", "c": "c", "d": "d"} attributes = {"a": "a", "b": "b", "c": "c"} indicator = {"fields": {"a": [{"a": "a"}], "b": "b"}} custom_mapping_function(mapping, indicator, attributes) assert indicator == {"fields": {"a": [{"a": "a", "b": "a"}], "b": "b", "c": "c"}} @pytest.mark.parametrize( "err_msg", [ pytest.param("502 Server Error: Bad Gateway for url: https://test/v1/", id="HTTPError 502"), pytest.param("Connection broken: IncompleteRead(3923 bytes read, 4269 more expected", id="Connection broken"), pytest.param("503 Server Error: Service Unavailable for url: https://test/v1/", id="HTTPError 503"), ], ) def test_exceptions_handle_known_exception(mocker: MockerFixture, err_msg: str): """ In the main function of the MalwareBazaar Feed we handle exceptions as follows: - Catch the exceptions occurred during the run of the 'feed_main' function. - Check if the exception is a known error. - If yes - wait 10 seconds and start another retry of the 'feed_main' function. (number or retries is 3). This test tests this logic. Given - A mock response of the 'feed_main' function that raises a known exception. 1. The exception is a known 502 server error. 2. The exception is a known connection error. 3. The exception is a known 503 server error. When - Running main flow for the fetching indicators command. Then - Verify that the exception is caught and the 'feed_main' function is called 4 times in total. - Verify that the error logs are as expected. """ from MalwareBazaarFeed import main mocker.patch.object(demisto, "params", return_value={"credentials": {"password": "test"}}) mocker.patch.object(demisto, "command", return_value="fetch-indicators") error_log_mock = mocker.patch.object(demisto, "error") def mock_feed_main(params, feed_name, prefix): raise HTTPError(err_msg) feed_main_mock = mocker.patch("MalwareBazaarFeed.feed_main", side_effect=mock_feed_main) with pytest.raises(Exception): main() assert "An Error Occurred during the run of the 'fetch-indicators' command" in error_log_mock.call_args_list[0][0][0] assert err_msg in error_log_mock.call_args_list[0][0][0] assert "Retrying in 10 seconds..." in error_log_mock.call_args_list[1][0][0] assert "This is attempt number: 1" in error_log_mock.call_args_list[1][0][0] assert "This is attempt number: 2" in error_log_mock.call_args_list[3][0][0] assert "This is attempt number: 3" in error_log_mock.call_args_list[5][0][0] assert feed_main_mock.call_count == 4 def test_exceptions_handle_unknown_exception(mocker): """ In the main function of the MalwareBazaar Feed we handle exceptions as follows: - Catch the exceptions occurred during the run of the 'feed_main' function. - Check if the exception is a known error. - If yes - wait 10 seconds and start another retry of the 'feed_main' function. (number or retries is 3). - If no - raises an error. This test tests this logic. Given - A mock response of the 'feed_main' function that raises an un-known exception. When - Running main flow for the fetching indicators command. Then - Verify that the exception is caught but the 'feed_main' function called only once. - Verify that the original error is raised. """ from MalwareBazaarFeed import main mocker.patch.object(demisto, "params", return_value={"credentials": {"password": "test"}}) mocker.patch.object(demisto, "command", return_value="fetch-indicators") error_log_mock = mocker.patch.object(demisto, "error") def mock_feed_main(params, feed_name, prefix): raise HTTPError( "[429] Failed with error: [parent] Data too large, data for [<http_request>] " "would be [1033445328/985.5mb], which is larger than the limit of [1020054732/972.7mb]" ) feed_main_mock = mocker.patch("MalwareBazaarFeed.feed_main", side_effect=mock_feed_main) with pytest.raises(Exception) as e: main() assert "[429] Failed with error: [parent] Data too large, data for [<http_request>]" in str(e) assert len(error_log_mock.call_args_list) == 0 assert feed_main_mock.call_count == 1 def test_exception_thrown_when_no_auth_key_param(mocker): from MalwareBazaarFeed import main mocker.patch.object(demisto, "params", return_value={}) mocker.patch.object(demisto, "command", return_value="fetch-indicators") error_log_mock = mocker.patch.object(demisto, "error") def mock_feed_main(params, feed_name, prefix): pass feed_main_mock = mocker.patch("MalwareBazaarFeed.feed_main", side_effect=mock_feed_main) with pytest.raises(Exception) as e: main() assert "Missing required parameter Auth Key. Please set this parameter in the instance configuration." in str(e) assert len(error_log_mock.call_args_list) == 0 assert feed_main_mock.call_count == 0 def test_no_exception_thrown_when_no_auth_key_param(mocker): from MalwareBazaarFeed import main mocker.patch.object(demisto, "params", return_value={"credentials": {"password": "test"}}) mocker.patch.object(demisto, "command", return_value="fetch-indicators") error_log_mock = mocker.patch.object(demisto, "error") def mock_feed_main(params, feed_name, prefix): return None feed_main_mock = mocker.patch("MalwareBazaarFeed.feed_main", side_effect=mock_feed_main) main() assert len(error_log_mock.call_args_list) == 0 assert feed_main_mock.call_count == 1 @pytest.mark.parametrize( "feed_tags, api_tags, expected_tags", [ pytest.param( ["source_mbazaar"], ["SilverFox", "ValleyRAT", "zip"], ["source_mbazaar", "SilverFox", "ValleyRAT", "zip"], id="merges_feed_tags_with_api_tags", ), pytest.param( ["source_mbazaar"], None, ["source_mbazaar"], id="preserves_feed_tags_when_api_tags_is_none", ), pytest.param( ["source_mbazaar"], [], ["source_mbazaar"], id="preserves_feed_tags_when_api_tags_is_empty", ), pytest.param( ["source_mbazaar", "SilverFox"], ["SilverFox", "ValleyRAT"], ["source_mbazaar", "SilverFox", "ValleyRAT"], id="deduplicates_overlapping_tags", ), ], ) def test_custom_mapping_function_tags_merge(feed_tags: list, api_tags: list | None, expected_tags: list): """ Regression test for XSUP-68506: The 'tags' mapping entry in MalwareBazaarFeed must MERGE the API response tags with the existing feedTags (set by JSONFeedApiModule.handle_indicator) rather than overwriting them. Given - An indicator whose fields["tags"] has already been populated with feedTags by handle_indicator. - A mapping that maps the API "tags" field to the indicator "tags" field. - Attributes from the API response with various tag values (list, None, empty). When - custom_mapping_function is called. Then - The resulting indicator["fields"]["tags"] matches the expected merged/deduplicated list. - The configured feedTags value is NOT lost. """ from MalwareBazaarFeed import custom_mapping_function mapping = {"tags": "tags"} attributes = {"tags": api_tags} indicator = {"fields": {"tags": feed_tags.copy()}, "value": "abc123"} custom_mapping_function(mapping, indicator, attributes) assert sorted(indicator["fields"]["tags"]) == sorted(expected_tags) def test_exceptions_handler_no_exception(mocker): """ In the main function of the MalwareBazaar Feed we handle exceptions as follows: - Catch the exceptions occurred during the run of the 'feed_main' function. - Check if the exception is a known error. - If yes - wait 10 seconds and start another retry of the 'feed_main' function. (number or retries is 3). - If no - raises an error. - If no error occurred the function is ended (without any recursive calls). This test tests this logic in case of a success (when no errors were detected in the feed_main function). Given - A mock response of the 'feed_main' function that returns None. When - Running main flow for the fetching indicators command. Then - Verify that the 'feed_main' function called only once. """ from MalwareBazaarFeed import main mocker.patch.object(demisto, "params", return_value={"credentials": {"password": "test"}}) mocker.patch.object(demisto, "command", return_value="fetch-indicators") error_log_mock = mocker.patch.object(demisto, "error") def mock_feed_main(params, feed_name, prefix): return None feed_main_mock = mocker.patch("MalwareBazaarFeed.feed_main", side_effect=mock_feed_main) main() assert len(error_log_mock.call_args_list) == 0 assert feed_main_mock.call_count == 1