diff --git a/README.md b/README.md index dc229bd..aa8d2f2 100644 --- a/README.md +++ b/README.md @@ -242,18 +242,9 @@ Secret: fake123 Details: {'sub': '1234567890', 'name': 'John Doe', 'iat': 1516239022, 'jwt_headers': {'alg': 'HS256', 'typ': 'JWT'}} ``` -### blacklist3r.py +### blacklist3r.py (removed) -*Note: This is now obsolete, since `cli.py` is now capable of handling machinekeys/generator values. It will remain included for reference.* -*Example: `badsecrets KLox5XeGYfb7Lo8zFzr1YepUagXuixcxX55lpFht+rrW6VGheZi831vdusH6DCMfxIhsLG1EPU3OuPvqN2XBc/fj0ew15TQ1zBmmKWJVns4= AAAAAAAA`* - -Bad secrets includes a [fully functional CLI example](https://github.com/blacklanternsecurity/badsecrets/blob/dev/badsecrets/examples/blacklist3r.py) which replicates the functionality of [blacklist3r](https://github.com/NotSoSecure/Blacklist3r) in python badsecrets/examples/blacklist3r. - - -```bash -python ./badsecrets/examples/blacklist3r.py --url http://vulnerablesite/vulnerablepage.aspx -python ./badsecrets/examples/blacklist3r.py --viewstate /wEPDwUJODExMDE5NzY5ZGQMKS6jehX5HkJgXxrPh09vumNTKQ== --generator EDD8C9AE -``` +The standalone `blacklist3r.py` tool has been **deprecated and removed**. The capabilities in the main badsecrets viewstate modules now far surpass what the standalone tool offered, and it had become a maintenance burden. Use the main `badsecrets` CLI (or the `aspnet_viewstate` module directly) for ASP.NET viewstate / machine key analysis. ### telerik_knownkey.py diff --git a/badsecrets/examples/blacklist3r.py b/badsecrets/examples/blacklist3r.py deleted file mode 100755 index b6b5f5b..0000000 --- a/badsecrets/examples/blacklist3r.py +++ /dev/null @@ -1,149 +0,0 @@ -#!/usr/bin/env python3 -# badsecrets - python 'blacklist3r' tool -# Inspired by blacklist3r - https://github.com/NotSoSecure/Blacklist3r\n") -# Black Lantern Security - https://www.blacklanternsecurity.com") -# @paulmmueller - -import re -import os -import sys -import asyncio -import argparse -import urllib.parse - -from blasthttp import BlastHTTP - -SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) -sys.path.append(os.path.dirname(SCRIPT_DIR)) - -from badsecrets import modules_loaded - -ASPNET_Viewstate = modules_loaded["aspnet_viewstate"] - - -def check_viewstate(viewstate, generator): - bs_vs = ASPNET_Viewstate() - r = bs_vs.check_secret(viewstate, generator) - return r - - -def print_result(r): - print("Matching MachineKeys found!") - print(r["secret"]) - - -def validate_viewstate(arg_value, pattern=re.compile(r"^(?:[A-Za-z0-9+\/=%]+)$")): - if not pattern.match(arg_value): - raise argparse.ArgumentTypeError("Viewstate is not formatted correctly") - return arg_value - - -def validate_generator(arg_value, pattern=re.compile(r"^(?:[A-Fa-f0-9]+)$")): - if not pattern.match(arg_value): - raise argparse.ArgumentTypeError("Generator is not formatted correctly") - return arg_value - - -def validate_url( - arg_value, - pattern=re.compile( - r"^https?://((?:[A-Z0-9_]|[A-Z0-9_][A-Z0-9\-_]*[A-Z0-9_])[\.]?)+(?:[A-Z0-9_][A-Z0-9\-_]*[A-Z0-9_]|[A-Z0-9_])(?::[0-9]{1,5})?.*$", - re.IGNORECASE, - ), -): - if not pattern.match(arg_value): - raise argparse.ArgumentTypeError("URL is not formatted correctly") - return arg_value - - -def main(): - viewstate = None - generator = "0000" - - generator_regex = re.compile(r' - - - Untitled Page - - -
-
- -
- -
- - - -
-
- test -
-
- - -""" - -vulnerable_viewstate = ( - "o6oVz97xjF/9t1+trA4X4xBFcTnk9bFXqzCNksR5PszHkTScHA/onlBaTUX0tEiHyZX18kIGkuiNoJBmzaGmjEqNsiJuIxrBRjT52D+DEWM7n6d+" -) - -non_vulnerable_viewstate = ( - "BADsecrets/9t1+trA4X4xBFcTnk9bFXqzCNksR5PszHkTScHA/onlBaTUX0tEiHyZX18kIGkuiNoJBmzaGmjEqNsiJuIxrBRjT52D+DEWM7n6d+" -) - -no_viewstate_page = "Just a website" - - -def test_examples_blacklist3r_manual(monkeypatch, capsys): - # Valid Viewstate Unencrypted W/Generator - monkeypatch.setattr( - "sys.argv", - [ - "python", - "--viewstate", - "/wEPDwUJODExMDE5NzY5ZGSglOSr1rG6xN5rzh/4C9UEuwa64w==", - "--generator", - "EDD8C9AE", - ], - ) - blacklist3r.main() - captured = capsys.readouterr() - assert "Matching MachineKeys found!" in captured.out - assert ( - "F5144F1A581A57BA3B60311AF7562A855998F7DD203CD8A71405599B980D8694B5C986C888BE4FC0E6571C2CE600D58CE82B8FA13106B17D77EA4CECDDBBEC1B" - in captured.out - ) - assert "validationAlgo: SHA1" in captured.out - - # Valid Viewstate Encrypted - monkeypatch.setattr( - "sys.argv", - [ - "python", - "--viewstate", - "dn/WEP+ogagnOcePgsXoPRe05wss0YIyAZdzFHJuWJejTRbDNDEqes7fBwNY4IqTmT7kTB0o9f8fRSpRXaMcyg==", - ], - ) - blacklist3r.main() - captured = capsys.readouterr() - assert "Matching MachineKeys found!" in captured.out - assert ( - "F5144F1A581A57BA3B60311AF7562A855998F7DD203CD8A71405599B980D8694B5C986C888BE4FC0E6571C2CE600D58CE82B8FA13106B17D77EA4CECDDBBEC1B" - in captured.out - ) - assert "encryptionAlgo: DES" in captured.out - - # Invalid viewstate is Rejected - monkeypatch.setattr( - "sys.argv", - [ - "python", - "--viewstate", - "/wEPDwUJODExMDE5NzY5ZGSglOSr1rG6xN4rzh/4C9UEuwa64w==", - "--generator", - "EDD8C9AE", - ], - ) - blacklist3r.main() - captured = capsys.readouterr() - assert "Matching MachineKeys NOT found" in captured.out - - # Invalid generator is rejected - monkeypatch.setattr( - "sys.argv", - [ - "python", - "--viewstate", - "/wEPDwUJODExMDE5NzY5ZGSglOSr1rG6xN5rzh/4C9UEuwa64w==", - "--generator", - "^INVALID^", - ], - ) - with patch("sys.exit") as exit_mock: - blacklist3r.main() - assert exit_mock.called - captured = capsys.readouterr() - assert "Generator is not formatted correctly" in captured.err - - # Viewstate doesn't match pattern and is rejected - with patch("sys.exit") as exit_mock: - monkeypatch.setattr( - "sys.argv", - [ - "python", - "--viewstate", - "^INVALID^", - "--generator", - "EDD8C9AE", - ], - ) - blacklist3r.main() - captured = capsys.readouterr() - assert "Viewstate is not formatted correctly" in captured.err - - -def test_examples_blacklist3r_offline(monkeypatch, capsys, bh_mock): - with patch("sys.exit") as exit_mock: - # Invalid URL is rejected - monkeypatch.setattr("sys.argv", ["python", "--url", "hxxp://notaurl"]) - blacklist3r.main() - assert exit_mock.called - captured = capsys.readouterr() - assert "error: One of --url or --viewstate is required" in captured.err - - with patch("sys.exit") as exit_mock: - # Both URL and viewstate are supplied - rejected appropriately - monkeypatch.setattr( - "sys.argv", - [ - "python", - "--url", - "http://example.com", - "--viewstate", - "dn/WEP+ogagnOcePgsXoPRe05wss0YIyAZdzFHJuWJejTRbDNDEqes7fBwNY4IqTmT7kTB0o9f8fRSpRXaMcyg==", - ], - ) - blacklist3r.main() - assert exit_mock.called - captured = capsys.readouterr() - assert "error: --viewstate/--generator options and --url option are mutually exclusive" in captured.err - - bh_mock.add_response( - url="http://example.com/vulnerableviewstate.aspx", - text=base_viewstate_page.replace("###viewstate###", vulnerable_viewstate), - status_code=200, - ) - bh_mock.add_response( - url="http://example.com/nonvulnerableviewstate.aspx", - text=base_viewstate_page.replace("###viewstate###", non_vulnerable_viewstate), - status_code=200, - ) - bh_mock.add_response(url="http://example.com/noviewstate.aspx", text=no_viewstate_page, status_code=200) - - def _err(req): - raise RuntimeError("timeout") - - bh_mock.add_callback(_err, url="http://notreal.com/") - - # URL Mode - Valid URL is visited, contains viewstate, viewstate is vulnerable - monkeypatch.setattr("sys.argv", ["python", "--url", "http://example.com/vulnerableviewstate.aspx"]) - blacklist3r.main() - captured = capsys.readouterr() - assert "Matching MachineKeys found!" in captured.out - assert ( - "F4F0AC3A8889DFBB6FC9D24275A8F0E523C1FB1A2F3FA0C3F3B36320A80670E1D62D15A16A335F0CB14F8AECE7002A5BD8A980F677EA82666B49167947F0A669" - in captured.out - ) - assert "encryptionAlgo: AES" in captured.out - - # URL Mode - Valid URL is visited, contains viewstate, viewstate is NOT vulnerable - monkeypatch.setattr("sys.argv", ["python", "--url", "http://example.com/nonvulnerableviewstate.aspx"]) - blacklist3r.main() - captured2 = capsys.readouterr() - assert "Matching MachineKeys NOT found" in captured2.out - - # URL Mode - Valid URL is visited, does not contain viewstate - monkeypatch.setattr("sys.argv", ["python", "--url", "http://example.com/noviewstate.aspx"]) - blacklist3r.main() - captured2 = capsys.readouterr() - assert "Did not find viewstate in repsonse from URL" in captured2.out - - # URL Mode - Validly formatted URL is not responding - monkeypatch.setattr("sys.argv", ["python", "--url", "http://notreal.com"]) - blacklist3r.main() - captured2 = capsys.readouterr() - assert "Error connecting to URL" in captured2.out