From bf887911ea1c402b6671163c27d1b2a944d68688 Mon Sep 17 00:00:00 2001 From: liquidsec Date: Mon, 27 Nov 2023 16:36:37 -0500 Subject: [PATCH 1/2] refining the vstate module and altering reporting behavior slightly --- badsecrets/examples/cli.py | 6 +++--- badsecrets/modules/aspnet_vstate.py | 13 +++++++++---- tests/all_modules_test.py | 21 +++++++++++++++++++++ tests/examples_cli_test.py | 4 ++-- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/badsecrets/examples/cli.py b/badsecrets/examples/cli.py index 6138cf6..e577566 100755 --- a/badsecrets/examples/cli.py +++ b/badsecrets/examples/cli.py @@ -68,13 +68,13 @@ def report(self): elif severity == "INFO": severity_color = Fore.BLUE print_status(f"Severity: {self.x['description']['severity']}", color=severity_color) - print(f"Details: {self.x['details']}") + print(f"Details: {self.x['details']}\n") class ReportIdentify(BaseReport): def report(self): self.print_report( - print_status("Cryptographic Product Identified (no vulnerability)\n", color=Fore.YELLOW, passthru=True) + print_status("Cryptographic Product Identified (no vulnerability, or not confirmed vulnerable)\n", color=Fore.YELLOW, passthru=True) ) if self.x["hashcat"] is not None: print_hashcat_results(self.x["hashcat"]) @@ -117,7 +117,7 @@ def validate_file(file): def print_hashcat_results(hashcat_candidates): print_status("\nPotential matching hashcat commands:\n", color=Fore.YELLOW) for hc in hashcat_candidates: - print(f"Module: [{hc['detecting_module']}] {hc['hashcat_description']} Command: [{hc['hashcat_command']}]") + print(f"Module: [{hc['detecting_module']}] {hc['hashcat_description']} Command: [{hc['hashcat_command']}]\n") def main(): diff --git a/badsecrets/modules/aspnet_vstate.py b/badsecrets/modules/aspnet_vstate.py index 343521d..9aafa8f 100644 --- a/badsecrets/modules/aspnet_vstate.py +++ b/badsecrets/modules/aspnet_vstate.py @@ -3,7 +3,7 @@ from badsecrets.base import BadsecretsBase from badsecrets.modules.aspnet_viewstate import ASPNET_Viewstate -# Reference: https://www.graa.nl/articles/2010.html +# Reference: https://blog.sorcery.ie/posts/higherlogic_rce/ class ASPNET_vstate(BadsecretsBase): @@ -11,7 +11,13 @@ class ASPNET_vstate(BadsecretsBase): description = {"product": "ASP.NET Compressed Vstate", "secret": "unprotected", "severity": "CRITICAL"} def carve_regex(self): - return re.compile(r" + + + +""" + + with requests_mock.Mocker() as m: + m.get( + f"http://multiplevulns.carve-all.badsecrets.com/", + status_code=200, + text=multiple_vuln_html, + ) + + res = requests.get(f"http://multiplevulns.carve-all.badsecrets.com/") + r_list = carve_all_modules(requests_response=res) + assert len(r_list) == 2 \ No newline at end of file diff --git a/tests/examples_cli_test.py b/tests/examples_cli_test.py index 3fe2586..d1b4460 100644 --- a/tests/examples_cli_test.py +++ b/tests/examples_cli_test.py @@ -184,7 +184,7 @@ def test_example_cli_vulnerable_headersidentifyonly(monkeypatch, capsys): "Data Cookie: [session=eyJ1c2VybmFtZSI6IkJib3RJc0xpZmUifQ==] Signature Cookie: [8BrG9wzvqxuPCtKmfgdyXXGGqA7]" in captured.out ) - assert "Cryptographic Product Identified (no vulnerability)" in captured.out + assert "Cryptographic Product Identified (no vulnerability, or not confirmed vulnerable)" in captured.out def test_example_cli_not_vulnerable_url(monkeypatch, capsys): @@ -213,7 +213,7 @@ def test_example_cli_identifyonly_url(monkeypatch, capsys): cli.main() captured = capsys.readouterr() print(captured) - assert "Cryptographic Product Identified (no vulnerability)" in captured.out + assert "Cryptographic Product Identified (no vulnerability, or not confirmed vulnerable)" in captured.out def test_example_cli_identifyonly_hashcat(monkeypatch, capsys): From 1a0579847d57cb0a532b8db87499bcb38167cee3 Mon Sep 17 00:00:00 2001 From: liquidsec Date: Mon, 27 Nov 2023 17:35:23 -0500 Subject: [PATCH 2/2] additional test + black --- badsecrets/examples/cli.py | 6 +++++- badsecrets/modules/aspnet_vstate.py | 2 +- tests/all_modules_test.py | 31 +++++++++++++++++++++++------ 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/badsecrets/examples/cli.py b/badsecrets/examples/cli.py index e577566..2bc1cc4 100755 --- a/badsecrets/examples/cli.py +++ b/badsecrets/examples/cli.py @@ -74,7 +74,11 @@ def report(self): class ReportIdentify(BaseReport): def report(self): self.print_report( - print_status("Cryptographic Product Identified (no vulnerability, or not confirmed vulnerable)\n", color=Fore.YELLOW, passthru=True) + print_status( + "Cryptographic Product Identified (no vulnerability, or not confirmed vulnerable)\n", + color=Fore.YELLOW, + passthru=True, + ) ) if self.x["hashcat"] is not None: print_hashcat_results(self.x["hashcat"]) diff --git a/badsecrets/modules/aspnet_vstate.py b/badsecrets/modules/aspnet_vstate.py index 9aafa8f..b74d028 100644 --- a/badsecrets/modules/aspnet_vstate.py +++ b/badsecrets/modules/aspnet_vstate.py @@ -26,4 +26,4 @@ def check_secret(self, compressed_vstate): uncompressed = self.attempt_decompress(compressed_vstate) if uncompressed and ASPNET_Viewstate.valid_preamble(uncompressed): r = {"source": compressed_vstate, "info": "ASP.NET Vstate (Unprotected, Compressed)"} - return {"secret": "UNPROTECTED (compressed)", "details": r} \ No newline at end of file + return {"secret": "UNPROTECTED (compressed)", "details": r} diff --git a/tests/all_modules_test.py b/tests/all_modules_test.py index 20ac6f0..dfba171 100644 --- a/tests/all_modules_test.py +++ b/tests/all_modules_test.py @@ -126,9 +126,8 @@ def test_carve_all_cookies(): r_list = carve_all_modules(requests_response=res) assert len(r_list) == 7 -def test_carve_multiple_vulns(): - +def test_carve_multiple_vulns(): multiple_vuln_html = """
@@ -138,11 +137,31 @@ def test_carve_multiple_vulns(): with requests_mock.Mocker() as m: m.get( - f"http://multiplevulns.carve-all.badsecrets.com/", - status_code=200, - text=multiple_vuln_html, + f"http://multiplevulns.carve-all.badsecrets.com/", + status_code=200, + text=multiple_vuln_html, ) res = requests.get(f"http://multiplevulns.carve-all.badsecrets.com/") r_list = carve_all_modules(requests_response=res) - assert len(r_list) == 2 \ No newline at end of file + assert len(r_list) == 2 + + +def test_carve_empty_vstate(): + empty_vstate_html = """ +
+ + +""" + + with requests_mock.Mocker() as m: + m.get( + f"http://emptyvstate.carve-all.badsecrets.com/", + status_code=200, + text=empty_vstate_html, + ) + + res = requests.get(f"http://emptyvstate.carve-all.badsecrets.com/") + r_list = carve_all_modules(requests_response=res) + assert r_list + assert r_list[0]["product"] == "EMPTY '__VSTATE' FORM FIELD"