Skip to content

Commit 0ae6d90

Browse files
authored
fix(fuzz): use actual parameter for frequency dedupe (projectdiscovery#7037)
Fix numeric path fuzz dedupe by using actualParameter for frequency checks and add regression tests for numeric index and actual value behavior.
1 parent 67e8806 commit 0ae6d90

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

pkg/fuzz/parts.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ func (rule *Rule) execWithInput(input *ExecuteRuleInput, httpReq *retryablehttp.
162162
// If the parameter is frequent, skip it if the option is enabled
163163
if rule.options.FuzzParamsFrequency != nil {
164164
if rule.options.FuzzParamsFrequency.IsParameterFrequent(
165-
parameter,
165+
actualParameter,
166166
httpReq.String(),
167167
rule.options.TemplateID,
168168
) {

pkg/fuzz/parts_frequency_test.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package fuzz
2+
3+
import (
4+
"net/http"
5+
"testing"
6+
7+
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz/frequency"
8+
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
9+
retryablehttp "github.com/projectdiscovery/retryablehttp-go"
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
// TestExecWithInputDoesNotUseNumericParameterIndexForFrequency verifies frequency
14+
// checks do not key on numeric path segment indexes.
15+
func TestExecWithInputDoesNotUseNumericParameterIndexForFrequency(t *testing.T) {
16+
tracker := frequency.New(64, 1)
17+
defer tracker.Close()
18+
19+
const target = "https://example.com/users/55"
20+
const templateID = "tmpl-frequency-check"
21+
22+
req, err := retryablehttp.NewRequest(http.MethodGet, target, nil)
23+
require.NoError(t, err)
24+
25+
tracker.MarkParameter("2", req.String(), templateID)
26+
27+
called := false
28+
rule := &Rule{
29+
options: &protocols.ExecutorOptions{
30+
TemplateID: templateID,
31+
FuzzParamsFrequency: tracker,
32+
},
33+
}
34+
input := &ExecuteRuleInput{
35+
Callback: func(GeneratedRequest) bool {
36+
called = true
37+
return true
38+
},
39+
}
40+
41+
err = rule.execWithInput(input, req, nil, nil, "2", "55", "", "", "", "")
42+
require.NoError(t, err)
43+
require.True(t, called, "numeric path index should not be used as frequency key")
44+
}
45+
46+
// TestExecWithInputSkipsWhenActualParameterIsFrequent verifies requests are
47+
// skipped when the normalized parameter value is marked frequent.
48+
func TestExecWithInputSkipsWhenActualParameterIsFrequent(t *testing.T) {
49+
tracker := frequency.New(64, 1)
50+
defer tracker.Close()
51+
52+
const target = "https://example.com/users/55"
53+
const templateID = "tmpl-frequency-check"
54+
55+
req, err := retryablehttp.NewRequest(http.MethodGet, target, nil)
56+
require.NoError(t, err)
57+
58+
tracker.MarkParameter("55", req.String(), templateID)
59+
60+
called := false
61+
rule := &Rule{
62+
options: &protocols.ExecutorOptions{
63+
TemplateID: templateID,
64+
FuzzParamsFrequency: tracker,
65+
},
66+
}
67+
input := &ExecuteRuleInput{
68+
Callback: func(GeneratedRequest) bool {
69+
called = true
70+
return true
71+
},
72+
}
73+
74+
err = rule.execWithInput(input, req, nil, nil, "2", "55", "", "", "", "")
75+
require.NoError(t, err)
76+
require.False(t, called, "frequent actual parameter should be skipped")
77+
}

0 commit comments

Comments
 (0)