@@ -16,34 +16,34 @@ func (r *Rule) evaluate(resp Response, urlInjection UrlInjection, ruleName strin
16
16
lengthExpected := false
17
17
heuristicsExpected := map [string ]bool {"responsecode" : false , "responselength" : false , "responsecontent" : false , "responseheader" : false }
18
18
19
+ for _ , match := range r .Heuristics .BaselineMatches {
20
+ heuristicsExpected [strings .ToLower (match )] = true
21
+ }
22
+
19
23
numOfChecks := 0
20
24
21
25
var ruleEvaluation RuleEvaluation
22
26
23
- if r .Expectation .Headers != nil {
27
+ if r .Expectation .Headers != nil || heuristicsExpected [ "responseheader" ] {
24
28
headersExpected = true
25
29
numOfChecks += 1
26
30
}
27
31
28
- if r .Expectation .Contents != nil {
32
+ if r .Expectation .Contents != nil || heuristicsExpected [ "responsecontent" ] {
29
33
bodyExpected = true
30
34
numOfChecks += 1
31
35
}
32
36
33
- if r .Expectation .Codes != nil {
37
+ if r .Expectation .Codes != nil || heuristicsExpected [ "responsecode" ] {
34
38
codeExpected = true
35
39
numOfChecks += 1
36
40
}
37
41
38
- if r .Expectation .Lengths != nil {
42
+ if r .Expectation .Lengths != nil || heuristicsExpected [ "responselength" ] {
39
43
lengthExpected = true
40
44
numOfChecks += 1
41
45
}
42
46
43
- for _ , match := range r .Heuristics .BaselineMatches {
44
- heuristicsExpected [strings .ToLower (match )] = true
45
- }
46
-
47
47
if bodyExpected {
48
48
if matched := r .evaluateContent (resp .Body , heuristicsResponse , baselineResponse , heuristicsExpected ["responsecontent" ]); matched {
49
49
ruleEvaluation .ChecksMatched += 1
@@ -92,13 +92,29 @@ func (r *Rule) evaluate(resp Response, urlInjection UrlInjection, ruleName strin
92
92
}
93
93
94
94
func (r * Rule ) evaluateContent (responseContent string , heuristicsResponse Response , baselineResponse Response , heuristicExpected bool ) bool {
95
+ if heuristicExpected && len (r .Expectation .Contents ) == 0 {
96
+ if heuristicsResponse .Body == baselineResponse .Body {
97
+ // This is a false positive. If the heuristics response, baseline response, and injected response all have the same response content
98
+ // It is not an indication of vulnerable functionality
99
+ if baselineResponse .Body == responseContent {
100
+ return false
101
+ }
102
+ return true
103
+ }
104
+ }
105
+
95
106
for _ , content := range r .Expectation .Contents {
96
107
if strings .Contains (strings .ToLower (responseContent ), strings .ToLower (content )) {
97
108
if ! heuristicExpected {
98
109
return true
99
110
}
100
111
101
112
if heuristicsResponse .Body == baselineResponse .Body {
113
+ // This is a false positive. If the heuristics response, baseline response, and injected response all have the same response content
114
+ // It is not an indication of vulnerable functionality
115
+ if baselineResponse .Body == responseContent {
116
+ return false
117
+ }
102
118
return true
103
119
}
104
120
}
@@ -122,6 +138,17 @@ func (r *Rule) evaluateHeaders(responseHeaders http.Header, heuristicsResponse R
122
138
}
123
139
124
140
func (r * Rule ) evaluateStatusCode (responseCode int , heuristicsResponse Response , baselineResponse Response , heuristicExpected bool ) bool {
141
+ if heuristicExpected && len (r .Expectation .Codes ) == 0 {
142
+ if heuristicsResponse .StatusCode == baselineResponse .StatusCode {
143
+ // This is a false positive. If the heuristics response, baseline response, and injected response all have the same code
144
+ // It is not an indication of vulnerable functionality
145
+ if baselineResponse .StatusCode == responseCode {
146
+ return false
147
+ }
148
+ return true
149
+ }
150
+ }
151
+
125
152
for _ , code := range r .Expectation .Codes {
126
153
statusCode , err := strconv .Atoi (code )
127
154
if err != nil {
@@ -147,6 +174,23 @@ func (r *Rule) evaluateStatusCode(responseCode int, heuristicsResponse Response,
147
174
}
148
175
149
176
func (r * Rule ) evaluateContentLength (responseLength int , heuristicsResponse Response , baselineResponse Response , heuristicExpected bool ) bool {
177
+ if heuristicExpected && len (r .Expectation .Lengths ) == 0 {
178
+ if heuristicsMatch := isLengthWithinTenPercent (heuristicsResponse .ContentLength , baselineResponse .ContentLength ); heuristicsMatch {
179
+
180
+ // This is a false positive. If the heuristics response, baseline response, and injected response all have the same length
181
+ // It is not an indication of vulnerable functionality
182
+ if heuristicsMatch := isLengthWithinTenPercent (baselineResponse .ContentLength , responseLength ); heuristicsMatch {
183
+ fmt .Println (baselineResponse .ContentLength )
184
+ fmt .Println (responseLength )
185
+ fmt .Println (heuristicsResponse .ContentLength )
186
+
187
+ return false
188
+ }
189
+
190
+ return true
191
+ }
192
+ }
193
+
150
194
for _ , length := range r .Expectation .Lengths {
151
195
expectedLength , err := strconv .Atoi (length )
152
196
if err != nil {
@@ -157,10 +201,16 @@ func (r *Rule) evaluateContentLength(responseLength int, heuristicsResponse Resp
157
201
if ! heuristicExpected {
158
202
return true
159
203
}
204
+ }
160
205
161
- if heuristicsMatch := isLengthWithinTenPercent (heuristicsResponse .ContentLength , baselineResponse .ContentLength ); heuristicsMatch {
162
- return true
206
+ if heuristicsMatch := isLengthWithinTenPercent (heuristicsResponse .ContentLength , baselineResponse .ContentLength ); heuristicsMatch {
207
+ // This is a false positive. If the heuristics response, baseline response, and injected response all have the same length
208
+ // It is not an indication of vulnerable functionality
209
+ if heuristicsMatch := isLengthWithinTenPercent (baselineResponse .ContentLength , responseLength ); heuristicsMatch {
210
+ return false
163
211
}
212
+
213
+ return true
164
214
}
165
215
}
166
216
return false
0 commit comments