bbot 2.3.1__py3-none-any.whl → 2.3.1.5818rc0__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,4 +1,4 @@
1
1
  # version placeholder (replaced by poetry-dynamic-versioning)
2
- __version__ = "v2.3.1"
2
+ __version__ = "v2.3.1.5818rc"
3
3
 
4
4
  from .scanner import Scanner, Preset
bbot/modules/telerik.py CHANGED
@@ -5,6 +5,21 @@ from bbot.modules.base import BaseModule
5
5
 
6
6
 
7
7
  class telerik(BaseModule):
8
+ """
9
+ Test for endpoints associated with Telerik.Web.UI.dll
10
+
11
+ Telerik.Web.UI.WebResource.axd (CVE-2017-11317)
12
+ Telerik.Web.UI.DialogHandler.aspx (CVE-2017-9248)
13
+ Telerik.Web.UI.SpellCheckHandler.axd (associated with CVE-2017-9248)
14
+ ChartImage.axd (CVE-2019-19790)
15
+
16
+ For the Telerik Report Server vulnerability (CVE-2024-4358) Use the Nuclei Template: (https://github.com/projectdiscovery/nuclei-templates/blob/main/http/cves/2024/CVE-2024-4358.yaml)
17
+
18
+ With exploit_RAU_crypto enabled, the module will attempt to exploit CVE-2017-11317. THIS WILL UPLOAD A (benign) FILE IF SUCCESSFUL.
19
+
20
+ Will dedupe to host by default (running against first received URL). With include_subdirs enabled, will run against every directory.
21
+ """
22
+
8
23
  watched_events = ["URL", "HTTP_RESPONSE"]
9
24
  produced_events = ["VULNERABILITY", "FINDING"]
10
25
  flags = ["active", "aggressive", "web-thorough"]
@@ -139,8 +154,11 @@ class telerik(BaseModule):
139
154
 
140
155
  RAUConfirmed = []
141
156
 
142
- options = {"exploit_RAU_crypto": False}
143
- options_desc = {"exploit_RAU_crypto": "Attempt to confirm any RAU AXD detections are vulnerable"}
157
+ options = {"exploit_RAU_crypto": False, "include_subdirs": False}
158
+ options_desc = {
159
+ "exploit_RAU_crypto": "Attempt to confirm any RAU AXD detections are vulnerable",
160
+ "include_subdirs": "Include subdirectories in the scan (off by default)", # will create many finding events if used in conjunction with web spider or ffuf
161
+ }
144
162
 
145
163
  in_scope_only = True
146
164
 
@@ -162,19 +180,33 @@ class telerik(BaseModule):
162
180
 
163
181
  _module_threads = 5
164
182
 
183
+ @staticmethod
184
+ def normalize_url(url):
185
+ return str(url.rstrip("/") + "/").lower()
186
+
165
187
  def _incoming_dedup_hash(self, event):
166
188
  if event.type == "URL":
167
- return hash(event.host)
168
- else:
169
- return hash(event.data["url"])
189
+ if self.config.get("include_subdirs") is True:
190
+ return hash(f"{event.type}{self.normalize_url(event.data)}")
191
+ else:
192
+ return hash(f"{event.type}{event.netloc}")
193
+ else: # HTTP_RESPONSE
194
+ return hash(f"{event.type}{event.data['url']}")
170
195
 
171
196
  async def handle_event(self, event):
172
197
  if event.type == "URL":
198
+ if self.config.get("include_subdirs"):
199
+ base_url = self.normalize_url(event.data) # Use the entire URL including subdirectories
200
+
201
+ else:
202
+ base_url = f"{event.parsed_url.scheme}://{event.parsed_url.netloc}/" # path will be omitted
203
+
204
+ # Check for RAU AXD Handler
173
205
  webresource = "Telerik.Web.UI.WebResource.axd?type=rau"
174
- result, _ = await self.test_detector(event.data, webresource)
206
+ result, _ = await self.test_detector(base_url, webresource)
175
207
  if result:
