From b128ef87010baaad0dfd072ba1f097854d0b12d2 Mon Sep 17 00:00:00 2001 From: Sebastian Obregoso Date: Wed, 1 Oct 2025 08:34:00 -0300 Subject: [PATCH 1/4] fix test case for api-obfuscation --- tests/analyzer/sourcecode/api-obfuscation.py | 26 ++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/analyzer/sourcecode/api-obfuscation.py b/tests/analyzer/sourcecode/api-obfuscation.py index b9ed13f9..d30b2c66 100644 --- a/tests/analyzer/sourcecode/api-obfuscation.py +++ b/tests/analyzer/sourcecode/api-obfuscation.py @@ -15,19 +15,45 @@ def send(): open(filename, 'wb').write(rq.content) # os.system('start '+filename) + # ruleid: api-obfuscation os.__dict__['startfile']('start '+filename) + + # ruleid: api-obfuscation os.__dict__['startfile'].__call__('start '+filename) + # ruleid: api-obfuscation os.__getattribute__('startfile')('start '+filename) + + # ruleid: api-obfuscation os.__getattribute__('startfile').__call__('start '+filename) + + # ruleid: api-obfuscation getattr(os, 'startfile')('start '+filename) + + # ruleid: api-obfuscation getattr(os, 'startfile').__call__('start '+filename) + + # ruleid: api-obfuscation __import__('os').startfile('start '+filename) + + # ruleid: api-obfuscation __import__('os').startfile.__call__('start '+filename) + + # ruleid: api-obfuscation __import__('os').__dict__['startfile']('start '+filename) + + # ruleid: api-obfuscation __import__('os').__dict__['startfile'].__call__('start '+filename) + + # ruleid: api-obfuscation __import__('os').__getattribute__('startfile')('start '+filename) + + # ruleid: api-obfuscation __import__('os').__getattribute__('startfile').__call__('start '+filename) + + # ruleid: api-obfuscation getattr(__import__('os'), 'startfile')('start '+filename) + + # ruleid: api-obfuscation getattr(__import__('os'), 'startfile').__call__('start '+filename) except: pass From 37d005d62e55feb58eb76546630c84fb8df90b26 Mon Sep 17 00:00:00 2001 From: Sebastian Obregoso Date: Wed, 1 Oct 2025 08:37:58 -0300 Subject: [PATCH 2/4] remove laying around file --- .../extension_powershell_policy_bypass.yar | 12 ------------ tests/analyzer/sourcecode/test_eval_call.js | 10 ---------- 2 files changed, 22 deletions(-) delete mode 100644 guarddog/analyzer/sourcecode/extension_powershell_policy_bypass.yar delete mode 100644 tests/analyzer/sourcecode/test_eval_call.js diff --git a/guarddog/analyzer/sourcecode/extension_powershell_policy_bypass.yar b/guarddog/analyzer/sourcecode/extension_powershell_policy_bypass.yar deleted file mode 100644 index 508df247..00000000 --- a/guarddog/analyzer/sourcecode/extension_powershell_policy_bypass.yar +++ /dev/null @@ -1,12 +0,0 @@ -rule DETECT_FILE_powershell_policy_bypass -{ - meta: - author = "T HAMDOUNI, Datadog" - description = "Detects suspicious read access to /etc/passwd file, which is often targeted by malware for credential harvesting" - - strings: - $cli = /(cat|less|more|head|tail)\s+.{0,100}\/etc\/passwd/ nocase - $read = /(readFile|readFileSync)\(\s*['"]\/etc\/passwd/ nocase - condition: - $cli or $read -} \ No newline at end of file diff --git a/tests/analyzer/sourcecode/test_eval_call.js b/tests/analyzer/sourcecode/test_eval_call.js deleted file mode 100644 index e8b70a68..00000000 --- a/tests/analyzer/sourcecode/test_eval_call.js +++ /dev/null @@ -1,10 +0,0 @@ -const str = `Y29uc29sZS5sb2coJ2hlbGxvIHdvcmxkJyk7`; // console.log('hello world'); -// ruleid: eval-call -eval(atob(str)); - -// ok: eval-call -eval('console.log(\'hello world\');'); - -const str2 = 'console.log(\'hello world\');'; -// ok: eval-call -eval(str2); From 9408388008e632dc6be14307a0655841effe8b86 Mon Sep 17 00:00:00 2001 From: Sebastian Obregoso Date: Wed, 1 Oct 2025 09:25:20 -0300 Subject: [PATCH 3/4] adding test cases --- ...wd_access_linux.yar => suspicious_passwd_access_linux.yar} | 4 ++-- tests/analyzer/sourcecode/suspicious_passwd_access_linux.test | 1 + tests/analyzer/sourcecode/test_sourcecode_yara.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) rename guarddog/analyzer/sourcecode/{extension_suspicious_passwd_access_linux.yar => suspicious_passwd_access_linux.yar} (88%) create mode 100644 tests/analyzer/sourcecode/suspicious_passwd_access_linux.test diff --git a/guarddog/analyzer/sourcecode/extension_suspicious_passwd_access_linux.yar b/guarddog/analyzer/sourcecode/suspicious_passwd_access_linux.yar similarity index 88% rename from guarddog/analyzer/sourcecode/extension_suspicious_passwd_access_linux.yar rename to guarddog/analyzer/sourcecode/suspicious_passwd_access_linux.yar index 72930cb5..9a082518 100644 --- a/guarddog/analyzer/sourcecode/extension_suspicious_passwd_access_linux.yar +++ b/guarddog/analyzer/sourcecode/suspicious_passwd_access_linux.yar @@ -1,4 +1,4 @@ -rule DETECT_FILE_suspicious_passwd_access_linux +rule suspicious_passwd_access_linux { meta: author = "T HAMDOUNI, Datadog" @@ -9,4 +9,4 @@ rule DETECT_FILE_suspicious_passwd_access_linux $read = /(readFile|readFileSync)\(\s*['"]\/etc\/passwd/ nocase condition: $cli or $read -} \ No newline at end of file +} diff --git a/tests/analyzer/sourcecode/suspicious_passwd_access_linux.test b/tests/analyzer/sourcecode/suspicious_passwd_access_linux.test new file mode 100644 index 00000000..7641623e --- /dev/null +++ b/tests/analyzer/sourcecode/suspicious_passwd_access_linux.test @@ -0,0 +1 @@ +cat /etc/passwd diff --git a/tests/analyzer/sourcecode/test_sourcecode_yara.py b/tests/analyzer/sourcecode/test_sourcecode_yara.py index 33b5f025..3f8ced31 100644 --- a/tests/analyzer/sourcecode/test_sourcecode_yara.py +++ b/tests/analyzer/sourcecode/test_sourcecode_yara.py @@ -49,6 +49,6 @@ def test_source_codde_analyzer_yara_exec(rule_name: str): if not f.startswith(f"{rule_name}."): continue - # testing file against against rule + # testing file against rule print(f"Testing YARA rule: {rule_name}") assert test_scan_rule.match(os.path.join(root, f)) From 44b9286536c673b1f9d7a10fdf8498d5a6712c84 Mon Sep 17 00:00:00 2001 From: Sebastian Obregoso Date: Wed, 1 Oct 2025 11:41:59 -0300 Subject: [PATCH 4/4] replacement of pkg_resources with packaging.requirements for parsing requirements files --- guarddog/scanners/pypi_project_scanner.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/guarddog/scanners/pypi_project_scanner.py b/guarddog/scanners/pypi_project_scanner.py index 92d1b20c..050fb89a 100644 --- a/guarddog/scanners/pypi_project_scanner.py +++ b/guarddog/scanners/pypi_project_scanner.py @@ -3,7 +3,7 @@ import re from typing import List -import pkg_resources +from packaging.requirements import Requirement import requests from packaging.specifiers import Specifier, Version @@ -111,12 +111,11 @@ def safe_parse_requirements(req): """ This helper function yields one valid requirement line at a time """ - parsed = pkg_resources.parse_requirements(req) - while True: + for req_line in req: + if not req_line.strip(): + continue try: - yield next(parsed) - except StopIteration: - break + yield Requirement(req_line) except Exception as e: log.error( f"Error when parsing requirements, received error {str(e)}. This entry will be " @@ -130,7 +129,7 @@ def safe_parse_requirements(req): continue versions = get_matched_versions( - find_all_versions(requirement.project_name), + find_all_versions(requirement.name), ( requirement.url if requirement.url @@ -140,7 +139,7 @@ def safe_parse_requirements(req): if len(versions) == 0: log.error( - f"Package/Version {requirement.project_name} not on PyPI\n" + f"Package/Version {requirement.name} not on PyPI\n" ) continue @@ -165,13 +164,13 @@ def safe_parse_requirements(req): # find the dep with the same name or create a new one dep = next( filter( - lambda d: d.name == requirement.project_name, + lambda d: d.name == requirement.name, dependencies, ), None, ) if not dep: - dep = Dependency(name=requirement.project_name, versions=set()) + dep = Dependency(name=requirement.name, versions=set()) dependencies.append(dep) dep.versions.update(dep_versions)