WildFire-Reports

Generates a Palo Alto Networks WildFire PDF report. For internal use with the TIM Sample Analysis feature.

Forensics & Malware Analysis · WildFire by Palo Alto Networks

Details

IDWildFire-Reports
ProviderPalo Alto Networks
CategoryForensics & Malware Analysis
From Version6.5.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix Cortex Cloud Cloud Runtime Security XSIAM EDR

README

Generates a Palo Alto Networks WildFire PDF report.

This integration is set up by default on Cortex XSOAR versions 6.5+ with the Threat Intel Module (TIM). It is designed for internal use with the TIM Sample Analysis feature. To run ad hoc CLI commands to generate WildFire reports, use the Palo Alto Networks WildFire v2 integration instead.

This integration was created and tested with version 10.1 of WildFire.

Configure Palo Alto Networks WildFire Reports in Cortex

Parameter Description Required
Server base URL (e.g., https://192.168.0.1/publicapi)   True
API Key   False
Trust any certificate (not secure) Trust any certificate (not secure). False
Use system proxy settings 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.

internal-wildfire-get-report


Retrieves results for a file hash using WildFire.

Base Command

internal-wildfire-get-report

Input

Argument Name Description Required
sha256 SHA256 hash to check. Required

Context Output

There is no context output for this command.

Command Example

!internal-wildfire-get-report sha256=abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890

Human Readable Output

Configuration parameters

  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings
  • server — Server base URL (e.g., https://192.168.0.1/publicapi) (required)
  • credentials
  • token — API Key
  • agent — Override Agent

Commands (1)

  • internal-wildfire-get-report

    Retrieves results for a file hash using WildFire.

import urllib3
from CommonServerPython import *

# Disable insecure warnings
urllib3.disable_warnings()

""" CLIENT CLASS """


class Client(BaseClient):
    def __init__(
        self,
        base_url: str,
        verify: bool = True,
        proxy: bool = False,
        ok_codes=(),
        headers: dict = None,
        token: str = None,
        agent: str = "",
    ):
        super().__init__(base_url, verify, proxy, ok_codes, headers)
        self.token = token
        self.agent = self.get_agent(agent)
        add_sensitive_log_strs(token)

    @staticmethod
    def get_agent(agent: str = "") -> str:
        """
        Determine the agent header value for WildFire API requests.
        If an override is provided (and is not 'auto'), use it directly.
        When set to 'auto' (default) or empty, auto-detect based on the platform (XSOAR/XSIAM).

        Auto API expects the agent header to be 'xdr' when running from within XSIAM and 'xsoartim' when running from
        within XSOAR (both on-prem and cloud).
        """
        if agent and agent != "auto":
            return agent
        return "xdr" if is_xsiam() else "xsoartim"

    def get_file_report(self, file_hash: str):
        demisto.info(f"Requesting WildFire report for hash {file_hash}, format 'pdf', with agent={self.agent}")
        return self._http_request(
            "POST",
            url_suffix="/get/report",
            params={
                "apikey": self.token,
                "agent": self.agent,
                "format": "pdf",
                "hash": file_hash,
            },
            resp_type="response",
            ok_codes=(200, 401, 404),
        )


""" COMMAND FUNCTIONS """


def test_module(client: Client) -> str:  # pragma: no coverage
    try:
        wildfire_hash_example = "dca86121cc7427e375fd24fe5871d727"  # guardrails-disable-line
        res = client.get_file_report(wildfire_hash_example)
        if res.status_code == 401:
            return "Authorization Error: make sure API Key is correctly set"
    except DemistoException as e:
        if "Forbidden" in str(e):
            return "Authorization Error: make sure API Key is correctly set"
        else:
            raise e
    return "ok"


def wildfire_get_report_command(client: Client, args: Dict[str, str]):
    """
    Args:
        client: the Client object
        args: the command arguments from demisto.args(), file hash (sha256) to query on
    """
    sha256 = str(args.get("sha256"))
    if not sha256Regex.match(sha256):
        raise Exception("Invalid hash. Only SHA256 are supported.")

    res = client.get_file_report(sha256)

    if res.status_code == 200:
        return_results({"status": "success", "data": base64.b64encode(res.content).decode()})

    elif res.status_code == 401:
        return_results(
            {
                "status": "error",
                "error": {
                    "title": "Couldn't fetch the Wildfire report.",
                    "description": "Invalid apikey or expired apikey",
                    "techInfo": str(res.content),
                },
            }
        )

    elif res.status_code == 404:
        return_results({"status": "not found"})


""" MAIN FUNCTION """


def main():  # pragma: no coverage
    command = demisto.command()
    params = demisto.params()
    args = demisto.args()

    base_url = params.get("server")
    if base_url and base_url[-1] == "/":
        base_url = base_url[:-1]
    if base_url and not base_url.endswith("/publicapi"):
        base_url += "/publicapi"
    token = params.get("credentials", {}).get("password") or params.get("token")
    if not token:
        token = demisto.getLicenseCustomField("WildFire-Reports.token")
    if not token:
        # If token is empty when test-module is running, return a more readable output to the user.
        if command == "test-module":
            return_error(
                "Authorization Error: It's seems that the token is empty and you have not a TIM license "
                "that is up-to-date, Please fill the token or update your TIM license and try again."
            )
        else:
            return_results(
                {
                    "status": "error",
                    "error": {
                        "title": "Couldn't fetch the Wildfire report.",
                        "description": "The token can't be empty.",
                        "techInfo": "The token can't be empty, Please fill the token in the instance configuration "
                        "or update your TIM license.",
                    },
                }
            )
            sys.exit()
    verify_certificate = not params.get("insecure", False)
    proxy = params.get("proxy", False)
    agent = params.get("agent", "")

    headers = {"Content-Type": "application/x-www-form-urlencoded"}

    demisto.debug(f"Command being called is {command}")

    try:
        client = Client(
            base_url=base_url,
            token=token,
            headers=headers,
            verify=verify_certificate,
            proxy=proxy,
            agent=agent,
        )

        if command == "test-module":
            result = test_module(client)
            return_results(result)

        elif command == "internal-wildfire-get-report":
            wildfire_get_report_command(client, args)

    # Log exceptions and return errors
    except Exception as e:
        # Its not an error because it's not return to the warroom
        return_results(
            {
                "status": "error",
                "error": {
                    "title": "Couldn't fetch the Wildfire report.",
                    "description": f"Failed to download report.\nError:\n{e!s}",
                    "techInfo": f"Failed to execute command {demisto.command()}.\nError:\n{e!s}\n"
                    f"Trace back:\n{traceback.format_exc()}",
                },
            }
        )


""" ENTRY POINT """

if __name__ in ("__main__", "__builtin__", "builtins"):
    main()