Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/pkg/protocols/http/build_request_test.go
2070 views
1
package http
2
3
import (
4
"context"
5
"testing"
6
"time"
7
8
"github.com/stretchr/testify/require"
9
10
"github.com/projectdiscovery/nuclei/v3/pkg/model"
11
"github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity"
12
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
13
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
14
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh"
15
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
16
)
17
18
func TestMakeRequestFromModal(t *testing.T) {
19
options := testutils.DefaultOptions
20
21
testutils.Init(options)
22
templateID := "testing-http"
23
request := &Request{
24
ID: templateID,
25
Name: "testing",
26
Path: []string{"{{BaseURL}}/login.php"},
27
Method: HTTPMethodTypeHolder{MethodType: HTTPPost},
28
Body: "username=test&password=pass",
29
Headers: map[string]string{
30
"Content-Type": "application/x-www-form-urlencoded",
31
"Content-Length": "1",
32
},
33
}
34
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
35
ID: templateID,
36
Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
37
})
38
err := request.Compile(executerOpts)
39
require.Nil(t, err, "could not compile http request")
40
41
generator := request.newGenerator(false)
42
inputData, payloads, _ := generator.nextValue()
43
req, err := generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com"), inputData, payloads, map[string]interface{}{})
44
require.Nil(t, err, "could not make http request")
45
if req.request.URL == nil {
46
t.Fatalf("url is nil in generator make")
47
}
48
bodyBytes, _ := req.request.BodyBytes()
49
require.Equal(t, "/login.php", req.request.Path, "could not get correct request path")
50
require.Equal(t, "username=test&password=pass", string(bodyBytes), "could not get correct request body")
51
}
52
53
func TestMakeRequestFromModalTrimSuffixSlash(t *testing.T) {
54
options := testutils.DefaultOptions
55
56
testutils.Init(options)
57
templateID := "testing-http"
58
request := &Request{
59
ID: templateID,
60
Name: "testing",
61
Path: []string{"{{BaseURL}}?query=example"},
62
Method: HTTPMethodTypeHolder{MethodType: HTTPGet},
63
}
64
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
65
ID: templateID,
66
Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
67
})
68
err := request.Compile(executerOpts)
69
require.Nil(t, err, "could not compile http request")
70
71
generator := request.newGenerator(false)
72
inputData, payloads, _ := generator.nextValue()
73
req, err := generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com/test.php"), inputData, payloads, map[string]interface{}{})
74
require.Nil(t, err, "could not make http request")
75
require.Equal(t, "https://example.com/test.php?query=example", req.request.String(), "could not get correct request path")
76
77
generator = request.newGenerator(false)
78
inputData, payloads, _ = generator.nextValue()
79
req, err = generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com/test/"), inputData, payloads, map[string]interface{}{})
80
require.Nil(t, err, "could not make http request")
81
require.Equal(t, "https://example.com/test/?query=example", req.request.String(), "could not get correct request path")
82
}
83
84
func TestMakeRequestFromRawWithPayloads(t *testing.T) {
85
options := testutils.DefaultOptions
86
87
testutils.Init(options)
88
templateID := "testing-http"
89
request := &Request{
90
ID: templateID,
91
Name: "testing",
92
Payloads: map[string]interface{}{
93
"username": []string{"admin"},
94
"password": []string{"admin", "guest", "password", "test", "12345", "123456"},
95
},
96
AttackType: generators.AttackTypeHolder{Value: generators.ClusterBombAttack},
97
Raw: []string{`GET /manager/html HTTP/1.1
98
Host: {{Hostname}}
99
User-Agent: Nuclei - Open-source project (github.com/projectdiscovery/nuclei)
100
Connection: close
101
Authorization: Basic {{username + ':' + password}}
102
Accept-Encoding: gzip`},
103
}
104
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
105
ID: templateID,
106
Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
107
})
108
err := request.Compile(executerOpts)
109
require.Nil(t, err, "could not compile http request")
110
111
generator := request.newGenerator(false)
112
inputData, payloads, _ := generator.nextValue()
113
req, err := generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com"), inputData, payloads, map[string]interface{}{})
114
require.Nil(t, err, "could not make http request")
115
authorization := req.request.Header.Get("Authorization")
116
require.Equal(t, "Basic admin:admin", authorization, "could not get correct authorization headers from raw")
117
118
inputData, payloads, _ = generator.nextValue()
119
req, err = generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com"), inputData, payloads, map[string]interface{}{})
120
require.Nil(t, err, "could not make http request")
121
authorization = req.request.Header.Get("Authorization")
122
require.Equal(t, "Basic admin:guest", authorization, "could not get correct authorization headers from raw")
123
}
124
125
func TestMakeRequestFromRawPayloadExpressions(t *testing.T) {
126
options := testutils.DefaultOptions
127
128
testutils.Init(options)
129
templateID := "testing-http"
130
request := &Request{
131
ID: templateID,
132
Name: "testing",
133
Payloads: map[string]interface{}{
134
"username": []string{"admin"},
135
"password": []string{"admin", "guest", "password", "test", "12345", "123456"},
136
},
137
AttackType: generators.AttackTypeHolder{Value: generators.ClusterBombAttack},
138
Raw: []string{`GET /manager/html HTTP/1.1
139
Host: {{Hostname}}
140
User-Agent: Nuclei - Open-source project (github.com/projectdiscovery/nuclei)
141
Connection: close
142
Authorization: Basic {{base64(username + ':' + password)}}
143
Accept-Encoding: gzip`},
144
}
145
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
146
ID: templateID,
147
Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
148
})
149
err := request.Compile(executerOpts)
150
require.Nil(t, err, "could not compile http request")
151
152
generator := request.newGenerator(false)
153
inputData, payloads, _ := generator.nextValue()
154
req, err := generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com"), inputData, payloads, map[string]interface{}{})
155
require.Nil(t, err, "could not make http request")
156
authorization := req.request.Header.Get("Authorization")
157
require.Equal(t, "Basic YWRtaW46YWRtaW4=", authorization, "could not get correct authorization headers from raw")
158
159
inputData, payloads, _ = generator.nextValue()
160
req, err = generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com"), inputData, payloads, map[string]interface{}{})
161
require.Nil(t, err, "could not make http request")
162
authorization = req.request.Header.Get("Authorization")
163
require.Equal(t, "Basic YWRtaW46Z3Vlc3Q=", authorization, "could not get correct authorization headers from raw")
164
}
165
166
func TestMakeRequestFromModelUniqueInteractsh(t *testing.T) {
167
168
options := testutils.DefaultOptions
169
170
testutils.Init(options)
171
templateID := "testing-unique-interactsh"
172
request := &Request{
173
ID: templateID,
174
Name: "testing",
175
Path: []string{"{{BaseURL}}/?u=http://{{interactsh-url}}/&href=http://{{interactsh-url}}/&action=http://{{interactsh-url}}/&host={{interactsh-url}}"},
176
Method: HTTPMethodTypeHolder{MethodType: HTTPGet},
177
}
178
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
179
ID: templateID,
180
Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
181
})
182
err := request.Compile(executerOpts)
183
require.Nil(t, err, "could not compile http request")
184
185
generator := request.newGenerator(false)
186
187
generator.options.Interactsh, err = interactsh.New(&interactsh.Options{
188
ServerURL: options.InteractshURL,
189
CacheSize: options.InteractionsCacheSize,
190
Eviction: time.Duration(options.InteractionsEviction) * time.Second,
191
CooldownPeriod: time.Duration(options.InteractionsCoolDownPeriod) * time.Second,
192
PollDuration: time.Duration(options.InteractionsPollDuration) * time.Second,
193
DisableHttpFallback: true,
194
})
195
require.Nil(t, err, "could not create interactsh client")
196
197
inputData, payloads, _ := generator.nextValue()
198
got, err := generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com"), inputData, payloads, map[string]interface{}{})
199
require.Nil(t, err, "could not make http request")
200
201
// check if all the interactsh markers are replaced with unique urls
202
require.NotContains(t, got.request.String(), "{{interactsh-url}}", "could not get correct interactsh url")
203
// check the length of returned urls
204
require.Equal(t, len(got.interactshURLs), 4, "could not get correct interactsh url")
205
// check if the interactsh urls are unique
206
require.True(t, areUnique(got.interactshURLs), "interactsh urls are not unique")
207
}
208
209
// areUnique checks if the elements of string slice are unique
210
func areUnique(elements []string) bool {
211
encountered := map[string]bool{}
212
for v := range elements {
213
if encountered[elements[v]] {
214
return false
215
}
216
encountered[elements[v]] = true
217
}
218
return true
219
}
220
221