176
208
  if "RadAsyncUpload handler is registered successfully" in result.text:
177
- self.debug("Detected Telerik instance (Telerik.Web.UI.WebResource.axd?type=rau)")
209
+ self.verbose("Detected Telerik instance (Telerik.Web.UI.WebResource.axd?type=rau)")
178
210
 
179
211
  probe_data = {
180
212
  "rauPostData": (
@@ -211,15 +243,14 @@ class telerik(BaseModule):
211
243
 
212
244
  description = f"Telerik RAU AXD Handler detected. Verbose Errors Enabled: [{str(verbose_errors)}] Version Guess: [{version}]"
213
245
  await self.emit_event(
214
- {"host": str(event.host), "url": f"{event.data}{webresource}", "description": description},
246
+ {"host": str(event.host), "url": f"{base_url}{webresource}", "description": description},
215
247
  "FINDING",
216
248
  event,
217
- context=f"{{module}} scanned {event.data} and identified {{event.type}}: Telerik RAU AXD Handler",
249
+ context=f"{{module}} scanned {base_url} and identified {{event.type}}: Telerik RAU AXD Handler",
218
250
  )
219
251
  if self.config.get("exploit_RAU_crypto") is True:
220
- hostname = urlparse(event.data).netloc
221
- if hostname not in self.RAUConfirmed:
222
- self.RAUConfirmed.append(hostname)
252
+ if base_url not in self.RAUConfirmed:
253
+ self.RAUConfirmed.append(base_url)
223
254
  root_tool_path = self.scan.helpers.tools_dir / "telerik"
224
255
  self.debug(root_tool_path)
225
256
 
@@ -242,17 +273,17 @@ class telerik(BaseModule):
242
273
  "severity": "CRITICAL",
243
274
  "description": description,
244
275
  "host": str(event.host),
245
- "url": f"{event.data}{webresource}",
276
+ "url": f"{base_url}{webresource}",
246
277
  },
247
278
  "VULNERABILITY",
248
279
  event,
249
- context=f"{{module}} scanned {event.data} and identified critical {{event.type}}: {description}",
280
+ context=f"{{module}} scanned {base_url} and identified critical {{event.type}}: {description}",
250
281
  )
251
282
  break
252
283
 
253
284
  urls = {}
254
285
  for dh in self.DialogHandlerUrls:
255
- url = self.create_url(event.data, f"{dh}?dp=1")
286
+ url = self.create_url(base_url, f"{dh}?dp=1")
256
287
  urls[url] = dh
257
288
 
258
289
  gen = self.helpers.request_batch(list(urls))
@@ -265,14 +296,14 @@ class telerik(BaseModule):
265
296
  # tolerate some random errors
266
297
  if fail_count < 2:
267
298
  continue
268
- self.debug(f"Cancelling run against {event.data} due to failed request")
299
+ self.debug(f"Cancelling run against {base_url} due to failed request")
269
300
  await gen.aclose()
270
301
  else:
271
302
  if "Cannot deserialize dialog parameters" in response.text:
272
303
  self.debug(f"Detected Telerik UI instance ({dh})")
273
304
  description = "Telerik DialogHandler detected"
274
305
  await self.emit_event(
275
- {"host": str(event.host), "url": f"{event.data}{dh}", "description": description},
306
+ {"host": str(event.host), "url": f"{base_url}{dh}", "description": description},
276
307
  "FINDING",
277
308
  event,
278
309
  )
@@ -280,12 +311,12 @@ class telerik(BaseModule):
280
311
  await gen.aclose()
281
312
 
282
313
  spellcheckhandler = "Telerik.Web.UI.SpellCheckHandler.axd"
283
- result, _ = await self.test_detector(event.data, spellcheckhandler)
314
+ result, _ = await self.test_detector(base_url, spellcheckhandler)
284
315
  status_code = getattr(result, "status_code", 0)
285
316
  # The standard behavior for the spellcheck handler without parameters is a 500
286
317
  if status_code == 500:
287
318
  # Sometimes webapps will just return 500 for everything, so rule out the false positive
