ParseHTMLIndicators
This script will extract indicators from given HTML and will handle bad top-level domains to avoid false positives caused by file extensions.
python · Common Scripts
Source
import re import demistomock as demisto # noqa: F401 import requests from bs4 import BeautifulSoup from CommonServerPython import * # noqa: F401 from tld import get_tld def strip_html_tags(page): # Parse the HTML content soup = BeautifulSoup(page.content, "html.parser") # Strip irrelevant tags for data in soup(["style", "script", "header", "head", "footer", "aside", "a"]): data.decompose() return " ".join(soup.stripped_strings) def validate_domains(domains, unescape_domain, TLD_exclusion): # TLD exclusion and validation for domain indicators bad_domain_TLD = set() for indicator in domains: if unescape_domain and not (get_tld(indicator, fail_silently=True)): bad_domain_TLD.add(indicator) continue for tld in TLD_exclusion: if indicator.endswith(tld): bad_domain_TLD.add(indicator) return bad_domain_TLD def main(): # Retrieve demisto args args = demisto.args() blog_url = args.get("url") headers = {"user-agent": "PANW-XSOAR"} page = requests.get(blog_url, verify=False, headers=headers) # nosec page.raise_for_status() exclusion_list = set(argToList(args.get("exclude_indicators"))) TLD_exclusion = argToList(args.get("exclude_TLD")) unescape_domain = argToBoolean(args.get("unescape_domain")) # Allow domain regex replacement between "[.]" and "." domain_regex = r"([a-zA-Z0-9]+?\[?\.?\]?[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\[\.\][a-zA-Z]{2,}\[?\.?\]?[a-zA-Z]{0,})" if unescape_domain: domain_regex = domain_regex.replace(r"\[\.\]", r"\.") # Declare indicator regexs url_regex = r"([https|ftp|hxxps]+:[//|\\\\]+[\w\d:#@%/;$()~_\+-=\\\[\.\]&]*)" ip_regex = ( r"(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(?:\[\.\]|\.)){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])" ) cve_regex = r"(CVE-\d{4}-\d{4,7})" page_update = strip_html_tags(page) # Extract indicators using regex md5 = set(md5Regex.findall(page_update)) sha1 = set(sha1Regex.findall(page_update)) sha256 = set(sha256Regex.findall(page_update)) domain = set(re.findall(domain_regex, page_update)) url = set(re.findall(url_regex, page_update)) ip = set(re.findall(ip_regex, page_update)) cve = set(re.findall(cve_regex, page_update, flags=re.IGNORECASE)) # Validate the domain indicators bad_domain_TLD = validate_domains(domain, unescape_domain, TLD_exclusion) # Combine all indicators blog_indicators = (md5 | sha1 | sha256 | domain | url | ip | cve) - exclusion_list - bad_domain_TLD return_results( CommandResults( readable_output="\n".join(blog_indicators), outputs={"http.parsedBlog.indicators": list(blog_indicators), "http.parsedBlog.sourceLink": blog_url}, ) ) if __name__ in ("__builtin__", "builtins", "__main__"): main()
README
This script will extract indicators from given HTML and will handle bad top-level domains to avoid false positives caused by file extensions.
Script Data
| Name | Description |
|---|---|
| Script Type | python3 |
| Tags | |
| Cortex XSOAR Version | 5.5.0 |
Used In
This script is used in the following playbooks and scripts.
- Kaseya VSA 0-day - REvil Ransomware Supply Chain Attack
Inputs
| Argument Name | Description |
|---|---|
| url | The full URL of the blog |
| exclude_indicators | The indicators to be excluded from the results. |
| exclude_TLD | Top-Level-Domain to be excluded from domain indicators. |
| unescape_domain | Whether to remove brackets [] from the domain regex extraction. Can result in higher false positives for file extensions. |
Outputs
| Path | Description | Type |
|---|---|---|
| http.parsedBlog.indicators | The extracted indicators | Unknown |
| http.parsedBlog.sourceLink | The link for the source of the indicators | Unknown |