bbot 2.5.0.6790rc0__py3-none-any.whl → 2.5.0.6803rc0__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.

Potentially problematic release.


This version of bbot might be problematic. Click here for more details.

bbot/__init__.py CHANGED
@@ -1,5 +1,5 @@
1
1
  # version placeholder (replaced by poetry-dynamic-versioning)
2
- __version__ = "v2.5.0.6790rc"
2
+ __version__ = "v2.5.0.6803rc"
3
3
 
4
4
  from .scanner import Scanner, Preset
5
5
 
@@ -0,0 +1,142 @@
1
+ import json
2
+ from pathlib import Path
3
+ from bbot.modules.base import BaseModule
4
+
5
+
6
+ class graphql_introspection(BaseModule):
7
+ watched_events = ["URL"]
8
+ produced_events = ["FINDING"]
9
+ flags = ["safe", "active", "web-basic"]
10
+ meta = {
11
+ "description": "Perform GraphQL introspection on a target",
12
+ "created_date": "2025-07-01",
13
+ "author": "@mukesh-dream11",
14
+ }
15
+ options = {
16
+ "graphql_endpoint_urls": ["/", "/graphql", "/v1/graphql"],
17
+ "output_folder": "",
18
+ }
19
+ options_desc = {
20
+ "graphql_endpoint_urls": "List of GraphQL endpoint to suffix to the target URL",
21
+ "output_folder": "Folder to save the GraphQL schemas to",
22
+ }
23
+
24
+ async def setup(self):
25
+ output_folder = self.config.get("output_folder", "")
26
+ if output_folder:
27
+ self.output_dir = Path(output_folder) / "graphql-schemas"
28
+ else:
29
+ self.output_dir = self.scan.home / "graphql-schemas"
30
+ self.helpers.mkdir(self.output_dir)
31
+ return True
32
+
33
+ async def filter_event(self, event):
34
+ # Dedup by the base URL
35
+ base_url = event.parsed_url._replace(path="/", query="", fragment="").geturl()
36
+ return hash(base_url)
37
+
38
+ async def handle_event(self, event):
39
+ base_url = event.parsed_url._replace(path="/", query="", fragment="").geturl().rstrip("/")
40
+ for endpoint_url in self.config.get("graphql_endpoint_urls", []):
41
+ url = f"{base_url}{endpoint_url}"
42
+ request_args = {
43
+ "url": url,
44
+ "method": "POST",
45
+ "json": {
46
+ "query": """\
47
+ query IntrospectionQuery {
48
+ __schema {
49
+ queryType {
50
+ name
51
+ }
52
+ mutationType {
53
+ name
54
+ }
55
+ types {
56
+ name
57
+ kind
58
+ description
59
+ fields(includeDeprecated: true) {
60
+ name
61
+ description
62
+ type {
63
+ ... TypeRef
64
+ }
65
+ isDeprecated
66
+ deprecationReason
67
+ }
68
+ interfaces {
69
+ ... TypeRef
70
+ }
71
+ possibleTypes {
72
+ ... TypeRef
73
+ }
74
+ enumValues(includeDeprecated: true) {
75
+ name
76
+ description
77
+ isDeprecated
78
+ deprecationReason
79
+ }
80
+ ofType {
81
+ ... TypeRef
82
+ }
83
+ }
84
+ }
85
+ }
86
+
87
+ fragment TypeRef on __Type {
88
+ kind
89
+ name
90
+ ofType {
91
+ kind
92
+ name
93
+ ofType {
94
+ kind
95
+ name
96
+ ofType {
97
+ kind
98
+ name
99
+ ofType {
100
+ kind
101
+ name
102
+ ofType {
103
+ kind
104
+ name
105
+ ofType {
106
+ kind
107
+ name
108
+ ofType {
109
+ kind
110
+ name
111
+ }
112
+ }
113
+ }
114
+ }
115
+ }
116
+ }
117
+ }
118
+ }"""
119
+ },
120
+ }
121
+ response = await self.helpers.request(**request_args)
122
+ if not response or response.status_code != 200:
123
+ self.debug(f"Failed to get GraphQL schema for {url} (status code {response.status_code})")
124
+ continue
125
+ try:
126
+ response_json = response.json()
127
+ except json.JSONDecodeError:
128
+ self.debug(f"Failed to parse JSON for {url}")
129
+ continue
130
+ if response_json.get("data", {}).get("__schema", {}).get("types", []):
131
+ filename = f"schema-{self.helpers.tagify(url)}.json"
132
+ filename = self.output_dir / filename
133
+ with open(filename, "w") as f:
134
+ json.dump(response_json, f)
135
+ await self.emit_event(
136
+ {"url": url, "description": "GraphQL schema", "path": str(filename.relative_to(self.scan.home))},
137
+ "FINDING",
138
+ event,
139
+ context=f"{{module}} found GraphQL schema at {url}",
140
+ )
141
+ # return, because we only want to find one schema per target
142
+ return
@@ -14,7 +14,7 @@ class trufflehog(BaseModule):
14
14
  }