288
- validate_result, _ = await self.test_detector(event.data, self.helpers.rand_string())
319
+ validate_result, _ = await self.test_detector(base_url, self.helpers.rand_string())
289
320
  self.debug(validate_result)
290
321
  validate_status_code = getattr(validate_result, "status_code", 0)
291
322
  if validate_status_code not in (0, 500):
@@ -294,31 +325,31 @@ class telerik(BaseModule):
294
325
  await self.emit_event(
295
326
  {
296
327
  "host": str(event.host),
297
- "url": f"{event.data}{spellcheckhandler}",
328
+ "url": f"{base_url}{spellcheckhandler}",
298
329
  "description": description,
299
330
  },
300
331
  "FINDING",
301
332
  event,
302
- context=f"{{module}} scanned {event.data} and identified {{event.type}}: Telerik SpellCheckHandler",
333
+ context=f"{{module}} scanned {base_url} and identified {{event.type}}: Telerik SpellCheckHandler",
303
334
  )
304
335
 
305
336
  chartimagehandler = "ChartImage.axd?ImageName=bqYXJAqm315eEd6b%2bY4%2bGqZpe7a1kY0e89gfXli%2bjFw%3d"
306
- result, _ = await self.test_detector(event.data, chartimagehandler)
337
+ result, _ = await self.test_detector(base_url, chartimagehandler)
307
338
  status_code = getattr(result, "status_code", 0)
308
339
  if status_code == 200:
309
340
  chartimagehandler_error = "ChartImage.axd?ImageName="
310
- result_error, _ = await self.test_detector(event.data, chartimagehandler_error)
341
+ result_error, _ = await self.test_detector(base_url, chartimagehandler_error)
311
342
  error_status_code = getattr(result_error, "status_code", 0)
312
343
  if error_status_code not in (0, 200):
313
344
  await self.emit_event(
314
345
  {
315
346
  "host": str(event.host),
316
- "url": f"{event.data}{chartimagehandler}",
347
+ "url": f"{base_url}{chartimagehandler}",
317
348
  "description": "Telerik ChartImage AXD Handler Detected",
318
349
  },
319
350
  "FINDING",
320
351
  event,
321
- context=f"{{module}} scanned {event.data} and identified {{event.type}}: Telerik ChartImage AXD Handler",
352
+ context=f"{{module}} scanned {base_url} and identified {{event.type}}: Telerik ChartImage AXD Handler",
322
353
  )
323
354
 
324
355
  elif event.type == "HTTP_RESPONSE":
@@ -348,14 +379,8 @@ class telerik(BaseModule):
348
379
  context="{module} searched HTTP_RESPONSE and identified {event.type}: Telerik AsyncUpload",
349
380
  )
350
381
 
351
- # Check for RAD Controls in URL
352
-
353
382
  def create_url(self, baseurl, detector):
354
- if not baseurl.endswith("/"):
355
- url = f"{baseurl}/{detector}"
356
- else:
357
- url = f"{baseurl}{detector}"
358
- return url
383
+ return f"{baseurl}{detector}"
359
384
 
360
385
  async def test_detector(self, baseurl, detector):
361
386
  result = None
@@ -19,3 +19,4 @@ config:
19
19
  extensions: asp,aspx,ashx,asmx,ascx
20
20
  telerik:
21
21
  exploit_RAU_crypto: True
22
+ include_subdirs: True # Run against every directory, not the default first received URL per-host
@@ -1,5 +1,5 @@
1
1
  import re
2
- from .base import ModuleTestBase
2
+ from .base import ModuleTestBase, tempwordlist
3
3
 
4
4
 
5
5
  class TestTelerik(ModuleTestBase):
@@ -28,7 +28,7 @@ class TestTelerik(ModuleTestBase):
28
28
  }
29
29
  module_test.set_expect_requests(expect_args=expect_args, respond_args=respond_args)
30
30
 
