SNDBOX Deprecated
Deprecated. No available replacement.
Forensics & Malware Analysis · SNDBOX (Deprecated)
Details
| ID | SNDBOX |
|---|---|
| Provider | Palo Alto Networks |
| Category | Forensics & Malware Analysis |
| From Version | 5.0.0 |
| Docker Image | demisto/python:2.7.18.24398 |
| Supported Modules | Agentix |
README
Use the SNDBOX integration to detect and analyze potentially malicious files.
SNDBOX Playbook
- Detonate File - SNDBOX
Use Cases
- Sample a file.
- Get information on an old analysis.
Supported File Types
SNDBOX supports the following file types:
- Microsoft (2003 and earlier): doc, dot, xls, csv, xlt, xlm, ppt, pot, pps
- Microsoft (2007 and later): docx, docm, dotx, dotm, dotm, xlsx, xlsm, xltx, xltm, xlsb, xla, xlam, iqy, pptx, pptm, potx, ppsx, xml
- Other: pe32, rtf, pdf, vbs, vbe, ps1, js, lnk, html, bat
Configure SNDBOX on Cortex XSOAR
- Navigate to Settings > Integrations > Servers & Services.
- Search for SNDBOX.
- Click Add instance to create and configure a new integration instance.
- Name: a textual name for the integration instance.
- Use Public API Key. (By approving SNDBOX public API you are accepting SNDBOX TOS @ https://app.sndbox.com/tos). Public submissions are shared with the community
- Private API Key
- Use system proxy settings
- Trust any certificate (not secure)
- Max. Polling Time (in seconds):
- Verbose (show log in case of error)
- Click Test to validate the URLs, token, and connection.
Commands
You can execute these commands from the Cortex XSOAR 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.
- Check SNDBOX status: sndbox-is-online
- Get information for an analysis: sndbox-analysis-info
- Submit a sample for analysis: sndbox-analysis-submit-sample
- Download a report resource: sndbox-download-report
- (Deprecated) Detonate a report: sndbox-detonate-file
- Download a file sample of an analysis: sndbox-download-sample
1. Check SNDBOX status
Checks if SNDBOX is online or in maintenance mode.
Base Command
sndbox-is-online
Input
There is no input for this command.
Context Output
There is no context output for this command.
2. Get information for an analysis
Show information about an analysis.
Base Command
sndbox-analysis-info
Input
| Argument Name | Description | Required |
|---|---|---|
| analysis_id | Analysis IDs, supports CSV arrays | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| SNDBOX.Analysis.ID | string | Analysis ID |
| SNDBOX.Analysis.SampleName | string | Sample data |
| SNDBOX.Analysis.Status | string | Analysis status |
| SNDBOX.Analysis.Time | date | Submitted time |
| SNDBOX.Analysis.Score | float | Analysis score |
| SNDBOX.Analysis.Result | string | Analysis results |
| SNDBOX.Analysis.Errors | unknown | Raised errors during sampling |
| SNDBOX.Analysis.Link | string | Analysis link |
| SNDBOX.Analysis.MD5 | string | MD5 of analysis sample |
| SNDBOX.Analysis.SHA1 | string | SHA-1 of analysis sample |
| SNDBOX.Analysis.SHA256 | string | SHA-256 of analysis sample |
| DBotScore.Vendor | string | Vendor name: SNDBOX |
| DBotScore.Indicator | unknown | The name of the sample file |
| DBotScore.Type | string | File type |
| DBotScore.Score | number | The actual score |
| DBotScore.Malicious.Vendor | string | Vendor name: SNDBOX |
| DBotScore.Malicious.Detections | string | The sub-analysis detection statuses |
| DBotScore.Malicious.SHA1 | string | SHA-1 of the file |
Command Example
!sndbox-analysis-info analysis_id="65577395-48d8-4d51-bc97-bc2486f49ca0"
Context Example
Human Readable Output
3. Submit a sample for analysis
Submit a sample for analysis.
Base Command
sndbox-analysis-submit-sample
Input
| Argument Name | Description | Required |
|---|---|---|
| file_id | War Room entry of a file, e.g., 3245@4 | Optional |
| should_wait | Should the command poll for the result of the analysis | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| SNDBOX.Analysis.ID | string | Analysis ID |
| SNDBOX.Analysis.SampleName | string | Sample data, (file name or URL) |
| SNDBOX.Analysis.Status | string | Analysis status |
| SNDBOX.Analysis.Time | date | Submitted time |
| SNDBOX.Analysis.Result | string | Analysis results |
| SNDBOX.Analysis.Errors | unknown | Raised errors during sampling |
| SNDBOX.Analysis.Link | string | Analysis Link |
| SNDBOX.Analysis.MD5 | string | MD5 of analysis sample |
| SNDBOX.Analysis.SHA1 | string | SHA-1 of analysis sample |
| SNDBOX.Analysis.SHA256 | string | SHA-256 of analysis sample |
| DBotScore.Vendor | string | Vendor name: SNDBOX |
| DBotScore.Indicator | unknown | The name of the sample file or URL |
| DBotScore.Type | string | 'url' for url samples, otherwise 'file' |
| DBotScore.Score | number | The actual score |
| DBotScore.Malicious.Vendor | string | Vendor name: SNDBOX |
| DBotScore.Malicious.SHA1 | string | SHA-1 of the file |
Command Example
!sndbox-analysis-submit-sample file_id="288@670"
Context Example
Human Readable Output
4. Download a report resource
Download a resource belonging to a report. This can be the full report, dropped binaries, etc.
Base Command
sndbox-download-report
Input
| Argument Name | Description | Required |
|---|---|---|
| analysis_id | Analysis ID | Required |
| type | The resource type to download. Default is JSON. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| InfoFile.Name | string | File name |
| InfoFile.EntryID | string | The EntryID of the report |
| InfoFile.Size | number | File size |
| InfoFile.Type | string | File type, e.g., "PE" |
| InfoFile.Info | string | Basic information of the file |
| InfoFile.Extension | string | File extension |
Command Example
!sndbox-download-report analysis_id=65577395-48d8-4d51-bc97-bc2486f49ca0 type=json
Context Example
Human Readable Output
5. (Deprecated) Detonate a file
Submit a sample for detonation. This command is deprecated.
Base Command
sndbox-detonate-file
Input
| Argument Name | Description | Required |
|---|---|---|
| file_id | War Room entry of a file, e.g., 3245@4 | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| SNDBOX.Analysis.ID | string | Analysis ID |
| SNDBOX.Analysis.SampleName | string | Sample data (file name or URL) |
| SNDBOX.Analysis.Status | string | Analysis status |
| SNDBOX.Analysis.Time | date | Submitted time |
| SNDBOX.Analysis.Result | string | Analysis results |
| SNDBOX.Analysis.Errors | unknown | Raised errors during sampling |
| SNDBOX.Analysis.Link | string | Analysis link |
| SNDBOX.Analysis.MD5 | string | MD5 of analysis sample |
| SNDBOX.Analysis.SHA1 | string | SHA-1 of analysis sample |
| SNDBOX.Analysis.SHA256 | string | SHA-256 of analysis sample |
| DBotScore.Vendor | string | Vendor name: SNDBOX |
| DBotScore.Indicator | unknown | The name of the sample file or URL |
| DBotScore.Type | string | File |
| DBotScore.Score | number | The actual score |
| DBotScore.Malicious.Vendor | string | Vendor name: SNDBOX |
| DBotScore.Malicious.Detections | string | The sub-analysis detection statuses |
| DBotScore.Malicious.SHA1 | string | SHA-1 of the file |
6. Download the sample file of an analysis
Download the sample file of an analysis. For security reasons, the file extension will be .dontrun.
Base Command
sndbox-download-sample
Input
| Argument Name | Description | Required |
|---|---|---|
| analysis_id | Analysis ID | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| File.Size | number | File size |
| File.SHA1 | string | SHA-1 hash of the file |
| File.SHA256 | string | SHA-256 hash of the file |
| File.Name | string | The sample name |
| File.SSDeep | string | SSDeep hash of the file |
| File.EntryID | string | War Room entry ID of the file |
| File.Info | string | Basic information of the file |
| File.Type | string | File type, e.g., "PE" |
| File MD5 | string | MD5 hash of the file |
| File.Extension | string | File extension |
Command Example
!sndbox-download-sample analysis_id=65577395-48d8-4d51-bc97-bc2486f49ca0
Context Example
Configuration parameters
public_api_key— Use Public API Key. (By approving SNDBOX public API you are accepting SNDBOX TOS @ https://app.sndbox.com/tos). Public submissions are shared with the communityapi_key— Private API Key (required)proxy— Use system proxy settingsinsecure— Trust any certificate (not secure)maxpolls— Max. Polling Time (in seconds):verbose— Verbose (show log in case of error)
Commands (5)
-
sndbox-analysis-infoShow information about an analysis.
-
sndbox-analysis-submit-sampleSubmit a sample for analysis.
-
sndbox-download-reportDownload a resource belonging to a report. This can be the full report, dropped binaries, etc.
-
sndbox-download-sampleDownload the sample file of an analysis. for security reasons, the extension will be "dontrun"
-
sndbox-is-onlineCheck if SNDBOX is online or in maintenance mode.
import demistomock as demisto from CommonServerPython import * from CommonServerUserPython import * ''' IMPORTS ''' import time import shutil import requests from distutils.util import strtobool # disable insecure warnings requests.packages.urllib3.disable_warnings() ''' GLOBAL VARS ''' BASE_URL = 'https://api.sndbox.com/' SAMPLE_URL = 'https://app.sndbox.com/sample/' USE_SSL = not demisto.params().get('insecure', False) ''' HELPER FUNCTIONS ''' def http_cmd(url_suffix, data=None, files=None, parse_json=True): data = {} if data is None else data url_params = {} # type:dict use_public_api = demisto.params().get('public_api_key', False) api_key = demisto.params().get('api_key', False) if not api_key and use_public_api: url_params.setdefault('apikey', demisto.params()['secret_public_api_key']) elif api_key: url_params.setdefault('apikey', api_key) LOG('running request with url=%s\n\tdata=%s\n\tfiles=%s' % (BASE_URL + url_suffix, data, files,)) res = {} # type:dict if files: res = requests.post(BASE_URL + url_suffix, # type:ignore verify=USE_SSL, params=url_params, data=data, files=files ) else: res = requests.get(BASE_URL + url_suffix, # type:ignore verify=USE_SSL, params=url_params ) if res.status_code == 401: # type:ignore raise Exception('API Key is incorrect') if res.status_code >= 400: # type:ignore try: LOG('result is: %s' % (res.json(),)) # type:ignore error_msg = res.json()['errors'][0]['msg'] # type:ignore raise Exception('Your request failed with the following status code (%s) and error: %s.\n%s' % (res.status_code, res.reason, error_msg,)) # type:ignore except ValueError: # in case the response is not parsed as JSON raise Exception('Your request failed with the following status code (%s) and error: %s.' % (res.status_code, res.reason)) # type:ignore if parse_json: return res.json() # type:ignore else: return res.content # type:ignore def extract_status(sndbox_status): s = sndbox_status['dynamic']['code'] + sndbox_status['static']['code'] if s <= 1: return 'pending' elif s == 2: return 'finished' else: return 'error' def extract_errors(sndbox_status): errors = [] if 'message' in sndbox_status['static']: errors.append(sndbox_status['static']['message']) if 'message' in sndbox_status['dynamic']: errors.append(sndbox_status['dynamic']['message']) return errors def analysis_to_entry(title, info): if not isinstance(info, list): info = [info] context = [] table = [] dbot_scores = [] for analysis in info: malicious = analysis['score'] and analysis['score'] * 100 > 56 status = extract_status(analysis['status']) result = '' if status == 'finished': result = 'malicious' if malicious else 'clean' analysis_info = { 'ID': analysis['id'], # for detonate generic polling 'SampleName': analysis['name'], 'Status': status, 'Time': analysis['created_at'], 'Link': SAMPLE_URL + analysis['id'], 'MD5': analysis['md5'], 'SHA1': analysis['sha1'], 'SHA256': analysis['sha256'], 'Score': analysis['score'], 'Result': result, 'Errors': extract_errors(analysis['status']), } analysis_context = dict(analysis_info) analysis_table = dict(analysis_info) if not any(analysis_table['Errors']): analysis_table['Errors'] = None dbot_score = 0 if malicious: dbot_score = 3 malicious = { 'Vendor': 'SNDBOX', # 'Detections' : ['TODO'], 'SHA1': analysis_info['SHA1'], } else: dbot_score = 1 malicious = None dbot_scores.append({ 'Vendor': 'SNDBOX', 'Indicator': analysis_info['SampleName'], 'Type': 'file', 'Score': dbot_score, 'Malicious': malicious, }) context.append(analysis_context) table.append(analysis_table) entry = { 'ContentsFormat': formats['json'], 'Type': entryTypes['note'], 'Contents': context, 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown(title, table, removeNull=True), 'EntryContext': {'SNDBOX.Analysis(val.ID && val.ID == obj.ID)': createContext(context, removeNull=True), 'DBotScore': createContext(dbot_scores, removeNull=True), } } return entry def poll_analysis_id(analysis_id): result = info_request(analysis_id) max_polls = MAX_POLLS / 10 if MAX_POLLS > 0 else MAX_POLLS # type:ignore # pylint: disable=E0602 while (max_polls >= 0) and extract_status(result['status']) != 'finished': if extract_status(result['status']) != 'pending': LOG('error while polling: result is %s' % (result,)) result = info_request(analysis_id) time.sleep(10) max_polls -= 1 LOG('reached max_polls #%d' % (max_polls,)) if max_polls < 0: return analysis_to_entry('Polling timeout on Analysis #' + analysis_id, result) else: return analysis_to_entry('Analysis #' + analysis_id, result) ''' FUNCTIONS ''' def is_online(): cmd_url = '' res = http_cmd(cmd_url) return res['status'] == 'online' def analysis_info(): ids = demisto.args().get('analysis_id') if type(ids) in STRING_TYPES: ids = ids.split(',') LOG('info: analysis_id = %s' % (ids,)) res = [info_request(analysis_id) for analysis_id in ids] return analysis_to_entry('Analyses:', res) def info_request(analysis_id): cmd_url = '/developers/files/' + analysis_id return http_cmd(cmd_url) def analyse_sample(): args = demisto.args() file_entry = args.get('file_id', '') if type(file_entry) in STRING_TYPES: file_entry = [f for f in file_entry.split(',') if f != ''] should_wait = bool(strtobool(demisto.get(args, 'should_wait'))) if len(file_entry) == 0 or not file_entry: raise ValueError('You must specify: file_id.') LOG('analysing sample') return [analyse_sample_file_request(f, should_wait) for f in file_entry] def analyse_sample_file_request(file_entry, should_wait): data = {} # type:dict shutil.copy(demisto.getFilePath(file_entry)['path'], demisto.getFilePath(file_entry)['name']) with open(demisto.getFilePath(file_entry)['name'], 'rb') as f: res = http_cmd('/developers/files', data=data, files={'file': f}) if 'errors' in res: LOG('Error! in command sample file: file_entry=%s' % (file_entry,)) LOG('got the following errors:\n' + '\n'.join(e['msg'] for e in res['errors'])) raise Exception('command failed to run.') shutil.rmtree(demisto.getFilePath(file_entry)['name'], ignore_errors=True) if should_wait: return poll_analysis_id(res['id']) analysis_id = res['id'] result = info_request(analysis_id) return analysis_to_entry('Analysis #%s' % (analysis_id,), result) def download_report(): args = demisto.args() analysis_id = args.get('analysis_id') rsc_type = args.get('type') return download_request(analysis_id, rsc_type) def download_sample(): args = demisto.args() analysis_id = args.get('analysis_id') rsc_type = 'sample' return download_request(analysis_id, rsc_type) def download_request(analysis_id, rsc_type): cmd_url = '/developers/files/' + analysis_id + '/' + rsc_type.lower() res = http_cmd(cmd_url, parse_json=False) info = info_request(analysis_id) if rsc_type == 'sample': return fileResult('%s.dontrun' % (info.get('filename', analysis_id),), res) else: rsc_type = rsc_type if rsc_type != 'json' else 'json.gz' return fileResult('%s_report.%s' % (info.get('filename', analysis_id), rsc_type,), res, entryTypes['entryInfoFile']) ''' EXECUTION CODE ''' LOG('command is %s' % (demisto.command(),)) try: handle_proxy() if demisto.command() in ['test-module', 'sndbox-is-online']: # This is the call made when pressing the integration test button. if is_online(): demisto.results('ok') else: demisto.results('not online') elif demisto.command() == 'sndbox-analysis-info': demisto.results(analysis_info()) elif demisto.command() == 'sndbox-analysis-submit-sample': demisto.results(analyse_sample()) elif demisto.command() == 'sndbox-download-report': demisto.results(download_report()) elif demisto.command() == 'sndbox-download-sample': demisto.results(download_sample()) except Exception as e: if demisto.params().get('verbose'): LOG(str(e)) if demisto.command() != 'test-module': LOG.print_log() return_error('An error has occurred in the SNDBOX integration: {err}'.format(err=str(e)))