15
15
 
16
16
  options = {
17
- "version": "3.89.2",
17
+ "version": "3.90.1",
18
18
  "config": "",
19
19
  "only_verified": True,
20
20
  "concurrency": 8,
@@ -0,0 +1,34 @@
1
+ from .base import ModuleTestBase
2
+
3
+
4
+ class TestGraphQLIntrospectionNon200(ModuleTestBase):
5
+ targets = ["http://127.0.0.1:8888"]
6
+ modules_overrides = ["graphql_introspection"]
7
+
8
+ async def setup_after_prep(self, module_test):
9
+ module_test.set_expect_requests(
10
+ expect_args={"method": "POST", "uri": "/"},
11
+ respond_args={"response_data": "ok"},
12
+ )
13
+
14
+ def check(self, module_test, events):
15
+ assert all(e.type != "FINDING" for e in events), "should have raised 0 events"
16
+
17
+
18
+ class TestGraphQLIntrospection(ModuleTestBase):
19
+ targets = ["http://127.0.0.1:8888"]
20
+ modules_overrides = ["graphql_introspection"]
21
+
22
+ async def setup_after_prep(self, module_test):
23
+ module_test.set_expect_requests(
24
+ expect_args={"method": "POST", "uri": "/"},
25
+ respond_args={
26
+ "response_data": """{"data": {"__schema": {"types": ["dummy"]}}}""",
27
+ },
28
+ )
29
+
30
+ def check(self, module_test, events):
31
+ finding = [e for e in events if e.type == "FINDING"]
32
+ assert finding, "should have raised 1 FINDING event"
33
+ assert finding[0].data["url"] == "http://127.0.0.1:8888/"
34
+ assert finding[0].data["description"] == "GraphQL schema"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bbot
3
- Version: 2.5.0.6790rc0
3
+ Version: 2.5.0.6803rc0
4
4
  Summary: OSINT automation for hackers.
5
5
  License: GPL-3.0
6
6
  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
@@ -1,4 +1,4 @@
1
- bbot/__init__.py,sha256=eeeMm8A02JCgtw8Y3LIUP8V1-N0OyiK-EWMPsXQRovY,163
1
+ bbot/__init__.py,sha256=psvZSLfHy5t3AIe_f5WcJGV67hsBRzebgolsC2TQ89Y,163
2
2
  bbot/cli.py,sha256=1QJbANVw9Q3GFM92H2QRV2ds5756ulm08CDZwzwPpeI,11888
3
3
  bbot/core/__init__.py,sha256=l255GJE_DvUnWvrRb0J5lG-iMztJ8zVvoweDOfegGtI,46
4
4
  bbot/core/config/__init__.py,sha256=zYNw2Me6tsEr8hOOkLb4BQ97GB7Kis2k--G81S8vofU,342
@@ -114,6 +114,7 @@ bbot/modules/github_workflows.py,sha256=xKntAFDeGuE4MqbEmhJyYXKbzoSh9tWYlHNlnF37
114
114
  bbot/modules/gitlab.py,sha256=9oWWpBijeHCjuFBfWW4HvNqt7bvJvrBgBjaaz_UPPnE,5964
115
115
  bbot/modules/google_playstore.py,sha256=N4QjzQag_bgDXfX17rytBiiWA-SQtYI2N0J_ZNEOdv0,3701
116
116
  bbot/modules/gowitness.py,sha256=o4nIBbHVX9tYVW9CpwTsaftWDZu41nhxS0KEp4FoiBs,13003
117
+ bbot/modules/graphql_introspection.py,sha256=-BAzNhBegup2sIYQdJ0jcafZFTGTZl3WoMygilyvfVA,4144
117
118
  bbot/modules/hackertarget.py,sha256=IsKs9PtxUHdLJKZydlRdW_loBE2KphQYi3lKDAd4odc,1029
118
119
  bbot/modules/host_header.py,sha256=uDjwidMdeNPMRfzQ2YW4REEGsZqnGOZHbOS6GgdNd9s,7686
119
120
  bbot/modules/httpx.py,sha256=z0sgnfLqIXyiadM0rKQK2p86lka7rC4pGCfTVUqU5Lk,8118
@@ -207,7 +208,7 @@ bbot/modules/templates/sql.py,sha256=o-CdyyoJvHJdJBKkj3CIGXYxUta4w2AB_2Vr-k7cDDU
207
208
  bbot/modules/templates/subdomain_enum.py,sha256=epyKSly08jqaINV_AMMWbNafIeQjJqvd3aj63KD0Mck,8402
208
209
  bbot/modules/templates/webhook.py,sha256=uGFmcJ81GzGN1UI2k2O7nQF_fyh4ehLDEg2NSXaPnhk,3373
209
210
  bbot/modules/trickest.py,sha256=MRgLW0YiDWzlWdAjyqfPPLFb-a51r-Ffn_dphiJI_gA,1550
210
- bbot/modules/trufflehog.py,sha256=e8M0HvDRImwvokeCPE-TnJGRXgAn1W4asu_BMST13Ik,8717
211
+ bbot/modules/trufflehog.py,sha256=CqF9UAEzi0JzJKitXnBWFAVypCVuKKXWPW14Txw6GMs,8717
211
212
  bbot/modules/url_manipulation.py,sha256=4J3oFkqTSJPPmbKEKAHJg2Q2w4QNKtQhiN03ZJq5VtI,4326
212
213
  bbot/modules/urlscan.py,sha256=-w_3Bm6smyG2GLQyIbnMUkKmeQVauo-V6F4_kJDYG7s,3740
213
214
  bbot/modules/vhost.py,sha256=cirOe0HR4M0TEBN8JdXo2l0s2flc8ZSdxggGm79blT8,5459
@@ -364,6 +365,7 @@ bbot/test/test_step_2/module_tests/test_module_github_workflows.py,sha256=o_teEa
364
365
  bbot/test/test_step_2/module_tests/test_module_gitlab.py,sha256=fnwE7BWTU6EQquKdGLCiaX_LwVwvzOLev3Y9GheTLSY,11859
365
366
  bbot/test/test_step_2/module_tests/test_module_google_playstore.py,sha256=uTRqpAGI9HI-rOk_6jdV44OoSqi0QQQ3aTVzvuV0dtc,3034
366
367
  bbot/test/test_step_2/module_tests/test_module_gowitness.py,sha256=EH3NIMDA3XgZz1yffu-PnRCrlZJODakGPfzgnU7Ls_s,6501
368
+ bbot/test/test_step_2/module_tests/test_module_graphql_introspection.py,sha256=qac8DJ_exe6Ra4UgRvVMSdgBhLIZP9lmXyKhi9RPOK8,1241
367
369
  bbot/test/test_step_2/module_tests/test_module_hackertarget.py,sha256=ldhNKxGk5fwq87zVptQDyfQ-cn3FzbWvpadKEO3h4ic,609
368
370
  bbot/test/test_step_2/module_tests/test_module_host_header.py,sha256=w1x0MyKNiUol4hlw7CijhMwEMEL5aBddbZZjOcEgv_k,2672
369
371
  bbot/test/test_step_2/module_tests/test_module_http.py,sha256=KhsQvqpVa6zmMa79jV4liv_NAv25wrSaO6h_x0AA12c,2127
@@ -451,8 +453,8 @@ bbot/wordlists/raft-small-extensions-lowercase_CLEANED.txt,sha256=ZSIVebs7ptMvHx
451
453
  bbot/wordlists/top_open_ports_nmap.txt,sha256=LmdFYkfapSxn1pVuQC2LkOIY2hMLgG-Xts7DVtYzweM,42727
452
454
  bbot/wordlists/valid_url_schemes.txt,sha256=0B_VAr9Dv7aYhwi6JSBDU-3M76vNtzN0qEC_RNLo7HE,3310
453
455
  bbot/wordlists/wordninja_dns.txt.gz,sha256=DYHvvfW0TvzrVwyprqODAk4tGOxv5ezNmCPSdPuDUnQ,570241
454
- bbot-2.5.0.6790rc0.dist-info/LICENSE,sha256=GzeCzK17hhQQDNow0_r0L8OfLpeTKQjFQwBQU7ZUymg,32473
455
- bbot-2.5.0.6790rc0.dist-info/METADATA,sha256=NEVTJu_6hgKq-HwhDk78Vgf-WP-HSmYYiB2GaMrPcxc,18308
456
- bbot-2.5.0.6790rc0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
457
- bbot-2.5.0.6790rc0.dist-info/entry_points.txt,sha256=cWjvcU_lLrzzJgjcjF7yeGuRA_eDS8pQ-kmPUAyOBfo,38
458
- bbot-2.5.0.6790rc0.dist-info/RECORD,,
456
+ bbot-2.5.0.6803rc0.dist-info/LICENSE,sha256=GzeCzK17hhQQDNow0_r0L8OfLpeTKQjFQwBQU7ZUymg,32473
457
+ bbot-2.5.0.6803rc0.dist-info/METADATA,sha256=RafoLsvxll-6fDNfVENz3dKWCZBy4nwrtx3qVZfkjw0,18308
458
+ bbot-2.5.0.6803rc0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
459
+ bbot-2.5.0.6803rc0.dist-info/entry_points.txt,sha256=cWjvcU_lLrzzJgjcjF7yeGuRA_eDS8pQ-kmPUAyOBfo,38
460
+ bbot-2.5.0.6803rc0.dist-info/RECORD,,