31
- # Simulate DialogHandler detection
31
+ # Simulate SpellCheckHandler detection
32
32
  expect_args = {"method": "GET", "uri": "/Telerik.Web.UI.SpellCheckHandler.axd"}
33
33
  respond_args = {"status": 500}
34
34
  module_test.set_expect_requests(expect_args=expect_args, respond_args=respond_args)
@@ -114,3 +114,58 @@ class TestTelerik(ModuleTestBase):
114
114
  assert telerik_dialoghandler_detection, "Telerik dialoghandler detection failed"
115
115
  assert telerik_chartimage_detection, "Telerik chartimage detection failed"
116
116
  assert telerik_http_response_parameters_detection, "Telerik SerializedParameters detection failed"
117
+
118
+
119
+ class TestTelerikDialogHandler_includesubdirs(TestTelerik):
120
+ targets = ["http://127.0.0.1:8888/", "http://127.0.0.1:8888/temp/"]
121
+ config_overrides = {
122
+ "modules": {
123
+ "telerik": {
124
+ "include_subdirs": True,
125
+ },
126
+ }
127
+ }
128
+ modules_overrides = ["httpx", "telerik"]
129
+
130
+ async def setup_before_prep(self, module_test):
131
+ # Simulate NO SpellCheckHandler detection (not testing for that with this test)
132
+ expect_args = {"method": "GET", "uri": "/Telerik.Web.UI.SpellCheckHandler.axd"}
133
+ respond_args = {"status": 404}
134
+ module_test.set_expect_requests(expect_args=expect_args, respond_args=respond_args)
135
+
136
+ # Simulate DialogHandler detection
137
+ expect_args = {"method": "GET", "uri": "/App_Master/Telerik.Web.UI.DialogHandler.aspx"}
138
+ respond_args = {
139
+ "response_data": '<input type="hidden" name="dialogParametersHolder" id="dialogParametersHolder" /><div style=\'color:red\'>Cannot deserialize dialog parameters. Please refresh the editor page.</div><div>Error Message:Invalid length for a Base-64 char array or string.</div></form></body></html>'
140
+ }
141
+ module_test.set_expect_requests(expect_args=expect_args, respond_args=respond_args)
142
+
143
+ # Simulate DialogHandler detection (in /temp)
144
+ expect_args = {"method": "GET", "uri": "/temp/App_Master/Telerik.Web.UI.DialogHandler.aspx"}
145
+ respond_args = {
146
+ "response_data": '<input type="hidden" name="dialogParametersHolder" id="dialogParametersHolder" /><div style=\'color:red\'>Cannot deserialize dialog parameters. Please refresh the editor page.</div><div>Error Message:Invalid length for a Base-64 char array or string.</div></form></body></html>'
147
+ }
148
+ module_test.set_expect_requests(expect_args=expect_args, respond_args=respond_args)
149
+
150
+ # Simulate /temp directory detection
151
+ expect_args = {"method": "GET", "uri": "/temp/"}
152
+ respond_args = {"response_data": "Temporary directory found"}
153
+ module_test.set_expect_requests(expect_args=expect_args, respond_args=respond_args)
154
+
155
+ # Fallback
156
+ expect_args = {"method": "GET", "uri": "/"}
157
+ respond_args = {"response_data": "alive"}
158
+ module_test.set_expect_requests(expect_args=expect_args, respond_args=respond_args)
159
+
160
+ async def setup_after_prep(self, module_test):
161
+ module_test.scan.modules["telerik"].telerikVersions = ["2014.2.724", "2014.3.1024", "2015.1.204"]
162
+ module_test.scan.modules["telerik"].DialogHandlerUrls = [
163
+ "App_Master/Telerik.Web.UI.DialogHandler.aspx",
164
+ ]
165
+
166
+ def check(self, module_test, events):
167
+ # Check if the expected requests were made
168
+ finding_count = sum(
169
+ 1 for e in events if e.type == "FINDING" and "Telerik DialogHandler detected" in e.data["description"]
170
+ )
171
+ assert finding_count == 2, "Expected 2 FINDING events (root and /temp), got {finding_count}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bbot
3
- Version: 2.3.1
3
+ Version: 2.3.1.5818rc0
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=9tKCKJdKi4W7gV89WCtpSPnt_sbfKiKcYJ-jR5Ter9c,123
1
+ bbot/__init__.py,sha256=84uhPTH3TNfR-SYUMJc3nC7qGRu7Sf_VgzzMbtKvoVE,130
2
2
  bbot/cli.py,sha256=Jdhrtcpwzq4Pm71bikElx1Fj_gWN5x_GEkp7W42iQxQ,10753
