bbot 2.6.0.6840rc0__py3-none-any.whl → 2.7.2.7424rc0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bbot/__init__.py +1 -1
- bbot/cli.py +22 -8
- bbot/core/engine.py +1 -1
- bbot/core/event/__init__.py +2 -2
- bbot/core/event/base.py +138 -110
- bbot/core/flags.py +1 -0
- bbot/core/helpers/bloom.py +6 -7
- bbot/core/helpers/depsinstaller/installer.py +21 -2
- bbot/core/helpers/dns/dns.py +0 -1
- bbot/core/helpers/dns/engine.py +0 -2
- bbot/core/helpers/files.py +2 -2
- bbot/core/helpers/git.py +17 -0
- bbot/core/helpers/helper.py +6 -5
- bbot/core/helpers/misc.py +8 -23
- bbot/core/helpers/ntlm.py +0 -2
- bbot/core/helpers/regex.py +1 -1
- bbot/core/helpers/regexes.py +25 -8
- bbot/core/helpers/web/web.py +2 -1
- bbot/core/modules.py +22 -60
- bbot/defaults.yml +4 -2
- bbot/modules/apkpure.py +1 -1
- bbot/modules/baddns.py +1 -1
- bbot/modules/baddns_direct.py +1 -1
- bbot/modules/baddns_zone.py +1 -1
- bbot/modules/badsecrets.py +1 -1
- bbot/modules/base.py +123 -38
- bbot/modules/bucket_amazon.py +1 -1
- bbot/modules/bucket_digitalocean.py +1 -1
- bbot/modules/bucket_firebase.py +1 -1
- bbot/modules/bucket_google.py +1 -1
- bbot/modules/{bucket_azure.py → bucket_microsoft.py} +2 -2
- bbot/modules/builtwith.py +4 -2
- bbot/modules/dnsbimi.py +1 -4
- bbot/modules/dnsbrute.py +6 -1
- bbot/modules/dnsdumpster.py +35 -52
- bbot/modules/dnstlsrpt.py +0 -6
- bbot/modules/docker_pull.py +1 -1
- bbot/modules/emailformat.py +17 -1
- bbot/modules/ffuf.py +4 -1
- bbot/modules/ffuf_shortnames.py +6 -3
- bbot/modules/filedownload.py +7 -4
- bbot/modules/git_clone.py +47 -22
- bbot/modules/gitdumper.py +4 -14
- bbot/modules/github_workflows.py +6 -5
- bbot/modules/gitlab_com.py +31 -0
- bbot/modules/gitlab_onprem.py +84 -0
- bbot/modules/gowitness.py +0 -6
- bbot/modules/graphql_introspection.py +5 -2
- bbot/modules/httpx.py +2 -0
- bbot/modules/iis_shortnames.py +0 -7
- bbot/modules/internal/cloudcheck.py +65 -72
- bbot/modules/internal/unarchive.py +9 -3
- bbot/modules/lightfuzz/lightfuzz.py +6 -2
- bbot/modules/lightfuzz/submodules/esi.py +42 -0
- bbot/modules/medusa.py +4 -7
- bbot/modules/nuclei.py +1 -1
- bbot/modules/otx.py +9 -2
- bbot/modules/output/base.py +3 -11
- bbot/modules/paramminer_headers.py +10 -7
- bbot/modules/portfilter.py +2 -0
- bbot/modules/postman_download.py +1 -1
- bbot/modules/retirejs.py +232 -0
- bbot/modules/securitytxt.py +0 -3
- bbot/modules/sslcert.py +2 -2
- bbot/modules/subdomaincenter.py +1 -16
- bbot/modules/telerik.py +7 -2
- bbot/modules/templates/bucket.py +24 -4
- bbot/modules/templates/gitlab.py +98 -0
- bbot/modules/trufflehog.py +6 -3
- bbot/modules/wafw00f.py +2 -2
- bbot/presets/web/lightfuzz-heavy.yml +1 -1
- bbot/presets/web/lightfuzz-medium.yml +1 -1
- bbot/presets/web/lightfuzz-superheavy.yml +1 -1
- bbot/scanner/manager.py +44 -37
- bbot/scanner/scanner.py +12 -4
- bbot/scripts/benchmark_report.py +433 -0
- bbot/test/benchmarks/__init__.py +2 -0
- bbot/test/benchmarks/test_bloom_filter_benchmarks.py +105 -0
- bbot/test/benchmarks/test_closest_match_benchmarks.py +76 -0
- bbot/test/benchmarks/test_event_validation_benchmarks.py +438 -0
- bbot/test/benchmarks/test_excavate_benchmarks.py +291 -0
- bbot/test/benchmarks/test_ipaddress_benchmarks.py +143 -0
- bbot/test/benchmarks/test_weighted_shuffle_benchmarks.py +70 -0
- bbot/test/test_step_1/test_bbot_fastapi.py +2 -2
- bbot/test/test_step_1/test_events.py +22 -21
- bbot/test/test_step_1/test_helpers.py +1 -0
- bbot/test/test_step_1/test_manager_scope_accuracy.py +45 -0
- bbot/test/test_step_1/test_modules_basic.py +40 -15
- bbot/test/test_step_1/test_python_api.py +2 -2
- bbot/test/test_step_1/test_regexes.py +21 -4
- bbot/test/test_step_1/test_scan.py +7 -8
- bbot/test/test_step_1/test_web.py +46 -0
- bbot/test/test_step_2/module_tests/base.py +6 -1
- bbot/test/test_step_2/module_tests/test_module_bucket_amazon.py +52 -18
- bbot/test/test_step_2/module_tests/test_module_bucket_google.py +1 -1
- bbot/test/test_step_2/module_tests/{test_module_bucket_azure.py → test_module_bucket_microsoft.py} +7 -5
- bbot/test/test_step_2/module_tests/test_module_cloudcheck.py +19 -31
- bbot/test/test_step_2/module_tests/test_module_dnsbimi.py +2 -1
- bbot/test/test_step_2/module_tests/test_module_dnsdumpster.py +3 -5
- bbot/test/test_step_2/module_tests/test_module_emailformat.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_emails.py +2 -2
- bbot/test/test_step_2/module_tests/test_module_excavate.py +57 -4
- bbot/test/test_step_2/module_tests/test_module_github_workflows.py +10 -1
- bbot/test/test_step_2/module_tests/test_module_gitlab_com.py +66 -0
- bbot/test/test_step_2/module_tests/{test_module_gitlab.py → test_module_gitlab_onprem.py} +4 -69
- bbot/test/test_step_2/module_tests/test_module_lightfuzz.py +71 -3
- bbot/test/test_step_2/module_tests/test_module_nuclei.py +1 -2
- bbot/test/test_step_2/module_tests/test_module_otx.py +3 -0
- bbot/test/test_step_2/module_tests/test_module_portfilter.py +2 -0
- bbot/test/test_step_2/module_tests/test_module_retirejs.py +161 -0
- bbot/test/test_step_2/module_tests/test_module_telerik.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_trufflehog.py +10 -1
- {bbot-2.6.0.6840rc0.dist-info → bbot-2.7.2.7424rc0.dist-info}/METADATA +10 -7
- {bbot-2.6.0.6840rc0.dist-info → bbot-2.7.2.7424rc0.dist-info}/RECORD +117 -106
- {bbot-2.6.0.6840rc0.dist-info → bbot-2.7.2.7424rc0.dist-info}/WHEEL +1 -1
- {bbot-2.6.0.6840rc0.dist-info → bbot-2.7.2.7424rc0.dist-info/licenses}/LICENSE +98 -58
- bbot/modules/censys.py +0 -98
- bbot/modules/gitlab.py +0 -141
- bbot/modules/zoomeye.py +0 -77
- bbot/test/test_step_2/module_tests/test_module_censys.py +0 -83
- bbot/test/test_step_2/module_tests/test_module_zoomeye.py +0 -35
- {bbot-2.6.0.6840rc0.dist-info → bbot-2.7.2.7424rc0.dist-info}/entry_points.txt +0 -0
|
@@ -608,7 +608,7 @@ class Test_Lightfuzz_urlencoding(Test_Lightfuzz_xss_injs):
|
|
|
608
608
|
"interactsh_disable": True,
|
|
609
609
|
"modules": {
|
|
610
610
|
"lightfuzz": {
|
|
611
|
-
"enabled_submodules": ["cmdi", "crypto", "path", "serial", "sqli", "ssti", "xss"],
|
|
611
|
+
"enabled_submodules": ["cmdi", "crypto", "path", "serial", "sqli", "ssti", "xss", "esi"],
|
|
612
612
|
}
|
|
613
613
|
},
|
|
614
614
|
}
|
|
@@ -1723,7 +1723,7 @@ class Test_Lightfuzz_XSS_jsquotecontext(ModuleTestBase):
|
|
|
1723
1723
|
input_value = param.split("=")[1]
|
|
1724
1724
|
break
|
|
1725
1725
|
|
|
1726
|
-
if input_value:
|
|
1726
|
+
if input_value is not None:
|
|
1727
1727
|
# Simulate flawed escaping
|
|
1728
1728
|
sanitized_input = input_value.replace('"', '\\"').replace("'", "\\'")
|
|
1729
1729
|
sanitized_input = sanitized_input.replace("<", "%3C").replace(">", "%3E")
|
|
@@ -1786,7 +1786,7 @@ class Test_Lightfuzz_XSS_jsquotecontext_doublequote(Test_Lightfuzz_XSS_jsquoteco
|
|
|
1786
1786
|
input_value = param.split("=")[1]
|
|
1787
1787
|
break
|
|
1788
1788
|
|
|
1789
|
-
if input_value:
|
|
1789
|
+
if input_value is not None:
|
|
1790
1790
|
# Simulate flawed escaping with opposite quotes
|
|
1791
1791
|
sanitized_input = input_value.replace("'", "\\").replace("%22", '\\"')
|
|
1792
1792
|
sanitized_input = sanitized_input.replace("<", "%3C").replace(">", "%3E")
|
|
@@ -1817,3 +1817,71 @@ class Test_Lightfuzz_XSS_jsquotecontext_doublequote(Test_Lightfuzz_XSS_jsquoteco
|
|
|
1817
1817
|
|
|
1818
1818
|
assert web_parameter_emitted, "WEB_PARAMETER for was not emitted"
|
|
1819
1819
|
assert xss_finding_emitted, "XSS FINDING not emitted"
|
|
1820
|
+
|
|
1821
|
+
|
|
1822
|
+
class Test_Lightfuzz_esi(ModuleTestBase):
|
|
1823
|
+
targets = ["http://127.0.0.1:8888"]
|
|
1824
|
+
modules_overrides = ["httpx", "lightfuzz", "excavate"]
|
|
1825
|
+
config_overrides = {
|
|
1826
|
+
"interactsh_disable": True,
|
|
1827
|
+
"modules": {
|
|
1828
|
+
"lightfuzz": {
|
|
1829
|
+
"enabled_submodules": ["esi"],
|
|
1830
|
+
}
|
|
1831
|
+
},
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
def request_handler(self, request):
|
|
1835
|
+
qs = str(request.query_string.decode())
|
|
1836
|
+
|
|
1837
|
+
parameter_block = """
|
|
1838
|
+
<section class=search>
|
|
1839
|
+
<form action=/ method=GET>
|
|
1840
|
+
<input type=text placeholder='Search...' name=search>
|
|
1841
|
+
<button type=submit class=button>Search</button>
|
|
1842
|
+
</form>
|
|
1843
|
+
</section>
|
|
1844
|
+
"""
|
|
1845
|
+
if "search=" in qs:
|
|
1846
|
+
value = qs.split("=")[1]
|
|
1847
|
+
if "&" in value:
|
|
1848
|
+
value = value.split("&")[0]
|
|
1849
|
+
# Decode the URL-encoded value
|
|
1850
|
+
decoded_value = unquote(value)
|
|
1851
|
+
# Simulate ESI processing: if the payload contains <!--esi-->, remove it
|
|
1852
|
+
if "<!--esi-->" in decoded_value:
|
|
1853
|
+
# ESI processor removes <!--esi--> tag, leaving the rest
|
|
1854
|
+
processed_value = decoded_value.replace("<!--esi-->", "")
|
|
1855
|
+
else:
|
|
1856
|
+
# For non-ESI payloads, just reflect the value as-is
|
|
1857
|
+
processed_value = decoded_value
|
|
1858
|
+
|
|
1859
|
+
esi_block = f"""
|
|
1860
|
+
<section class=blog-header>
|
|
1861
|
+
<h1>Search results for '{processed_value}'</h1>
|
|
1862
|
+
<hr>
|
|
1863
|
+
</section>
|
|
1864
|
+
"""
|
|
1865
|
+
return Response(esi_block, status=200)
|
|
1866
|
+
|
|
1867
|
+
return Response(parameter_block, status=200)
|
|
1868
|
+
|
|
1869
|
+
async def setup_after_prep(self, module_test):
|
|
1870
|
+
expect_args = re.compile("/")
|
|
1871
|
+
module_test.set_expect_requests_handler(expect_args=expect_args, request_handler=self.request_handler)
|
|
1872
|
+
|
|
1873
|
+
def check(self, module_test, events):
|
|
1874
|
+
web_parameter_emitted = False
|
|
1875
|
+
esi_finding_emitted = False
|
|
1876
|
+
|
|
1877
|
+
for e in events:
|
|
1878
|
+
if e.type == "WEB_PARAMETER":
|
|
1879
|
+
if "HTTP Extracted Parameter [search]" in e.data["description"]:
|
|
1880
|
+
web_parameter_emitted = True
|
|
1881
|
+
|
|
1882
|
+
if e.type == "FINDING":
|
|
1883
|
+
if "Edge Side Include. Parameter: [search] Parameter Type: [GETPARAM]" in e.data["description"]:
|
|
1884
|
+
esi_finding_emitted = True
|
|
1885
|
+
|
|
1886
|
+
assert web_parameter_emitted, "WEB_PARAMETER was not emitted"
|
|
1887
|
+
assert esi_finding_emitted, "ESI FINDING not emitted"
|
|
@@ -12,7 +12,6 @@ class TestNucleiManual(ModuleTestBase):
|
|
|
12
12
|
},
|
|
13
13
|
"modules": {
|
|
14
14
|
"nuclei": {
|
|
15
|
-
"version": "2.9.4",
|
|
16
15
|
"mode": "manual",
|
|
17
16
|
"concurrency": 2,
|
|
18
17
|
"ratelimit": 10,
|
|
@@ -67,7 +66,7 @@ class TestNucleiSevere(TestNucleiManual):
|
|
|
67
66
|
"nuclei": {
|
|
68
67
|
"mode": "severe",
|
|
69
68
|
"concurrency": 1,
|
|
70
|
-
"templates": "/tmp/.bbot_test/tools/nuclei-templates/vulnerabilities/generic/generic-env.yaml",
|
|
69
|
+
"templates": "/tmp/.bbot_test/tools/nuclei-templates/http/vulnerabilities/generic/generic-env.yaml",
|
|
71
70
|
}
|
|
72
71
|
},
|
|
73
72
|
"interactsh_disable": True,
|
|
@@ -2,6 +2,8 @@ from .base import ModuleTestBase
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class TestOTX(ModuleTestBase):
|
|
5
|
+
config_overrides = {"modules": {"otx": {"api_key": "test"}}}
|
|
6
|
+
|
|
5
7
|
async def setup_after_prep(self, module_test):
|
|
6
8
|
module_test.httpx_mock.add_response(
|
|
7
9
|
url="https://otx.alienvault.com/api/v1/indicators/domain/blacklanternsecurity.com/passive_dns",
|
|
@@ -21,6 +23,7 @@ class TestOTX(ModuleTestBase):
|
|
|
21
23
|
}
|
|
22
24
|
]
|
|
23
25
|
},
|
|
26
|
+
headers={"X-OTX-API-KEY": "test"},
|
|
24
27
|
)
|
|
25
28
|
|
|
26
29
|
def check(self, module_test, events):
|
|
@@ -43,6 +43,8 @@ class TestPortfilter_enabled(TestPortfilter_disabled):
|
|
|
43
43
|
modules_overrides = ["portfilter"]
|
|
44
44
|
|
|
45
45
|
def check(self, module_test, events):
|
|
46
|
+
# even though portfilter listens for URLs, enabling it should not automatically enable httpx
|
|
47
|
+
assert "httpx" not in module_test.scan.modules
|
|
46
48
|
open_ports = {event.data for event in events if event.type == "OPEN_TCP_PORT"}
|
|
47
49
|
# we should be missing the 8080 port because it's a CDN and not in portfilter's allowed list of open ports
|
|
48
50
|
assert open_ports == {"www.blacklanternsecurity.com:443", "www.blacklanternsecurity.com:21"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
from .base import ModuleTestBase
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class TestRetireJS(ModuleTestBase):
|
|
5
|
+
targets = ["http://127.0.0.1:8888"]
|
|
6
|
+
modules_overrides = ["httpx", "excavate", "retirejs"]
|
|
7
|
+
|
|
8
|
+
# HTML page with vulnerable JavaScript libraries
|
|
9
|
+
vulnerable_html = """<!doctype html>
|
|
10
|
+
<html lang="en">
|
|
11
|
+
<head>
|
|
12
|
+
<meta charset="utf-8" />
|
|
13
|
+
<title>retire.js test page</title>
|
|
14
|
+
</head>
|
|
15
|
+
<body>
|
|
16
|
+
<h1>retire.js test page</h1>
|
|
17
|
+
<p>This page includes JavaScript libraries for testing.</p>
|
|
18
|
+
|
|
19
|
+
<!-- jQuery 3.4.1 -->
|
|
20
|
+
<script src="/jquery-3.4.1.min.js"></script>
|
|
21
|
+
|
|
22
|
+
<!-- Lodash 4.17.11 -->
|
|
23
|
+
<script src="/lodash.min.js"></script>
|
|
24
|
+
|
|
25
|
+
<!-- Handlebars 4.0.5 -->
|
|
26
|
+
<script src="/handlebars.min.js"></script>
|
|
27
|
+
|
|
28
|
+
<script>
|
|
29
|
+
console.log('Libraries loaded');
|
|
30
|
+
</script>
|
|
31
|
+
</body>
|
|
32
|
+
</html>"""
|
|
33
|
+
|
|
34
|
+
# Sample jQuery 3.4.1 content
|
|
35
|
+
jquery_content = """/*!
|
|
36
|
+
* jQuery JavaScript Library v3.4.1
|
|
37
|
+
* https://jquery.com/
|
|
38
|
+
*/
|
|
39
|
+
(function( global, factory ) {
|
|
40
|
+
"use strict";
|
|
41
|
+
factory( global );
|
|
42
|
+
})(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
|
|
43
|
+
var jQuery = function( selector, context ) {
|
|
44
|
+
return new jQuery.fn.init( selector, context );
|
|
45
|
+
};
|
|
46
|
+
jQuery.fn = jQuery.prototype = {};
|
|
47
|
+
jQuery.fn.jquery = "3.4.1";
|
|
48
|
+
if ( typeof noGlobal === "undefined" ) {
|
|
49
|
+
window.jQuery = window.$ = jQuery;
|
|
50
|
+
}
|
|
51
|
+
return jQuery;
|
|
52
|
+
});"""
|
|
53
|
+
|
|
54
|
+
# Sample Lodash 4.17.11 content
|
|
55
|
+
lodash_content = """/**
|
|
56
|
+
* @license
|
|
57
|
+
* Lodash lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
|
|
58
|
+
*/
|
|
59
|
+
;(function(){
|
|
60
|
+
var i="4.17.11";
|
|
61
|
+
var Mn={VERSION:i};
|
|
62
|
+
if(typeof define=="function"&&define.amd)define(function(){return Mn});else if(typeof module=="object"&&module.exports)module.exports=Mn;else this._=Mn}());"""
|
|
63
|
+
|
|
64
|
+
# Sample Handlebars 4.0.5 content
|
|
65
|
+
handlebars_content = """/*!
|
|
66
|
+
handlebars v4.0.5
|
|
67
|
+
*/
|
|
68
|
+
!function(a,b){"object"==typeof exports&&"object"==typeof module?module.exports=b():"function"==typeof define&&define.amd?define([],b):"object"==typeof exports?exports.Handlebars=b():a.Handlebars=b()}(this,function(){
|
|
69
|
+
var Handlebars={};
|
|
70
|
+
Handlebars.VERSION="4.0.5";
|
|
71
|
+
return Handlebars;
|
|
72
|
+
});"""
|
|
73
|
+
|
|
74
|
+
async def setup_after_prep(self, module_test):
|
|
75
|
+
expect_args = {"uri": "/"}
|
|
76
|
+
respond_args = {"response_data": self.vulnerable_html}
|
|
77
|
+
module_test.set_expect_requests(expect_args, respond_args)
|
|
78
|
+
|
|
79
|
+
expect_args = {"uri": "/jquery-3.4.1.min.js"}
|
|
80
|
+
respond_args = {"response_data": self.jquery_content}
|
|
81
|
+
module_test.set_expect_requests(expect_args, respond_args)
|
|
82
|
+
|
|
83
|
+
expect_args = {"uri": "/lodash.min.js"}
|
|
84
|
+
respond_args = {"response_data": self.lodash_content}
|
|
85
|
+
module_test.set_expect_requests(expect_args, respond_args)
|
|
86
|
+
|
|
87
|
+
expect_args = {"uri": "/handlebars.min.js"}
|
|
88
|
+
respond_args = {"response_data": self.handlebars_content}
|
|
89
|
+
module_test.set_expect_requests(expect_args, respond_args)
|
|
90
|
+
|
|
91
|
+
def check(self, module_test, events):
|
|
92
|
+
# Check that excavate found the JavaScript URLs
|
|
93
|
+
url_unverified_events = [e for e in events if e.type == "URL_UNVERIFIED"]
|
|
94
|
+
js_url_events = [e for e in url_unverified_events if "extension-js" in e.tags]
|
|
95
|
+
|
|
96
|
+
# Two out of the three URLs should be in the output
|
|
97
|
+
# The third, non-vulnerable URL (lodash.min.js) is not output because it's a "special URL", and
|
|
98
|
+
# nothing interesting has been discovered from it.
|
|
99
|
+
vuln_urls = {"http://127.0.0.1:8888/handlebars.min.js", "http://127.0.0.1:8888/jquery-3.4.1.min.js"}
|
|
100
|
+
assert {e.data for e in js_url_events} == vuln_urls, "Expected to find the vulnerable URLs in the output"
|
|
101
|
+
|
|
102
|
+
# Check for FINDING events generated by retirejs
|
|
103
|
+
finding_events = [e for e in events if e.type == "FINDING"]
|
|
104
|
+
retirejs_findings = [
|
|
105
|
+
e
|
|
106
|
+
for e in finding_events
|
|
107
|
+
if "vulnerable javascript library detected:" in e.data.get("description", "").lower()
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
# We should have at least some findings from our vulnerable libraries
|
|
111
|
+
assert len(retirejs_findings) > 0, (
|
|
112
|
+
f"Expected retirejs to find vulnerabilities, but got {len(retirejs_findings)} findings"
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# Check for specific expected vulnerability descriptions
|
|
116
|
+
descriptions = [finding.data.get("description", "") for finding in retirejs_findings]
|
|
117
|
+
all_descriptions = "\n".join(descriptions)
|
|
118
|
+
|
|
119
|
+
# Look for specific vulnerabilities we expect to find
|
|
120
|
+
expected_handlebars_vuln = "Vulnerable JavaScript library detected: handlebars v4.0.5 Severity: HIGH Summary: Regular Expression Denial of Service in Handlebars JavaScript URL: http://127.0.0.1:8888/handlebars.min.js CVE(s): CVE-2019-20922 Affected versions: [4.0.0 to 4.4.5)"
|
|
121
|
+
expected_jquery_vuln = "Vulnerable JavaScript library detected: jquery v3.4.1 Severity: MEDIUM Summary: Regex in its jQuery.htmlPrefilter sometimes may introduce XSS JavaScript URL: http://127.0.0.1:8888/jquery-3.4.1.min.js CVE(s): CVE-2020-11022 Affected versions: [1.2.0 to 3.5.0)"
|
|
122
|
+
|
|
123
|
+
# Verify at least one of the expected vulnerabilities is found
|
|
124
|
+
handlebars_found = expected_handlebars_vuln in all_descriptions
|
|
125
|
+
jquery_found = expected_jquery_vuln in all_descriptions
|
|
126
|
+
|
|
127
|
+
assert handlebars_found and jquery_found, (
|
|
128
|
+
f"Expected to find specific vulnerabilities but didn't find them. Found descriptions:\n{all_descriptions}"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# Basic validation of findings structure
|
|
132
|
+
for finding in retirejs_findings:
|
|
133
|
+
assert "description" in finding.data, "Finding should have description"
|
|
134
|
+
assert "url" in finding.data, "Finding should have url"
|
|
135
|
+
assert finding.parent.type == "URL_UNVERIFIED", "Parent should be URL_UNVERIFIED"
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class TestRetireJSNoExcavate(ModuleTestBase):
|
|
139
|
+
targets = ["http://127.0.0.1:8888"]
|
|
140
|
+
modules_overrides = ["httpx", "retirejs"]
|
|
141
|
+
force_start = True # Allow scan to continue even if modules fail setup
|
|
142
|
+
config_overrides = {
|
|
143
|
+
"excavate": False,
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
def check(self, module_test, events):
|
|
147
|
+
# When excavate is disabled, retirejs should fail setup but scan should still run
|
|
148
|
+
retirejs_module = module_test.scan.modules.get("retirejs")
|
|
149
|
+
|
|
150
|
+
if retirejs_module:
|
|
151
|
+
# Check that the module exists but setup failed
|
|
152
|
+
setup_status = getattr(retirejs_module, "_setup_status", None)
|
|
153
|
+
if setup_status is not None:
|
|
154
|
+
success, error_msg = setup_status
|
|
155
|
+
assert success is False, "retirejs setup should have failed without excavate"
|
|
156
|
+
expected_error = "retirejs will not function without excavate enabled"
|
|
157
|
+
assert error_msg == expected_error, f"Expected error message '{expected_error}', but got '{error_msg}'"
|
|
158
|
+
|
|
159
|
+
# No retirejs findings should be generated since setup failed
|
|
160
|
+
retirejs_findings = [e for e in events if e.type == "FINDING" and getattr(e, "module", None) == "retirejs"]
|
|
161
|
+
assert len(retirejs_findings) == 0, "retirejs should not generate findings when setup fails"
|
|
@@ -11,7 +11,7 @@ class TestTelerik(ModuleTestBase):
|
|
|
11
11
|
# Simulate Telerik.Web.UI.WebResource.axd?type=rau detection
|
|
12
12
|
expect_args = {"method": "GET", "uri": "/Telerik.Web.UI.WebResource.axd", "query_string": "type=rau"}
|
|
13
13
|
respond_args = {
|
|
14
|
-
"response_data": '{ "message" : "RadAsyncUpload handler is registered
|
|
14
|
+
"response_data": '{ "message" : "RadAsyncUpload handler is registered succesfully, however, it may not be accessed directly." }'
|
|
15
15
|
}
|
|
16
16
|
module_test.set_expect_requests(expect_args=expect_args, respond_args=respond_args)
|
|
17
17
|
|
|
@@ -16,6 +16,7 @@ class TestTrufflehog(ModuleTestBase):
|
|
|
16
16
|
"modules": {
|
|
17
17
|
"postman_download": {"api_key": "asdf", "output_folder": str(download_dir)},
|
|
18
18
|
"docker_pull": {"output_folder": str(download_dir)},
|
|
19
|
+
"github_org": {"api_key": "asdf"},
|
|
19
20
|
"git_clone": {"output_folder": str(download_dir)},
|
|
20
21
|
}
|
|
21
22
|
}
|
|
@@ -34,7 +35,9 @@ class TestTrufflehog(ModuleTestBase):
|
|
|
34
35
|
file_content = "Verifiable Secret:\nhttps://admin:admin@the-internet.herokuapp.com/basic_auth\n\nUnverifiable Secret:\nhttps://admin:admin@internal.host.com"
|
|
35
36
|
|
|
36
37
|
async def setup_before_prep(self, module_test):
|
|
37
|
-
module_test.httpx_mock.add_response(
|
|
38
|
+
module_test.httpx_mock.add_response(
|
|
39
|
+
url="https://api.github.com/zen", match_headers={"Authorization": "token asdf"}
|
|
40
|
+
)
|
|
38
41
|
module_test.httpx_mock.add_response(
|
|
39
42
|
url="https://api.getpostman.com/me",
|
|
40
43
|
json={
|
|
@@ -68,6 +71,7 @@ class TestTrufflehog(ModuleTestBase):
|
|
|
68
71
|
)
|
|
69
72
|
module_test.httpx_mock.add_response(
|
|
70
73
|
url="https://api.github.com/orgs/blacklanternsecurity",
|
|
74
|
+
match_headers={"Authorization": "token asdf"},
|
|
71
75
|
json={
|
|
72
76
|
"login": "blacklanternsecurity",
|
|
73
77
|
"id": 25311592,
|
|
@@ -103,6 +107,7 @@ class TestTrufflehog(ModuleTestBase):
|
|
|
103
107
|
)
|
|
104
108
|
module_test.httpx_mock.add_response(
|
|
105
109
|
url="https://api.github.com/orgs/blacklanternsecurity/repos?per_page=100&page=1",
|
|
110
|
+
match_headers={"Authorization": "token asdf"},
|
|
106
111
|
json=[
|
|
107
112
|
{
|
|
108
113
|
"id": 459780477,
|
|
@@ -310,6 +315,7 @@ class TestTrufflehog(ModuleTestBase):
|
|
|
310
315
|
)
|
|
311
316
|
module_test.httpx_mock.add_response(
|
|
312
317
|
url="https://api.github.com/repos/blacklanternsecurity/bbot/actions/workflows?per_page=100&page=1",
|
|
318
|
+
match_headers={"Authorization": "token asdf"},
|
|
313
319
|
json={
|
|
314
320
|
"total_count": 3,
|
|
315
321
|
"workflows": [
|
|
@@ -330,6 +336,7 @@ class TestTrufflehog(ModuleTestBase):
|
|
|
330
336
|
)
|
|
331
337
|
module_test.httpx_mock.add_response(
|
|
332
338
|
url="https://api.github.com/repos/blacklanternsecurity/bbot/actions/workflows/22452226/runs?status=success&per_page=1",
|
|
339
|
+
match_headers={"Authorization": "token asdf"},
|
|
333
340
|
json={
|
|
334
341
|
"total_count": 2993,
|
|
335
342
|
"workflow_runs": [
|
|
@@ -576,6 +583,7 @@ class TestTrufflehog(ModuleTestBase):
|
|
|
576
583
|
)
|
|
577
584
|
module_test.httpx_mock.add_response(
|
|
578
585
|
url="https://api.github.com/repos/blacklanternsecurity/bbot/actions/runs/8839360698/logs",
|
|
586
|
+
match_headers={"Authorization": "token asdf"},
|
|
579
587
|
headers={
|
|
580
588
|
"location": "https://productionresultssa10.blob.core.windows.net/actions-results/7beb304e-f42c-4830-a027-4f5dec53107d/workflow-job-run-3a559e2a-952e-58d2-b8db-2e604a9266d7/logs/steps/step-logs-0e34a19a-18b0-4208-b27a-f8c031db2d17.txt?rsct=text%2Fplain&se=2024-04-26T16%3A25%3A39Z&sig=a%2FiN8dOw0e3tiBQZAfr80veI8OYChb9edJ1eFY136B4%3D&sp=r&spr=https&sr=b&st=2024-04-26T16%3A15%3A34Z&sv=2021-12-02"
|
|
581
589
|
},
|
|
@@ -1221,6 +1229,7 @@ class TestTrufflehog_NonVerified(TestTrufflehog):
|
|
|
1221
1229
|
"trufflehog": {"only_verified": False},
|
|
1222
1230
|
"docker_pull": {"output_folder": str(download_dir)},
|
|
1223
1231
|
"postman_download": {"api_key": "asdf", "output_folder": str(download_dir)},
|
|
1232
|
+
"github_org": {"api_key": "asdf"},
|
|
1224
1233
|
"git_clone": {"output_folder": str(download_dir)},
|
|
1225
1234
|
}
|
|
1226
1235
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: bbot
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.7.2.7424rc0
|
|
4
4
|
Summary: OSINT automation for hackers.
|
|
5
5
|
License: GPL-3.0
|
|
6
|
+
License-File: LICENSE
|
|
6
7
|
Keywords: python,cli,automation,osint,threat-intel,intelligence,neo4j,scanner,python-library,hacking,recursion,pentesting,recon,command-line-tool,bugbounty,subdomains,security-tools,subdomain-scanner,osint-framework,attack-surface,subdomain-enumeration,osint-tool
|
|
7
8
|
Author: TheTechromancer
|
|
8
9
|
Requires-Python: >=3.9,<4.0
|
|
@@ -14,14 +15,15 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
14
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
19
|
Classifier: Topic :: Security
|
|
18
20
|
Requires-Dist: ansible-core (>=2.15.13,<3.0.0)
|
|
19
21
|
Requires-Dist: ansible-runner (>=2.3.2,<3.0.0)
|
|
20
22
|
Requires-Dist: beautifulsoup4 (>=4.12.2,<5.0.0)
|
|
21
23
|
Requires-Dist: cachetools (>=5.3.2,<7.0.0)
|
|
22
|
-
Requires-Dist: cloudcheck (>=
|
|
24
|
+
Requires-Dist: cloudcheck (>=8.6.0,<9.0.0)
|
|
23
25
|
Requires-Dist: deepdiff (>=8.0.0,<9.0.0)
|
|
24
|
-
Requires-Dist: dnspython (>=2.
|
|
26
|
+
Requires-Dist: dnspython (>=2.7.0,<2.8.0)
|
|
25
27
|
Requires-Dist: httpx (>=0.28.1,<0.29.0)
|
|
26
28
|
Requires-Dist: idna (>=3.4,<4.0)
|
|
27
29
|
Requires-Dist: jinja2 (>=3.1.3,<4.0.0)
|
|
@@ -34,9 +36,9 @@ Requires-Dist: puremagic (>=1.28,<2.0)
|
|
|
34
36
|
Requires-Dist: pycryptodome (>=3.17,<4.0)
|
|
35
37
|
Requires-Dist: pydantic (>=2.9.2,<3.0.0)
|
|
36
38
|
Requires-Dist: pyjwt (>=2.7.0,<3.0.0)
|
|
37
|
-
Requires-Dist: pyzmq (>=26.0.3,<
|
|
39
|
+
Requires-Dist: pyzmq (>=26.0.3,<28.0.0)
|
|
38
40
|
Requires-Dist: radixtarget (>=3.0.13,<4.0.0)
|
|
39
|
-
Requires-Dist: regex (>=2024.4.16,<
|
|
41
|
+
Requires-Dist: regex (>=2024.4.16,<2026.0.0)
|
|
40
42
|
Requires-Dist: setproctitle (>=1.3.3,<2.0.0)
|
|
41
43
|
Requires-Dist: socksio (>=1.0.0,<2.0.0)
|
|
42
44
|
Requires-Dist: tabulate (==0.8.10)
|
|
@@ -45,6 +47,7 @@ Requires-Dist: unidecode (>=1.3.8,<2.0.0)
|
|
|
45
47
|
Requires-Dist: websockets (>=14.0.0,<16.0.0)
|
|
46
48
|
Requires-Dist: wordninja (>=2.0.0,<3.0.0)
|
|
47
49
|
Requires-Dist: xmltojson (>=2.0.2,<3.0.0)
|
|
50
|
+
Requires-Dist: xxhash (>=3.5.0,<4.0.0)
|
|
48
51
|
Requires-Dist: yara-python (>=4.5.1,<5.0.0)
|
|
49
52
|
Project-URL: Documentation, https://www.blacklanternsecurity.com/bbot/
|
|
50
53
|
Project-URL: Discord, https://discord.com/invite/PZqkgxu5SA
|
|
@@ -55,7 +58,7 @@ Description-Content-Type: text/markdown
|
|
|
55
58
|
|
|
56
59
|
[](https://github.com/blacklanternsecurity/bbot)
|
|
57
60
|
|
|
58
|
-
[](https://www.python.org) [](https://www.python.org) [](https://github.com/blacklanternsecurity/bbot/blob/dev/LICENSE) [](https://www.reconvillage.org/talks) [](https://pepy.tech/project/bbot) [](https://github.com/astral-sh/ruff) [](https://github.com/blacklanternsecurity/bbot/actions?query=workflow%3A"tests") [](https://codecov.io/gh/blacklanternsecurity/bbot) [](https://discord.com/invite/PZqkgxu5SA)
|
|
59
62
|
|
|
60
63
|
### **BEE·bot** is a multipurpose scanner inspired by [Spiderfoot](https://github.com/smicallef/spiderfoot), built to automate your **Recon**, **Bug Bounties**, and **ASM**!
|
|
61
64
|
|