CloudShark
Use the CloudShark integration to upload, share, and collaborate on network packet capture files using your on-premises CS Enterprise system.
Data Enrichment & Threat Intelligence · CloudShark
Details
| ID | CloudShark |
|---|---|
| Provider | QA Cafe LLC |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.8.3296088 |
| Supported Modules | Agentix XSIAM |
README
Overview
Designed for networking and security teams, CS Enterprise is a collaboration platform focused on network packet capture (PCAP) analysis. CS Enterprise delivers secure storage, organization, access control, and powerful analysis tools in an elegant, responsive browser-based interface.
Use Cases
- Upload a network capture for analysis in your browser
- Collaborate on network pcap analysis by easily sharing captures with others via a URL
- Collect meta-information about a capture file
- Manage and organize capture files in CS Enterprise
To set up CS Enterprise to work with Cortex XSOAR
You will need the following before setting up the CS Enterprise integration on
Cortex XSOAR:
- CS Enterprise URL The URL of your CS Enterprise instance
- API Token: An API Token from CloudShark with upload, info, download, and delete permissions enabled on it
Configure the CS Enterprise Integration on Cortex XSOAR
- Go to Settings > Integrations > Servers & Services
- Search for CloudShark
- Click Add instance to create and configure a new integration instance
- Name: a textual name for the integration instance
- CS Enterprise URL: The URL of your CS Enterprise Instance
- API Token: Your API token
- Click Test to validate the URL
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.
- cloudshark-upload: cloudshark-upload
- cloudshark-info: cloudshark-info
- cloudshark-download: cloudshark-download
- cloudshark-delete: cloudshark-delete
1. cloudshark-upload
Upload a capture file into CS Enterprise
Base Command
cloudshark-upload
Input
| Argument Name | Description | Required |
|---|---|---|
| file | EntryID of the capture to upload | Required |
| additional_tags | A comma-separated list of tags to apply to the capture file | Optional |
| filename | The filename of the capture in CS Enterprise | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| URL.Data | string | URL of the capture file in CS Enterprise |
| CloudShark.CaptureID | string | Capture ID of the capture in CS Enterprise |
Command Example
!cloudshark-upload file=494@1e6024f1-485b-4d1a-8ee3-b6bf51e8ca1a filename=demisto.pcapng additional_tags=demisto,cloudshark,test
Context Example
{
"CloudShark": {
"CaptureID": "5277a3a64076"
},
"URL": {
"Data": "CLOUDSHARK_URL/captures/5277a3a64076"
}
}
Human Readable Output
Open Capture in CloudShark
2. cloudshark-info
Retrieve meta-information about a capture file from CS Enterprise
Base Command
cloudshark-info
Input
| Argument Name | Description | Required |
|---|---|---|
| capture_id | Capture ID of the capture in CS Enterprise | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| CloudShark.CaptureInfo | unknown | Meta-information of capture file |
Command Example
!cloudshark-info capture_id=ccaa62cbbb06
Context Example
{
"CloudShark": {
"CaptureInfo": {
"avg_packet_rate": "3.24",
"avg_packet_size": "70.19",
"cap_file_id": 165174,
"comments": "",
"created_at": "2019-11-06T21:18:30+00:00",
"data_bit_rate": "1817.36",
"data_byte_rate": "227.17",
"data_size": 4071908,
"disable_autodelete": false,
"duration": "17924.501967",
"encapsulation": "Ethernet",
"end_time": "2019-07-26T23:20:44+00:00",
"file": "/var/www/cloudshark/current/uploads/2019/11/05/16/13172ab4-61a7-4439-aa27-292306c062c0.cap",
"file_source": "upload",
"file_type": "Wireshark/tcpdump/... - pcap",
"filename": "capture.pcapng",
"group": "",
"group_write?": false,
"id": "ccaa62cbbb06",
"last_accessed": "2019-11-07T15:42:07+00:00",
"num_packets": 58009,
"public?": false,
"sha1_hash": "e871eee9d85a9898d1f7aec37f22f291fb1d1971",
"size": 5000076,
"start_time": "2019-07-26T18:22:00+00:00",
"tag_list": "",
"truncated": "No",
}
}
}
Human Readable Output
Capture file info
| avg_packet_rate | avg_packet_size | cap_file_id | comments | created_at | data_bit_rate | data_byte_rate | data_size | disable_autodelete | duration | encapsulation | end_time | file | file_source | file_type | filename | group | group_write? | id | last_accessed | num_packets | public? | sha1_hash | size | start_time | tag_list | truncated | user |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 3.24 | 70.19 | 165174 | 2019-11-06T21:18:30+00:00 | 1817.36 | 227.17 | 4071908 | false | 17924.501967 | Ethernet | 2019-07-26T23:20:44+00:00 | /var/www/cloudshark/current/uploads/2019/11/05/16/13172ab4-61a7-4439-aa27-292306c062c0.cap | upload | Wireshark/tcpdump/... - pcap | capture.pcapng | false | ccaa62cbbb06 | 2019-11-07T15:42:07+00:00 | 58009 | false | e871eee9d85a9898d1f7aec37f22f291fb1d1971 | 5000076 | 2019-07-26T18:22:00+00:00 | No |
3. cloudshark-download
Download a capture file from CS Enterprise
Base Command
cloudshark-download
Input
| Argument Name | Description | Required |
|---|---|---|
| capture_id | Capture ID of the capture in CS Enterprise | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| File | unknown | File downloaded from CloudShark |
Command Example
!cloudshark-download capture_id=ccaa62cbbb06
Human Readable Output
4. cloudshark-delete
Delete a capture file from CS Enterprise
Base Command
cloudshark-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| capture_id | Delete a capture file from CS Enterprise | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CloudShark.Result | unknown | Result of delete command |
Command Example
!cloudshark-delete capture_id=ccaa62cbbb06
Context Example
{
"CloudShark": {
"Result": {
"id": "5277a3a64076",
"message": "Capture deleted successfully.",
"status": 200
}
}
}
Human Readable Output
Result
| Response |
|---|
| id: ccaa62cbbb06 status: 200 message: Capture deleted successfully. |
Configuration parameters
url— CS Enterprise URL (required)apikey— API Token (required)proxy— Use system proxy settingsinsecure— Trust any certificate (not secure)
Commands (4)
-
cloudshark-deleteDeletes a capture file from CS Enterprise.
-
cloudshark-downloadDownloads a capture file from CS Enterprise.
-
cloudshark-infoRetrieves meta-information about a capture file from CS Enterprise.
-
cloudshark-uploadUploads a capture file into CS Enterprise
import collections import demistomock as demisto import requests import urllib3 from CommonServerPython import * # disable insecure warnings urllib3.disable_warnings() BASE_URL = demisto.params().get("url") USE_SSL = not demisto.params().get("insecure", False) PROXY = demisto.params().get("proxy") API_KEY = demisto.params().get("apikey") """HELPER FUNCTIONS""" capture_info_outputs = { "id": "CaptureID", "group_write?": "GroupWrite", "size": "Size", "data_byte_rate": "DataByteRate", "tag_list": "TagList", "data_bit_rate": "DataBitRate", "filename": "FileName", "sha1_hash": "SHA1", "avg_packet_rate": "AvgPacketRate", "start_time": "StartTime", "created_at": "CreatedAt", "avg_packet_size": "AvgPacketSize", "user": "User", "last_accessed": "LastAccessed", "disable_autodelete": "DisableAutodelete", "cap_file_id": "CapFileID", "end_time": "EndTime", "num_packets": "NumPackets", "encapsulation": "Encapsulation", "duration": "Duration", "comments": "Comments", "public?": "Public", "data_size": "DataSize", "file": "File", "file_type": "FileType", "file_source": "FileSource", "truncated": "Truncated", "group": "Group", } # Translates the capture info field names to standard outputs def transalte_capture_info(capture_info): translated_output = {} for field_name, standard_name in capture_info_outputs.items(): if field_name in capture_info: translated_output[standard_name] = capture_info.get(field_name) return translated_output # Allows nested keys to be accesible def makehash(): return collections.defaultdict(makehash) def parse_error_response(http_response): try: response = http_response.json() except ValueError: return ( f"Error in API call. Recived status code: {http_response.status_code};" f" Reason: {http_response.reason}; contents: {http_response.content}" ) exceptions = response.get("exceptions", "") if exceptions: # noqa: RET503 return f"Call Failed. status code:{http_response.status_code}, reason: {exceptions}" def http(method, url_suffix, params=None, data=None, files=None): try: response = requests.request( method, BASE_URL + "/api/v1/" + API_KEY + url_suffix, verify=USE_SSL, params=params, data=data, files=files ) if response.status_code == 200: return response elif (response.status_code == 403) and (url_suffix == "/search/"): # API Token cannot execute API method. # If testing toekn is valid using the /search/ endpoint this is ok return response elif response.status_code == 404: return_error(parse_error_response(response)) else: return_error(parse_error_response(response)) except requests.exceptions.ConnectionError as err: return_error("Could not connect to CS Enterprise URL ", str(err)) except requests.exceptions.MissingSchema: return_error("Invalid Schema. URL must start with http:// or https://") except requests.exceptions.InvalidSchema: return_error("Invalid Schema. URL must start with http:// or https://") """MAIN FUNCTIONS""" def upload(file_entry_id, additional_tags=None, filename=None): # Get file cmd_res = demisto.getFilePath(file_entry_id) file_path = cmd_res.get("path") name = cmd_res.get("name") # Setup optional parameters params = {} if filename is not None: params["filename"] = filename if additional_tags is not None: params["additional_tags"] = additional_tags files = {"file": (name, open(file_path, "rb"))} response = http("POST", "/upload", files=files, params=params) capture_id = response.json()["id"] return capture_id def upload_command(): # Get arguments file_entry_id = demisto.args().get("file") filename = demisto.args().get("filename") additional_tags = demisto.args().get("additional_tags") # Create hashes contxt = makehash() # Upload capture and get capture_id capture_id = upload(file_entry_id, additional_tags=additional_tags, filename=filename) url = BASE_URL + "/captures/" + capture_id # Set Demisto Context contxt["URL"]["Data"] = url contxt["CloudShark"]["CaptureID"] = capture_id ec = contxt # Create markdown link to capture markdown_url = "CaptureID: " + capture_id + " - [Open Capture in CloudShark](" + url + ")" demisto.results( { "Type": entryTypes["note"], "ContentsFormat": formats["markdown"], "Contents": ec, "HumanReadable": markdown_url, "EntryContext": ec, } ) def info(capture_id): url_suffix = "/info/" + capture_id response = http("GET", url_suffix) info = response.json() return info def info_command(): # Get arguments capture_id = demisto.args().get("capture_id") # Create hashes contxt = makehash() # Request meta-info from CloudShark file_info = info(capture_id) # Set Demisto Context capture_info = transalte_capture_info(file_info) contxt["CloudShark.CaptureInfo(val.CaptureID && val.CaptureID == obj.CaptureID)"] = capture_info ec = contxt # Create table with capture info info_table = tableToMarkdown("Capture file info", capture_info) demisto.results( { "Type": entryTypes["note"], "ContentsFormat": formats["markdown"], "Contents": file_info, "HumanReadable": info_table, "EntryContext": ec, } ) def download(capture_id): url_suffix = "/download/" + capture_id response = http("GET", url_suffix) filename = re.findall("filename=(.+)", response.headers["Content-Disposition"])[0] file = response.content files = {"filename": filename, "file": file} return files def download_command(): # Get argument capture_id = demisto.args().get("capture_id") # Download file files = download(capture_id) demisto.results(fileResult(files["filename"], files["file"])) def delete(capture_id): url_suffix = "/delete/" + capture_id response = http("POST", url_suffix) msg = response.json() return msg def delete_command(): # Get argument capture_id = demisto.args().get("capture_id") # Create hashes contxt = makehash() human_readable = makehash() # Delete capture result = delete(capture_id) # Set result contents = result human_readable["Response"] = result contxt["CloudShark"]["Result"] = result ec = contxt demisto.results( { "Type": entryTypes["note"], "ContentsFormat": formats["markdown"], "Contents": contents, "HumanReadable": tableToMarkdown("Result", human_readable), "EntryContext": ec, } ) """ EXECUTION CODE """ LOG(f"command is {demisto.command()}") try: handle_proxy() # The command demisto.command() holds the command sent from the user. if demisto.command() == "cloudshark-upload": upload_command() elif demisto.command() == "cloudshark-info": info_command() elif demisto.command() == "cloudshark-download": download_command() elif demisto.command() == "cloudshark-delete": delete_command() elif demisto.command() == "test-module": # This is the call made when pressing the integration test button. if API_KEY == "": return_error("Must enter API Token") response = http("GET", "/search/") if response.status_code == 200 or response.status_code == 403: # Token is valid but search method not allowed demisto.results("ok") else: demisto.results(f"Error: Server returned {response.status_code}: {response.reason}") sys.exit(0) except Exception as e: LOG(e) LOG.print_log() raise