3
3
  bbot/core/__init__.py,sha256=l255GJE_DvUnWvrRb0J5lG-iMztJ8zVvoweDOfegGtI,46
4
4
  bbot/core/config/__init__.py,sha256=zYNw2Me6tsEr8hOOkLb4BQ97GB7Kis2k--G81S8vofU,342
@@ -183,7 +183,7 @@ bbot/modules/social.py,sha256=SaXC8gK69k9aMNHS9y7b-Ag-w7U7DbeXqrZRx9CtXLw,2499
183
183
  bbot/modules/sslcert.py,sha256=83rf_rzlj4iku3gldx1_R1L_v3ZCGItGPay8JviUy9w,8211
184
184
  bbot/modules/subdomaincenter.py,sha256=aWjcIqGGWnAj2ePwcS4sgUJDUsq0trY3Klhr_lcc4dg,1424
185
185
  bbot/modules/subdomainradar.py,sha256=YlRNMtNGLpa13KZ7aksAMVZdSjxe1tkywU5RXlwXpPc,6784
186
- bbot/modules/telerik.py,sha256=zEgA3Wtn9o7DjMySLf5RsRpbpnFyzfmZvzL8xbL95lc,17587
186
+ bbot/modules/telerik.py,sha256=9F7-MrAiulM5W26JxydAJ6nqD_Di7_X6RoTpCb3S5FI,18930
187
187
  bbot/modules/templates/bucket.py,sha256=muLPpfAGtcNhL0tLU-qHTlTNIz4yncRcVjdZMqVRtUI,7153
188
188
  bbot/modules/templates/github.py,sha256=n6cVjf62ezkztCRAcXNnlxfCkB0VRWqn138mOOt6T08,1454
189
189
  bbot/modules/templates/postman.py,sha256=MIpz2q_r6LP0kIEgByo7oX5qHhMZLOhr7oKzJI9Beec,6959
@@ -217,7 +217,7 @@ bbot/presets/spider.yml,sha256=-7HkEEZS_fFESPVzGi91eNf2ZwfAv1lU9oyFp0dhuZA,400
217
217
  bbot/presets/subdomain-enum.yml,sha256=tn9h8TlVB_uS3nKZFUP72HzceoRONSef66mGLWzxj9w,414
218
218
  bbot/presets/web/dirbust-heavy.yml,sha256=NDqu7p0Hx1RsZCVnaEWRgI_iL9O0io-tvWerxJf36SM,653
219
219
  bbot/presets/web/dirbust-light.yml,sha256=5zSANdjKfYh49kFlsElYY2G6acVrZFzDCEkyqwU6oOQ,203
220
- bbot/presets/web/dotnet-audit.yml,sha256=7ZlE7Q3F1p5g6AO33-m1lPzPW12_tRKEDXy4eaLXlCk,335
220
+ bbot/presets/web/dotnet-audit.yml,sha256=FdUaBUftkzr9TX3evpJec3oZTSU4o77FVKwTgWqyxHU,438
221
221
  bbot/presets/web/iis-shortnames.yml,sha256=EcYKMpl-cI8Xb79_u4wQS42yFXxDpLH9OqINcFUXoTE,176
222
222
  bbot/presets/web/paramminer.yml,sha256=VuiXkxrOAeqXlk9Gmuo938_REvbbTH6-lxTrlyWAvZ4,163
223
223
  bbot/presets/web-basic.yml,sha256=6YWSYclbuf9yr8-gILDpLvOUj5QjP4rlarm5_d5iBFw,79
