From f5d7912149587a0943157e9c84ba2791055fc8a4 Mon Sep 17 00:00:00 2001 From: cccs-kevin Date: Mon, 10 Jun 2024 20:28:52 +0000 Subject: [PATCH 1/9] Adding elements with src tag --- jsjaws.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/jsjaws.py b/jsjaws.py index 52f47c4f..d3e14d2e 100755 --- a/jsjaws.py +++ b/jsjaws.py @@ -1841,7 +1841,24 @@ def _extract_embeds_using_soup( embed_srcs: Set[str] = set() # https://www.w3schools.com/tags/att_src.asp - elements_with_src_attr = ["audio", "embed", "iframe", "img", "input", "script", "source", "track", "video"] + # Supported by https://github.com/sandialabs/laikaboss/blob/8dd2ca17c18d4d0d363d566798720acb7b4d3662/laikaboss/modules/scan_html.py#L60 + elements_with_src_attr = [ + "audio", + "embed", + "frame", + "iframe", + "img", + "input", + "script", + "source", + "track", + "v:fill", + "v:image", + "v:oval", + "v:rect", + "v:roundrect", + "video", + ] # https://www.w3schools.com/tags/att_href.asp elements_with_href_attr = ["a", "area", "base", "link"] From dc721c71cea62f9792aba1334b86fd418b7c9b2b Mon Sep 17 00:00:00 2001 From: cccs-kevin Date: Mon, 10 Jun 2024 20:30:22 +0000 Subject: [PATCH 2/9] Adding 'object' tag to src list --- jsjaws.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jsjaws.py b/jsjaws.py index d3e14d2e..5b163435 100755 --- a/jsjaws.py +++ b/jsjaws.py @@ -1841,7 +1841,7 @@ def _extract_embeds_using_soup( embed_srcs: Set[str] = set() # https://www.w3schools.com/tags/att_src.asp - # Supported by https://github.com/sandialabs/laikaboss/blob/8dd2ca17c18d4d0d363d566798720acb7b4d3662/laikaboss/modules/scan_html.py#L60 + # Supported and inspired by https://github.com/sandialabs/laikaboss/blob/8dd2ca17c18d4d0d363d566798720acb7b4d3662/laikaboss/modules/scan_html.py#L60 elements_with_src_attr = [ "audio", "embed", @@ -1849,6 +1849,8 @@ def _extract_embeds_using_soup( "iframe", "img", "input", + # Inspired by https://github.com/sandialabs/laikaboss/blob/8dd2ca17c18d4d0d363d566798720acb7b4d3662/laikaboss/modules/scan_html.py#L197 + "object", "script", "source", "track", From 68297c5e5036fc234e9119f10aae3fc619c9cd57 Mon Sep 17 00:00:00 2001 From: cccs-kevin Date: Mon, 10 Jun 2024 20:50:57 +0000 Subject: [PATCH 3/9] Adding validation for on- support --- jsjaws.py | 1 + 1 file changed, 1 insertion(+) diff --git a/jsjaws.py b/jsjaws.py index 5b163435..28c63b3e 100755 --- a/jsjaws.py +++ b/jsjaws.py @@ -2522,6 +2522,7 @@ def _handle_onevent_attributes( """ This method """ + # Supported by https://github.com/target/strelka/blob/3439953e6aa2dafb68ea73c3977da11f87aeacdf/src/python/strelka/scanners/scan_javascript.py#L37:L39 # Look for elements with the on attributes and add their script bodies to the aggregated js script for event in ["error", "pageshow", "load", "submit", "click", "finish"]: for onevent in element.get_attribute_list(f"on{event}"): From 8aef5d79b0208048bc58c7e111c300bbe1df681f Mon Sep 17 00:00:00 2001 From: cccs-kevin Date: Mon, 10 Jun 2024 20:51:39 +0000 Subject: [PATCH 4/9] Adding validation for signatures --- signatures/active_x_object.py | 2 ++ signatures/decode.py | 2 ++ signatures/suspicious_process.py | 3 +++ 3 files changed, 7 insertions(+) diff --git a/signatures/active_x_object.py b/signatures/active_x_object.py index 998a0bb0..2b06511e 100644 --- a/signatures/active_x_object.py +++ b/signatures/active_x_object.py @@ -1,10 +1,12 @@ """ These are all of the signatures related to using ActiveXObjects """ + from signatures.abstracts import Signature class ActiveXObject(Signature): + # Supported by https://github.com/target/strelka/blob/3439953e6aa2dafb68ea73c3977da11f87aeacdf/src/python/strelka/scanners/scan_javascript.py#L35 def __init__(self): super().__init__( heuristic_id=3, diff --git a/signatures/decode.py b/signatures/decode.py index 5979148f..d0dc39b4 100644 --- a/signatures/decode.py +++ b/signatures/decode.py @@ -7,6 +7,7 @@ class Unescape(Signature): # Supported by https://github.com/CYB3RMX/Qu1cksc0pe/blob/ad3105ab9d3363df013ff95bae218f5c374a93fb/Systems/Multiple/malicious_html_codes.json#L27 + # Supported by https://github.com/target/strelka/blob/3439953e6aa2dafb68ea73c3977da11f87aeacdf/src/python/strelka/scanners/scan_javascript.py#L33 # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/unescape def __init__(self): super().__init__( @@ -101,6 +102,7 @@ def process_output(self, output): class CryptoJSObfuscation(Signature): + # Supported by https://github.com/target/strelka/blob/3439953e6aa2dafb68ea73c3977da11f87aeacdf/src/python/strelka/scanners/scan_javascript.py#L41 def __init__(self): super().__init__( heuristic_id=3, diff --git a/signatures/suspicious_process.py b/signatures/suspicious_process.py index 32e8ab5f..d482f153 100644 --- a/signatures/suspicious_process.py +++ b/signatures/suspicious_process.py @@ -1,10 +1,12 @@ """ These are all of the signatures related to the presence of suspicious processes """ + from signatures.abstracts import Signature class SuspiciousProcess(Signature): + # Supported by https://github.com/target/strelka/blob/3439953e6aa2dafb68ea73c3977da11f87aeacdf/src/python/strelka/scanners/scan_javascript.py#L42 def __init__(self): super().__init__( heuristic_id=3, @@ -20,6 +22,7 @@ def process_output(self, output): class EvalUsage(Signature): # Inspired by https://github.com/CYB3RMX/Qu1cksc0pe/blob/ad3105ab9d3363df013ff95bae218f5c374a93fb/Systems/Multiple/malicious_html_codes.json#L7 + # Supported by https://github.com/target/strelka/blob/3439953e6aa2dafb68ea73c3977da11f87aeacdf/src/python/strelka/scanners/scan_javascript.py#L31 # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#never_use_eval! def __init__(self): From 2e78b92e76375d0652874836d75f42d81856bb3c Mon Sep 17 00:00:00 2001 From: cccs-kevin Date: Mon, 10 Jun 2024 20:52:37 +0000 Subject: [PATCH 5/9] Adding ExecCommandUsage and WebSocketUsage signatures --- signatures/network.py | 18 ++++++++++++++++++ signatures/suspicious_function_call.py | 17 +++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/signatures/network.py b/signatures/network.py index d91bba3c..86c44ae6 100644 --- a/signatures/network.py +++ b/signatures/network.py @@ -1,11 +1,13 @@ """ These are all of the signatures related to making network requests """ + from signatures.abstracts import ALL, Signature class PrepareNetworkRequest(Signature): # Supported by https://github.com/CYB3RMX/Qu1cksc0pe/blob/ad3105ab9d3363df013ff95bae218f5c374a93fb/Systems/Multiple/malicious_html_codes.json#L47 + # Supported by https://github.com/target/strelka/blob/3439953e6aa2dafb68ea73c3977da11f87aeacdf/src/python/strelka/scanners/scan_javascript.py#L36 def __init__(self): super().__init__( heuristic_id=3, @@ -90,3 +92,19 @@ def process_output(self, output): {"method": ALL, "indicators": self.indicators}, ] self.check_multiple_indicators_in_list(output, indicator_list) + + +class WebSocketUsage(Signature): + # Inspired by https://github.com/target/strelka/blob/3439953e6aa2dafb68ea73c3977da11f87aeacdf/src/python/strelka/scanners/scan_javascript.py#L40 + # https://developer.mozilla.org/en-US/docs/Web/API/WebSocket + def __init__(self): + super().__init__( + heuristic_id=3, + name="websocket_usage", + description="WebSocket object was used for communicating with a server", + indicators=["WebSocket("], + severity=0, + ) + + def process_output(self, output): + self.check_indicators_in_list(output) diff --git a/signatures/suspicious_function_call.py b/signatures/suspicious_function_call.py index 436872c2..c67b35b0 100644 --- a/signatures/suspicious_function_call.py +++ b/signatures/suspicious_function_call.py @@ -1,6 +1,7 @@ """ These are all of the signatures related to using suspicious function calls """ + from signatures.abstracts import Signature @@ -39,3 +40,19 @@ def __init__(self): def process_output(self, output): self.check_indicators_in_list(output, match_all=True) + + +class ExecCommandUsage(Signature): + # Inspired by https://github.com/target/strelka/blob/3439953e6aa2dafb68ea73c3977da11f87aeacdf/src/python/strelka/scanners/scan_javascript.py#L34 + # https://developer.mozilla.org/en-US/docs/Web/API/document/execCommand + def __init__(self): + super().__init__( + heuristic_id=3, + name="execcommand_usage", + description="Executes command, possibly related to clipboard access, or editing forms and documents.", + indicators=["execCommand("], + severity=0, + ) + + def process_output(self, output): + self.check_indicators_in_list(output, match_all=True) From 7b1d40f36b1a84f84a2c1aa1e77679640547a91d Mon Sep 17 00:00:00 2001 From: cccs-kevin Date: Thu, 13 Jun 2024 17:49:02 +0000 Subject: [PATCH 6/9] Adding HTML detection for automatic redirection in meta tags --- jsjaws.py | 120 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 45 deletions(-) diff --git a/jsjaws.py b/jsjaws.py index 28c63b3e..f68689f5 100755 --- a/jsjaws.py +++ b/jsjaws.py @@ -24,7 +24,6 @@ from assemblyline.common.identify import CUSTOM_BATCH_ID, CUSTOM_PS1_ID from assemblyline.common.str_utils import safe_str, truncate from assemblyline.common.uid import get_id_from_data -from assemblyline.odm.base import DOMAIN_ONLY_REGEX, FULL_URI, URI_REGEX from assemblyline_service_utilities.common.dynamic_service_helper import ( COMMON_FP_DOMAINS, OntologyResults, @@ -52,6 +51,7 @@ from bs4 import BeautifulSoup from bs4.element import Comment, PageElement, ResultSet from dateutil.parser import parse as dtparse +from multidecoder.decoders.network import find_urls, is_domain, is_url from multidecoder.decoders.shell import find_powershell_strings, get_powershell_command from requests import get from signatures.abstracts import Signature @@ -723,9 +723,7 @@ def _handle_filtered_code(self, file_path: str, file_content: bytes) -> Tuple[st for uri in gootloader_config.urls: stripped_uri = uri.strip() # URI should exist, URI should actually be a URI, or URI is actually a domain - if not stripped_uri or ( - not re.match(FULL_URI, stripped_uri) and not re.match(DOMAIN_ONLY_REGEX, stripped_uri) - ): + if not stripped_uri or (not is_url(stripped_uri.encode()) and not is_domain(stripped_uri.encode())): continue self.gootloader_uris.append(stripped_uri) @@ -1785,6 +1783,7 @@ def extract_using_soup( self._hunt_for_suspicious_titles(soup) self._hunt_for_suspicious_input_fields(soup) self._hunt_for_suspicious_forms(soup) + self._hunt_for_suspicious_meta(soup, request) if aggregated_js_script: aggregated_js_script.close() @@ -2393,7 +2392,7 @@ def _is_script_source(self, script: PageElement) -> bool: """ source_added = False if script.get("src") and script["src"] not in self.initial_script_sources: - if re.match(FULL_URI, script["src"]): + if is_url(script["src"].encode()): if self.gauntlet_runs < 2: self.initial_script_sources.add(script["src"]) else: @@ -3790,7 +3789,7 @@ def _flag_jsxray_iocs(self, output: Dict[str, Any], request: ServiceRequest) -> if safe_str(val) == OBFUSCATOR_IO: run_synchrony = True elif kind == "shady-link": - if not re.match(FULL_URI, val) and not re.match(DOMAIN_ONLY_REGEX, val): + if not is_url(val.encode()) and not is_domain(val.encode()): continue else: add_tag(jsxray_iocs_result_section, "network.static.uri", val, self.safelist) @@ -3870,7 +3869,6 @@ def _extract_malware_jail_iocs(self, output: List[str], request: ServiceRequest) self.log.debug(f"Extracting IOCs from the {MALWARE_JAIL} output...") malware_jail_res_sec = ResultTableSection(f"{MALWARE_JAIL} extracted the following IOCs") - redirection_res_sec: Optional[ResultTextSection] = None for line in self._parse_malwarejail_output(output): split_line = line.split("] ", 1) if len(split_line) == 2: @@ -3943,7 +3941,7 @@ def _extract_malware_jail_iocs(self, output: List[str], request: ServiceRequest) # (it may be truncated, but desperate times call for desperate measures) location_href = "" if not path.exists(self.malware_jail_sandbox_env_dump_path): - matches = re.findall(URI_REGEX, log_line) + matches = list(set([url.value.decode() for url in find_urls(log_line.encode())])) if matches and len(matches) == 2: location_href = matches[1] else: @@ -3984,41 +3982,7 @@ def _extract_malware_jail_iocs(self, output: List[str], request: ServiceRequest) elif isinstance(location_href, dict): continue - if location_href.lower().startswith("ms-msdt:"): - heur = Heuristic(5) - redirection_res_sec = ResultTextSection(heur.name, heuristic=heur, parent=request.result) - - # Try to only recover the msdt command's powershell for the extracted file - # If we can't, write the whole command - try: - encoded_content = self.parse_msdt_powershell(location_href).encode() - except ValueError: - encoded_content = location_href.encode() - - with tempfile.NamedTemporaryFile(dir=self.working_directory, delete=False) as out: - out.write(encoded_content) - artifact = { - "name": sha256(encoded_content).hexdigest(), - "path": out.name, - "description": "Redirection location", - "to_be_extracted": True, - } - self.log.debug(f"Redirection location: {out.name}") - self.artifact_list.append(artifact) - elif not redirection_res_sec: - heur = Heuristic(6) - redirection_res_sec = ResultTextSection(heur.name, heuristic=heur, parent=request.result) - - if not redirection_res_sec.body or ( - redirection_res_sec.body and f"Redirection to:\n{location_href}" not in redirection_res_sec.body - ): - if add_tag(redirection_res_sec, "network.static.uri", location_href, self.safelist): - redirection_res_sec.add_line(f"Redirection to:\n{location_href}") - - if any( - urlparse(decoded_url).netloc in location_href for decoded_url in self.base64_encoded_urls - ): - redirection_res_sec.heuristic.add_signature_id("redirection_to_base64_decoded_url", 500) + self._handle_location_redirection(location_href, request) # Check if programatically created script with src set is found if HTMLELEMENT_SRC_SET_TO_URI in log_line and any( @@ -4036,6 +4000,51 @@ def _extract_malware_jail_iocs(self, output: List[str], request: ServiceRequest) malware_jail_res_sec.set_heuristic(2) request.result.add_section(malware_jail_res_sec) + def _handle_location_redirection(self, location_href: str, request: ServiceRequest): + """ + If a location redirection related to MS-MSDT is seen, handle + If a generic location redirection is seen, handle + :param location_href: The URI that the page is being redirected to + :param request: The ServiceRequest object + """ + redirection_res_sec: Optional[ResultTextSection] = next( + (res for res in request.result.sections if res.heuristic and res.heuristic.heur_id == 6), None + ) + + if location_href.lower().startswith("ms-msdt:"): + heur = Heuristic(5) + redirection_res_sec = ResultTextSection(heur.name, heuristic=heur, parent=request.result) + + # Try to only recover the msdt command's powershell for the extracted file + # If we can't, write the whole command + try: + encoded_content = self.parse_msdt_powershell(location_href).encode() + except ValueError: + encoded_content = location_href.encode() + + with tempfile.NamedTemporaryFile(dir=self.working_directory, delete=False) as out: + out.write(encoded_content) + artifact = { + "name": sha256(encoded_content).hexdigest(), + "path": out.name, + "description": "Redirection location", + "to_be_extracted": True, + } + self.log.debug(f"Redirection location: {out.name}") + self.artifact_list.append(artifact) + elif not redirection_res_sec: + heur = Heuristic(6) + redirection_res_sec = ResultTextSection(heur.name, heuristic=heur, parent=request.result) + + if not redirection_res_sec.body or ( + redirection_res_sec.body and f"Redirection to:\n{location_href}" not in redirection_res_sec.body + ): + if add_tag(redirection_res_sec, "network.static.uri", location_href, self.safelist): + redirection_res_sec.add_line(f"Redirection to:\n{location_href}") + + if any(urlparse(decoded_url).netloc in location_href for decoded_url in self.base64_encoded_urls): + redirection_res_sec.heuristic.add_signature_id("redirection_to_base64_decoded_url", 500) + def _handle_subsequent_scripts(self, result: Result): """ This method handles subsequent script sources, by creating a result section and applying applicable signatures @@ -4496,7 +4505,7 @@ def _hunt_for_suspicious_forms(self, soup: BeautifulSoup) -> None: if not value: continue # https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#attributes_for_form_submission - if key == "action" and re.match(FULL_URI, value): + if key == "action" and is_url(value.encode()): form_has_action = True if self.single_script_with_unescape: # A form with an action was created from a single script that used an unescape AND the form @@ -4523,7 +4532,7 @@ def _hunt_for_suspicious_forms(self, soup: BeautifulSoup) -> None: if not value: continue # https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#action - if key == "formaction" and re.match(FULL_URI, value): + if key == "formaction" and is_url(value.encode()): form_has_action = True if self.single_script_with_unescape: # A form with an action was created from a single script that used an @@ -4538,3 +4547,24 @@ def _hunt_for_suspicious_forms(self, soup: BeautifulSoup) -> None: if not form_has_action: self.password_input_and_no_form_action = True + + def _hunt_for_suspicious_meta(self, soup: BeautifulSoup, request: ServiceRequest) -> None: + """ + This method looks for meta redirects, which are suspicious. + Inspired by https://github.com/sandialabs/laikaboss/blob/8dd2ca17c18d4d0d363d566798720acb7b4d3662/laikaboss/modules/scan_html.py#L264 + :param soup: The BeautifulSoup object + :param request: The ServiceRequest object + :return: None + """ + # https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta + metas = soup.findAll("meta") + + for meta in metas: + # Metadata equivalent to http headers + # https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta#http-equiv + if meta.has_attr("http-equiv"): + if meta.get("http-equiv").lower() == "refresh": + url_data = meta.get("content", "unknown") + urls = list(set([url.value.decode() for url in find_urls(url_data.encode())])) + if urls: + self._handle_location_redirection(urls[0], request) From 62210335fab1d643de9741e33e4d08130ec05209 Mon Sep 17 00:00:00 2001 From: cccs-kevin Date: Thu, 13 Jun 2024 18:59:32 +0000 Subject: [PATCH 7/9] Adding detection for web bugs/beacons --- jsjaws.py | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/jsjaws.py b/jsjaws.py index f68689f5..95fcf199 100755 --- a/jsjaws.py +++ b/jsjaws.py @@ -644,6 +644,8 @@ def __init__(self, config: Optional[Dict] = None) -> None: self.sus_form_actions: Set[str] = set() # Map of scripts found and their corresponding entropies self.script_entropies: Dict[str, Any] = dict() + # The number of web bugs/beacons found in an HTML document + self.num_of_web_bugs = 0 self.log.debug("JsJaws service initialized") def start(self) -> None: @@ -689,6 +691,7 @@ def _reset_execution_variables(self) -> None: self.phishing_inputs = set() self.sus_form_actions = set() self.script_entropies = dict() + self.num_of_web_bugs = 0 def _reset_gauntlet_variables(self, request: ServiceRequest) -> None: """ @@ -1468,6 +1471,10 @@ def _run_the_gauntlet(self, request, file_path, file_content, subsequent_run: bo phishing_inputs_sec.add_line(phishing_inputs_heur.description) phishing_inputs_sec.add_lines([f"\t- {item}" for item in sorted(self.phishing_inputs)]) + if self.num_of_web_bugs: + web_bugs_sec = ResultTextSection("Web bugs found", parent=request.result) + web_bugs_sec.add_lines([f"{self.num_of_web_bugs} web bug(s)/beacon(s) found in document"]) + if self.password_input_and_no_form_action: pass_and_no_action_heur = Heuristic(26) pass_and_no_action_sec = ResultTextSection( @@ -1784,6 +1791,7 @@ def extract_using_soup( self._hunt_for_suspicious_input_fields(soup) self._hunt_for_suspicious_forms(soup) self._hunt_for_suspicious_meta(soup, request) + self._hunt_for_suspicious_images(soup) if aggregated_js_script: aggregated_js_script.close() @@ -4568,3 +4576,44 @@ def _hunt_for_suspicious_meta(self, soup: BeautifulSoup, request: ServiceRequest urls = list(set([url.value.decode() for url in find_urls(url_data.encode())])) if urls: self._handle_location_redirection(urls[0], request) + + def _hunt_for_suspicious_images(self, soup: BeautifulSoup): + """ + This method looks for web bugs, which are suspicious. + Web bug/beacon: https://en.wikipedia.org/wiki/Web_beacon + Inspired by https://github.com/sandialabs/laikaboss/blob/8dd2ca17c18d4d0d363d566798720acb7b4d3662/laikaboss/modules/scan_html.py#L304 + :param soup: The BeautifulSoup object + :return: None + """ + imgs = soup.findAll("img") + + for img in imgs: + d = {} + try: + if img.has_attr("height"): + try: + d["height"] = int(img.get("height")) + except Exception: + try: + d["height"] = img.get("height") + if isinstance(d["height"], str): + d["height"] = d["height"].encode("utf-8") + except Exception: + pass + if img.has_attr("width"): + try: + d["width"] = int(img.get("width")) + except Exception: + try: + d["width"] = img.get("width") + if isinstance(type(d["width"]), str): + d["width"] = d["width"].encode("utf-8") + except Exception: + pass + if "height" in d and "width" in d: + if isinstance(d["height"], int) and isinstance(d["width"], int): + if d["height"] <= 1 and d["width"] <= 1: + self.num_of_web_bugs += 1 + except Exception: + # We don't care that much + pass From e6ad1383a39317dce01f1a5e23ed1278b010c5ff Mon Sep 17 00:00:00 2001 From: cccs-kevin Date: Thu, 13 Jun 2024 19:55:17 +0000 Subject: [PATCH 8/9] Adding short form detection --- jsjaws.py | 9 +++++++++ .../result.json | 8 ++++++-- .../result.json | 8 ++++++-- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/jsjaws.py b/jsjaws.py index 95fcf199..b084a937 100755 --- a/jsjaws.py +++ b/jsjaws.py @@ -646,6 +646,8 @@ def __init__(self, config: Optional[Dict] = None) -> None: self.script_entropies: Dict[str, Any] = dict() # The number of web bugs/beacons found in an HTML document self.num_of_web_bugs = 0 + # Used for heuristic 25, to show that a form exists and that there are a small amount of input elements + self.short_form = False self.log.debug("JsJaws service initialized") def start(self) -> None: @@ -692,6 +694,7 @@ def _reset_execution_variables(self) -> None: self.sus_form_actions = set() self.script_entropies = dict() self.num_of_web_bugs = 0 + self.short_form = False def _reset_gauntlet_variables(self, request: ServiceRequest) -> None: """ @@ -1470,6 +1473,8 @@ def _run_the_gauntlet(self, request, file_path, file_content, subsequent_run: bo ) phishing_inputs_sec.add_line(phishing_inputs_heur.description) phishing_inputs_sec.add_lines([f"\t- {item}" for item in sorted(self.phishing_inputs)]) + if self.short_form: + phishing_inputs_heur.add_signature_id("short_form") if self.num_of_web_bugs: web_bugs_sec = ResultTextSection("Web bugs found", parent=request.result) @@ -4502,6 +4507,10 @@ def _hunt_for_suspicious_forms(self, soup: BeautifulSoup) -> None: break if password_field_exists: + # Inspired by https://github.com/sandialabs/laikaboss/blob/8dd2ca17c18d4d0d363d566798720acb7b4d3662/laikaboss/modules/scan_html.py#L375 + if len(inputs) > 0 and len(inputs) < 4: + self.short_form = True + # If we have a password field, let's look at the form details # https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form forms = soup.findAll("form") diff --git a/tests/results/a822a0ad8bdf6afe197ae4eb4d375f988e30224c4af13e04110e6dcdcd77c836/result.json b/tests/results/a822a0ad8bdf6afe197ae4eb4d375f988e30224c4af13e04110e6dcdcd77c836/result.json index c15fa631..b2604327 100644 --- a/tests/results/a822a0ad8bdf6afe197ae4eb4d375f988e30224c4af13e04110e6dcdcd77c836/result.json +++ b/tests/results/a822a0ad8bdf6afe197ae4eb4d375f988e30224c4af13e04110e6dcdcd77c836/result.json @@ -36,7 +36,9 @@ "heur_id": 25, "score": 100, "score_map": {}, - "signatures": {} + "signatures": { + "short_form": 1 + } }, "promote_to": null, "tags": {}, @@ -986,7 +988,9 @@ { "attack_ids": [], "heur_id": 25, - "signatures": [] + "signatures": [ + "short_form" + ] }, { "attack_ids": [], diff --git a/tests/results/b96949f50cf1cf7e6abe4c3e1d77902e694b1098a57619e68bfe7afb5aa1c19d/result.json b/tests/results/b96949f50cf1cf7e6abe4c3e1d77902e694b1098a57619e68bfe7afb5aa1c19d/result.json index 7b65552f..ad93fd35 100644 --- a/tests/results/b96949f50cf1cf7e6abe4c3e1d77902e694b1098a57619e68bfe7afb5aa1c19d/result.json +++ b/tests/results/b96949f50cf1cf7e6abe4c3e1d77902e694b1098a57619e68bfe7afb5aa1c19d/result.json @@ -56,7 +56,9 @@ "heur_id": 25, "score": 100, "score_map": {}, - "signatures": {} + "signatures": { + "short_form": 1 + } }, "promote_to": null, "tags": {}, @@ -856,7 +858,9 @@ { "attack_ids": [], "heur_id": 25, - "signatures": [] + "signatures": [ + "short_form" + ] }, { "attack_ids": [], From 1497e1a8d9db9303b2aef10470783a4e1026ab1f Mon Sep 17 00:00:00 2001 From: cccs-kevin Date: Thu, 13 Jun 2024 19:55:38 +0000 Subject: [PATCH 9/9] Moving URLSearchParams into the sandbox context --- tools/malwarejail/env/web/web.js | 4 ---- tools/malwarejail/jailme.js | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/tools/malwarejail/env/web/web.js b/tools/malwarejail/env/web/web.js index fa0960c5..a443aad9 100644 --- a/tools/malwarejail/env/web/web.js +++ b/tools/malwarejail/env/web/web.js @@ -6318,10 +6318,6 @@ URLPattern = function () { util_log(">>> FIXME: URLPattern used"); return URLPattern; } -URLSearchParams = function () { - util_log(">>> FIXME: URLSearchParams used"); - return URLSearchParams; -} USB = function () { util_log(">>> FIXME: USB used"); return USB; diff --git a/tools/malwarejail/jailme.js b/tools/malwarejail/jailme.js index e9a53000..921e8213 100644 --- a/tools/malwarejail/jailme.js +++ b/tools/malwarejail/jailme.js @@ -283,6 +283,7 @@ sandbox.TextDecoder = TextDecoder; sandbox.TextDecoderStream = TextDecoderStream; sandbox.TextEncoder = TextEncoder; sandbox.TextEncoderStream = TextEncoderStream; +sandbox.URLSearchParams = URLSearchParams; process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";