Source
import demistomock as demisto # noqa: F401
import requests
from CommonServerPython import * # noqa: F401
NON_SSL_PREFIX = "http"
SSL_PREFIX = "https"
VENDOR = "URL SSL Verification"
SUSPICIOUS_SCORE = 2
UNKNOWN_SCORE = 0
URL_REGEX_PATTERN = r",(?=https?://)"
def arg_to_list_with_regex(arg):
"""
Converts a string representation of args to a python list
:type arg: ``str`` or ``list``
:param arg: Args to be converted (required)
:return: A python list of args
:rtype: ``list``
"""
if not arg:
return []
if isinstance(arg, list):
return arg
if isinstance(arg, STRING_TYPES):
if arg[0] == "[" and arg[-1] == "]":
return json.loads(arg)
return re.split(URL_REGEX_PATTERN, arg) # type: ignore[arg-type]
return arg
def request_get_wrap(url: str, allow_redirects=True):
"""
Wrapper around requests.get to handle SSL and connection errors,
and optionally capture the full redirect chain.
Return message with Failure information.
Args:
url (str): The URL to fetch.
allow_redirects (bool): Whether to follow redirects.
Returns:
tuple:
- message (dict): Result message with Vendor and Description.
- redirect_chain (list): List of response objects from the redirect chain (if any).
"""
message = {}
redirect_chain = []
try:
response = requests.get(url, timeout=5, allow_redirects=allow_redirects)
if allow_redirects:
redirect_chain = response.history + [response]
except requests.exceptions.SSLError:
message = {"Vendor": VENDOR, "Description": "SSL Certificate verification failed"}
except requests.exceptions.RequestException:
message = {"Vendor": VENDOR, "Description": "Failed to establish a new connection with the URL"}
return message, redirect_chain
def verify_ssl_certificate(url: str):
"""
Verifies the SSL certificate of a given URL by following any redirects and checking the certificate for each redirected URL.
If all of the redirect chain are all http return malicious message.
Args:
url (str): The URL to verify.
Returns:
dict: A dictionary with Information and a description of the issue if the SSL certificate verification.
Returns None if the verification is successful.
"""
message, redirect_chain = request_get_wrap(url, allow_redirects=True)
if message:
return message
is_all_http = True
for resp in redirect_chain:
redirected_url = resp.url
if not redirected_url.startswith(SSL_PREFIX):
continue
is_all_http = False
message, _ = request_get_wrap(url, allow_redirects=True)
if message:
return message
if is_all_http:
return {"Vendor": VENDOR, "Description": "The URL is not secure under SSL"}
return None
def mark_http_as_suspicious(set_http_as_suspicious):
# Could be None in previous playbooks that using this automation.
return set_http_as_suspicious != "false"
def main():
url_arg = demisto.get(demisto.args(), "url")
urls = arg_to_list_with_regex(url_arg)
set_http_as_suspicious = demisto.args().get("set_http_as_suspicious")
url_list = []
dbot_score = []
for url in urls:
url_obj = {"Data": url}
malicious = verify_ssl_certificate(url)
if malicious:
url_obj["Verified"] = False
url_obj["Malicious"] = malicious
else:
url_obj["Verified"] = True
score = UNKNOWN_SCORE
if mark_http_as_suspicious(set_http_as_suspicious) and not url.startswith(SSL_PREFIX):
score = SUSPICIOUS_SCORE
elif malicious:
score = SUSPICIOUS_SCORE
dbot_score.append(
{
"Indicator": url,
"Type": "url",
"Vendor": VENDOR,
"Score": score,
}
)
url_list.append(url_obj)
preview_list = [
{
"URL": url["Data"],
"Verified": url["Verified"],
"Description": demisto.get(url, "Malicious.Description") or "SSL certificate is verified",
}
for url in url_list
]
entry_context = {"URL": url_list, "DBotScore": dbot_score}
return_results(
CommandResults(
readable_output=tableToMarkdown(
name="URL SSL Verification", t=preview_list, headers=["URL", "Verified", "Description"]
),
outputs=entry_context,
outputs_key_field="URL.Data",
)
)
if __name__ in ["__main__", "__builtin__", "builtins"]:
main()