Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/pkg/fuzz/component/headers.go
2070 views
1
package component
2
3
import (
4
"context"
5
"strings"
6
7
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz/dataformat"
8
"github.com/projectdiscovery/retryablehttp-go"
9
)
10
11
// Header is a component for a request header
12
type Header struct {
13
value *Value
14
15
req *retryablehttp.Request
16
}
17
18
var _ Component = &Header{}
19
20
// NewHeader creates a new header component
21
func NewHeader() *Header {
22
return &Header{}
23
}
24
25
// Name returns the name of the component
26
func (q *Header) Name() string {
27
return RequestHeaderComponent
28
}
29
30
// Parse parses the component and returns the
31
// parsed component
32
func (q *Header) Parse(req *retryablehttp.Request) (bool, error) {
33
q.req = req
34
q.value = NewValue("")
35
36
parsedHeaders := make(map[string]interface{})
37
for key, value := range req.Header {
38
if len(value) == 1 {
39
parsedHeaders[key] = value[0]
40
continue
41
}
42
parsedHeaders[key] = value
43
}
44
q.value.SetParsed(dataformat.KVMap(parsedHeaders), "")
45
return true, nil
46
}
47
48
// Iterate iterates through the component
49
func (q *Header) Iterate(callback func(key string, value interface{}) error) (errx error) {
50
q.value.parsed.Iterate(func(key string, value any) bool {
51
// Skip ignored headers
52
if _, ok := defaultIgnoredHeaderKeys[key]; ok {
53
return ok
54
}
55
if err := callback(key, value); err != nil {
56
errx = err
57
return false
58
}
59
return true
60
})
61
return
62
}
63
64
// SetValue sets a value in the component
65
// for a key
66
func (q *Header) SetValue(key string, value string) error {
67
if !q.value.SetParsedValue(key, value) {
68
return ErrSetValue
69
}
70
return nil
71
}
72
73
// Delete deletes a key from the component
74
func (q *Header) Delete(key string) error {
75
if !q.value.Delete(key) {
76
return ErrKeyNotFound
77
}
78
return nil
79
}
80
81
// Rebuild returns a new request with the
82
// component rebuilt
83
func (q *Header) Rebuild() (*retryablehttp.Request, error) {
84
cloned := q.req.Clone(context.Background())
85
q.value.parsed.Iterate(func(key string, value any) bool {
86
if strings.TrimSpace(key) == "" {
87
return true
88
}
89
if strings.EqualFold(key, "Host") {
90
return true
91
}
92
if vx, ok := IsTypedSlice(value); ok {
93
// convert to []interface{}
94
value = vx
95
}
96
if v, ok := value.([]interface{}); ok {
97
for _, vv := range v {
98
cloned.Header.Add(key, vv.(string))
99
}
100
return true
101
}
102
cloned.Header.Set(key, value.(string))
103
return true
104
})
105
return cloned, nil
106
}
107
108
// Clones current state of this component
109
func (q *Header) Clone() Component {
110
return &Header{
111
value: q.value.Clone(),
112
req: q.req.Clone(context.Background()),
113
}
114
}
115
116
// A list of headers that are essential to the request and
117
// must not be fuzzed.
118
var defaultIgnoredHeaderKeys = map[string]struct{}{
119
"Accept-Charset": {},
120
"Accept-Datetime": {},
121
"Accept-Encoding": {},
122
"Accept-Language": {},
123
"Accept": {},
124
"Access-Control-Request-Headers": {},
125
"Access-Control-Request-Method": {},
126
"Authorization": {},
127
"Cache-Control": {},
128
"Connection": {},
129
"Cookie": {},
130
"Content-Length": {},
131
"Content-Type": {},
132
"Date": {},
133
"Dnt": {},
134
"Expect": {},
135
"Forwarded": {},
136
"From": {},
137
"Host": {},
138
"If-Match": {},
139
"If-Modified-Since": {},
140
"If-None-Match": {},
141
"If-Range": {},
142
"If-Unmodified-Since": {},
143
"Max-Forwards": {},
144
"Pragma": {},
145
"Priority": {},
146
"Proxy-Authorization": {},
147
"Range": {},
148
"Sec-Ch-Ua": {},
149
"Sec-Ch-Ua-Mobile": {},
150
"Sec-Ch-Ua-Platform": {},
151
"Sec-Fetch-Dest": {},
152
"Sec-Fetch-Mode": {},
153
"Sec-Fetch-Site": {},
154
"Sec-Fetch-User": {},
155
"TE": {},
156
"Upgrade": {},
157
"Via": {},
158
"Warning": {},
159
"Upgrade-Insecure-Requests": {},
160
"X-CSRF-Token": {},
161
"X-Requested-With": {},
162
"Strict-Transport-Security": {},
163
"Content-Security-Policy": {},
164
"X-Content-Type-Options": {},
165
"X-Frame-Options": {},
166
"X-XSS-Protection": {},
167
"Public-Key-Pins": {},
168
"Referrer-Policy": {},
169
"Access-Control-Allow-Origin": {},
170
"Access-Control-Allow-Credentials": {},
171
"Access-Control-Expose-Headers": {},
172
"Access-Control-Max-Age": {},
173
"Access-Control-Allow-Methods": {},
174
"Access-Control-Allow-Headers": {},
175
"Server": {},
176
"X-Powered-By": {},
177
"X-AspNet-Version": {},
178
"X-AspNetMvc-Version": {},
179
"ETag": {},
180
"Vary": {},
181
"Expires": {},
182
"Last-Modified": {},
183
"X-Cache": {},
184
"X-Proxy-ID": {},
185
"CF-Ray": {}, // Cloudflare
186
"X-Served-By": {}, // Varnish, etc.
187
"X-Cache-Hits": {},
188
"Content-Encoding": {},
189
"Transfer-Encoding": {},
190
"Location": {},
191
"WWW-Authenticate": {},
192
"Proxy-Authenticate": {},
193
"X-Access-Token": {},
194
"X-Refresh-Token": {},
195
"Link": {},
196
"X-Content-Duration": {},
197
"X-UA-Compatible": {},
198
"X-RateLimit-Limit": {}, // Rate limiting header
199
"X-RateLimit-Remaining": {}, // Rate limiting header
200
"X-RateLimit-Reset": {}, // Rate limiting header
201
}
202
203