mirror of https://github.com/daffainfo/nuclei.git
Added redirected matched URL + stop-at-first-match for redirect chains (#2050)
* Added redirected matched URL + stop-at-first-match for redirect chains * Pleasing go-linterdev
parent
8723a1fd70
commit
be5f1a7623
|
@ -0,0 +1,18 @@
|
||||||
|
id: redirect-match-url
|
||||||
|
|
||||||
|
info:
|
||||||
|
name: Redirect Match URL
|
||||||
|
author: pdteam
|
||||||
|
severity: info
|
||||||
|
|
||||||
|
requests:
|
||||||
|
- method: GET
|
||||||
|
path:
|
||||||
|
- "{{BaseURL}}"
|
||||||
|
stop-at-first-match: true # Confirm stop-at-first-match
|
||||||
|
redirects: true # Confirm redirected URL matched value
|
||||||
|
max-redirects: 3
|
||||||
|
matchers:
|
||||||
|
- type: word
|
||||||
|
words:
|
||||||
|
- "This is test redirects matcher text"
|
|
@ -50,6 +50,7 @@ var httpTestcases = map[string]testutils.TestCase{
|
||||||
"http/variables.yaml": &httpVariables{},
|
"http/variables.yaml": &httpVariables{},
|
||||||
"http/get-override-sni.yaml": &httpSniAnnotation{},
|
"http/get-override-sni.yaml": &httpSniAnnotation{},
|
||||||
"http/get-sni.yaml": &customCLISNI{},
|
"http/get-sni.yaml": &customCLISNI{},
|
||||||
|
"http/redirect-match-url.yaml": &httpRedirectMatchURL{},
|
||||||
"http/get-sni-unsafe.yaml": &customCLISNIUnsafe{},
|
"http/get-sni-unsafe.yaml": &customCLISNIUnsafe{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -858,6 +859,35 @@ func (h *httpSniAnnotation) Execute(filePath string) error {
|
||||||
return expectResultsCount(results, 1)
|
return expectResultsCount(results, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type httpRedirectMatchURL struct{}
|
||||||
|
|
||||||
|
// Execute executes a test case and returns an error if occurred
|
||||||
|
func (h *httpRedirectMatchURL) Execute(filePath string) error {
|
||||||
|
router := httprouter.New()
|
||||||
|
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
|
http.Redirect(w, r, "/redirected", http.StatusFound)
|
||||||
|
_, _ = w.Write([]byte("This is test redirects matcher text"))
|
||||||
|
})
|
||||||
|
router.GET("/redirected", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
|
fmt.Fprintf(w, "This is test redirects matcher text")
|
||||||
|
})
|
||||||
|
ts := httptest.NewServer(router)
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug, "-no-meta")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := expectResultsCount(results, 1); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if results[0] != fmt.Sprintf("%s/redirected", ts.URL) {
|
||||||
|
return fmt.Errorf("mismatched url found: %s", results[0])
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type customCLISNIUnsafe struct{}
|
type customCLISNIUnsafe struct{}
|
||||||
|
|
||||||
// Execute executes a test case and returns an error if occurred
|
// Execute executes a test case and returns an error if occurred
|
||||||
|
|
|
@ -555,6 +555,12 @@ func (request *Request) executeRequest(reqURL string, generatedRequest *generate
|
||||||
if generatedRequest.request != nil {
|
if generatedRequest.request != nil {
|
||||||
matchedURL = generatedRequest.request.URL.String()
|
matchedURL = generatedRequest.request.URL.String()
|
||||||
}
|
}
|
||||||
|
// Give precedence to the final URL from response
|
||||||
|
if response.resp.Request != nil {
|
||||||
|
if responseURL := response.resp.Request.URL.String(); responseURL != "" {
|
||||||
|
matchedURL = responseURL
|
||||||
|
}
|
||||||
|
}
|
||||||
finalEvent := make(output.InternalEvent)
|
finalEvent := make(output.InternalEvent)
|
||||||
|
|
||||||
outputEvent := request.responseToDSLMap(response.resp, reqURL, matchedURL, tostring.UnsafeToString(dumpedRequest), tostring.UnsafeToString(response.fullResponse), tostring.UnsafeToString(response.body), tostring.UnsafeToString(response.headers), duration, generatedRequest.meta)
|
outputEvent := request.responseToDSLMap(response.resp, reqURL, matchedURL, tostring.UnsafeToString(dumpedRequest), tostring.UnsafeToString(response.fullResponse), tostring.UnsafeToString(response.body), tostring.UnsafeToString(response.headers), duration, generatedRequest.meta)
|
||||||
|
@ -598,6 +604,11 @@ func (request *Request) executeRequest(reqURL string, generatedRequest *generate
|
||||||
dumpResponse(event, request, response.fullResponse, formedURL, responseContentType, isResponseTruncated, reqURL)
|
dumpResponse(event, request, response.fullResponse, formedURL, responseContentType, isResponseTruncated, reqURL)
|
||||||
|
|
||||||
callback(event)
|
callback(event)
|
||||||
|
|
||||||
|
// Skip further responses if we have stop-at-first-match and a match
|
||||||
|
if (request.options.Options.StopAtFirstMatch || request.options.StopAtFirstMatch || request.StopAtFirstMatch) && len(event.Results) > 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue