Skip to content

Commit eb0f07c

Browse files
authored
Merge pull request #2712 from blacklanternsecurity/lightfuzz-performance
Add default WAF filter for lightfuzz
2 parents 2a76775 + cb65410 commit eb0f07c

8 files changed

Lines changed: 106 additions & 5 deletions

File tree

bbot/core/helpers/interactsh.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,9 @@ async def poll(self):
234234

235235
try:
236236
r = await self.parent_helper.request(
237-
f"https://{self.server}/poll?id={self.correlation_id}&secret={self.secret}", headers=headers
237+
f"https://{self.server}/poll?id={self.correlation_id}&secret={self.secret}",
238+
headers=headers,
239+
timeout=15,
238240
)
239241
if r is None:
240242
raise InteractshError("Error polling interact.sh: No response from server")

bbot/modules/lightfuzz/lightfuzz.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ class lightfuzz(BaseModule):
1313
"force_common_headers": False,
1414
"enabled_submodules": ["sqli", "cmdi", "xss", "path", "ssti", "crypto", "serial", "esi"],
1515
"disable_post": False,
16+
"avoid_wafs": True,
1617
}
1718
options_desc = {
1819
"force_common_headers": "Force emit commonly exploitable parameters that may be difficult to detect",
1920
"enabled_submodules": "A list of submodules to enable. Empty list enabled all modules.",
2021
"disable_post": "Disable processing of POST parameters, avoiding form submissions.",
22+
"avoid_wafs": "Avoid running against confirmed WAFs, which are likely to block lightfuzz requests",
2123
}
2224

2325
meta = {
@@ -38,6 +40,7 @@ async def setup(self):
3840
self.disable_post = self.config.get("disable_post", False)
3941
self.enabled_submodules = self.config.get("enabled_submodules")
4042
self.interactsh_disable = self.scan.config.get("interactsh_disable", False)
43+
self.avoid_wafs = self.scan.config.get("avoid_wafs", True)
4144
self.submodules = {}
4245

4346
if not self.enabled_submodules:
@@ -167,8 +170,16 @@ async def finish(self):
167170
except InteractshError as e:
168171
self.debug(f"Error in interact.sh: {e}")
169172

170-
# If we've disabled fuzzing POST parameters, back out of POSTPARAM WEB_PARAMETER events as quickly as possible
171173
async def filter_event(self, event):
174+
# Unless configured specifically to do so, avoid running against confirmed WAFs
175+
if self.avoid_wafs and "waf" in event.tags:
176+
# Use parsed_url.geturl() for both URL and WEB_PARAMETER events
177+
parsed_url = getattr(event, "parsed_url", None)
178+
url = parsed_url.geturl() if parsed_url else "unknown"
179+
self.debug(f"Skipping {event.type} because it is likely to be blocked by a WAF. URL: {url}")
180+
return False
181+
182+
# If we've disabled fuzzing POST parameters, back out of POSTPARAM WEB_PARAMETER events as quickly as possible
172183
if event.type == "WEB_PARAMETER" and self.disable_post and event.data["type"] == "POSTPARAM":
173184
return False, "POST parameter disabled in lightfuzz module"
174185
return True

bbot/presets/web/lightfuzz-heavy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
description: Discover web parameters and lightly fuzz them for vulnerabilities, with more intense discovery techniques, including POST parameters, which are more invasive. Uses all lightfuzz modules, and adds paramminer modules for parameter discovery.
1+
description: Discover web parameters and lightly fuzz them for vulnerabilities, with more intense discovery techniques, including POST parameters, which are more invasive. Uses all lightfuzz modules, and adds paramminer modules for parameter discovery. Avoids running against confirmed WAFs.
22

33
include:
44
- lightfuzz-medium

bbot/presets/web/lightfuzz-light.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ config:
1212
lightfuzz:
1313
enabled_submodules: [path,sqli,xss] # only look for the most common vulnerabilities
1414
disable_post: True # don't send POST requests (less aggressive)
15+
avoid_wafs: True
1516

1617
conditions:
1718
- |

bbot/presets/web/lightfuzz-medium.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
description: Discover web parameters and lightly fuzz them for vulnerabilities. Uses all lightfuzz modules, without some of the more intense discovery techniques. Does not send POST requests. This is the default lightfuzz preset; if you're not sure which one to use, this is a good starting point.
1+
description: Discover web parameters and lightly fuzz them for vulnerabilities. Uses all lightfuzz modules, without some of the more intense discovery techniques. Does not send POST requests. This is the default lightfuzz preset; if you're not sure which one to use, this is a good starting point. Avoids running against confirmed WAFs.
22

33
include:
44
- lightfuzz-light

bbot/presets/web/lightfuzz-superheavy.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ config:
99
lightfuzz:
1010
force_common_headers: True # Fuzz common headers like X-Forwarded-For even if they're not observed on the target
1111
enabled_submodules: [cmdi,crypto,path,serial,sqli,ssti,xss,esi]
12+
avoid_wafs: False
1213
excavate:
1314
speculate_params: True # speculate potential parameters extracted from JSON/XML web responses

bbot/presets/web/lightfuzz-xss.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
description: Discover web parameters and lightly fuzz them, limited to just GET-based xss vulnerabilities. This is an example of a custom lightfuzz preset, selectively enabling a single lightfuzz module.
1+
description: Discover web parameters and lightly fuzz them, limited to just GET-based xss vulnerabilities. Avoids running against confirmed WAFs. This is an example of a custom lightfuzz preset, selectively enabling a single lightfuzz module.
22

33
modules:
44
- httpx

bbot/test/test_step_2/module_tests/test_module_lightfuzz.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2060,3 +2060,89 @@ class Test_Lightfuzz_envelope_isolation_paddingoracle_reflecting(Test_Lightfuzz_
20602060
}
20612061
},
20622062
}
2063+
2064+
2065+
# Test filter_event method with WAF tags
2066+
class Test_Lightfuzz_filter_event(ModuleTestBase):
2067+
targets = ["http://127.0.0.1:8888"]
2068+
modules_overrides = ["httpx", "lightfuzz"]
2069+
config_overrides = {
2070+
"interactsh_disable": True,
2071+
"modules": {
2072+
"lightfuzz": {
2073+
"enabled_submodules": ["xss"],
2074+
"avoid_wafs": True,
2075+
}
2076+
},
2077+
}
2078+
2079+
async def setup_after_prep(self, module_test):
2080+
# Create test events with WAF tags
2081+
self.url_event_with_waf = module_test.scan.make_event(
2082+
"http://127.0.0.1:8888/",
2083+
"URL",
2084+
module_test.scan.root_event,
2085+
module="httpx",
2086+
tags=["status-200", "distance-0", "waf"],
2087+
)
2088+
2089+
self.web_param_event_with_waf = module_test.scan.make_event(
2090+
{
2091+
"host": "127.0.0.1",
2092+
"type": "GETPARAM",
2093+
"name": "test",
2094+
"original_value": "value",
2095+
"url": "http://127.0.0.1:8888/",
2096+
"description": "Test parameter",
2097+
},
2098+
"WEB_PARAMETER",
2099+
module_test.scan.root_event,
2100+
module="excavate",
2101+
tags=["distance-0", "waf"],
2102+
)
2103+
2104+
self.url_event_without_waf = module_test.scan.make_event(
2105+
"http://127.0.0.1:8888/",
2106+
"URL",
2107+
module_test.scan.root_event,
2108+
module="httpx",
2109+
tags=["status-200", "distance-0"],
2110+
)
2111+
2112+
self.web_param_event_without_waf = module_test.scan.make_event(
2113+
{
2114+
"host": "127.0.0.1",
2115+
"type": "GETPARAM",
2116+
"name": "test",
2117+
"original_value": "value",
2118+
"url": "http://127.0.0.1:8888/",
2119+
"description": "Test parameter",
2120+
},
2121+
"WEB_PARAMETER",
2122+
module_test.scan.root_event,
2123+
module="excavate",
2124+
tags=["distance-0"],
2125+
)
2126+
2127+
async def test_filter_event(self, module_test):
2128+
lightfuzz_module = module_test.scan.modules["lightfuzz"]
2129+
2130+
# Test URL event with WAF tag - should be filtered out
2131+
result = await lightfuzz_module.filter_event(self.url_event_with_waf)
2132+
assert result is False, "URL event with waf tag should be filtered out"
2133+
2134+
# Test WEB_PARAMETER event with WAF tag - should be filtered out
2135+
result = await lightfuzz_module.filter_event(self.web_param_event_with_waf)
2136+
assert result is False, "WEB_PARAMETER event with waf tag should be filtered out"
2137+
2138+
# Test URL event without WAF tag - should not be filtered
2139+
result = await lightfuzz_module.filter_event(self.url_event_without_waf)
2140+
assert result is True, "URL event without WAF tag should not be filtered"
2141+
2142+
# Test WEB_PARAMETER event without WAF tag - should not be filtered
2143+
result = await lightfuzz_module.filter_event(self.web_param_event_without_waf)
2144+
assert result is True, "WEB_PARAMETER event without WAF tag should not be filtered"
2145+
2146+
def check(self, module_test, events):
2147+
# This test doesn't need to check events since it's testing the filter method directly
2148+
pass

0 commit comments

Comments
 (0)