@@ -391,7 +391,7 @@ bbot/test/test_step_2/module_tests/test_module_subdomaincenter.py,sha256=KXprbHa
391
391
  bbot/test/test_step_2/module_tests/test_module_subdomainradar.py,sha256=c6aUKr4yrGJqrQP0hOaP6Ao4-PQn1N_IlaqSw6E-xW8,10672
392
392
  bbot/test/test_step_2/module_tests/test_module_subdomains.py,sha256=r1zCmw5ZZ_0wA7L7cDg9dpgdpRigjQXhf-Zm7P4ya9Q,1108
393
393
  bbot/test/test_step_2/module_tests/test_module_teams.py,sha256=r91ZZxhj3pEhKnjr1jGwhcqOPXTqNJNupC1CDKccfH8,1638
394
- bbot/test/test_step_2/module_tests/test_module_telerik.py,sha256=_EynKEnQXIV0y2YC0VzGozSCqp9VCLWYqTX8OCv85SU,7752
394
+ bbot/test/test_step_2/module_tests/test_module_telerik.py,sha256=fnOzpw9VbqSj1o7ERpq9cS1UJqE0BYxM2GHzILwyFPs,10742
395
395
  bbot/test/test_step_2/module_tests/test_module_trickest.py,sha256=6mTYH6fIah-WbKnFI-_WZBwRdKFi-oeWyVtl1n0nVAU,1630
396
396
  bbot/test/test_step_2/module_tests/test_module_trufflehog.py,sha256=H8bvRfeUrDgIcJFxQIv3RyksSTKdjG8AsKOqK-2ISjU,95420
397
397
  bbot/test/test_step_2/module_tests/test_module_txt.py,sha256=R-EBfEZM0jwY2yuVyfYhoccDOl0Y2uQZSkXQ1HyinUA,247
@@ -422,8 +422,8 @@ bbot/wordlists/raft-small-extensions-lowercase_CLEANED.txt,sha256=ZSIVebs7ptMvHx
422
422
  bbot/wordlists/top_open_ports_nmap.txt,sha256=LmdFYkfapSxn1pVuQC2LkOIY2hMLgG-Xts7DVtYzweM,42727
423
423
  bbot/wordlists/valid_url_schemes.txt,sha256=0B_VAr9Dv7aYhwi6JSBDU-3M76vNtzN0qEC_RNLo7HE,3310
424
424
  bbot/wordlists/wordninja_dns.txt.gz,sha256=DYHvvfW0TvzrVwyprqODAk4tGOxv5ezNmCPSdPuDUnQ,570241
425
- bbot-2.3.1.dist-info/LICENSE,sha256=GzeCzK17hhQQDNow0_r0L8OfLpeTKQjFQwBQU7ZUymg,32473
426
- bbot-2.3.1.dist-info/METADATA,sha256=yTl9SYJxb7JTuiujOZfc48QrUoxh0y8R4JvQgWuGeRQ,18216
427
- bbot-2.3.1.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
428
- bbot-2.3.1.dist-info/entry_points.txt,sha256=cWjvcU_lLrzzJgjcjF7yeGuRA_eDS8pQ-kmPUAyOBfo,38
429
- bbot-2.3.1.dist-info/RECORD,,
425
+ bbot-2.3.1.5818rc0.dist-info/LICENSE,sha256=GzeCzK17hhQQDNow0_r0L8OfLpeTKQjFQwBQU7ZUymg,32473
426
+ bbot-2.3.1.5818rc0.dist-info/METADATA,sha256=crcIDiczOiK8BW38L6ixKnNS5H45-zOoqceUERZTbLw,18224
427
+ bbot-2.3.1.5818rc0.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
428
+ bbot-2.3.1.5818rc0.dist-info/entry_points.txt,sha256=cWjvcU_lLrzzJgjcjF7yeGuRA_eDS8pQ-kmPUAyOBfo,38
429
+ bbot-2.3.1.5818rc0.dist-info/RECORD,,