From 2926a9800b304fc0cfca3b6f4d4f2a04dbe08491 Mon Sep 17 00:00:00 2001 From: Dwi Siswanto Date: Wed, 11 Dec 2024 22:21:39 +0700 Subject: [PATCH] fix(httpclientpool): rebuild malformed Location URL Signed-off-by: Dwi Siswanto --- .../http/httpclientpool/clientpool.go | 30 +++++++++++++++++-- pkg/protocols/http/httpclientpool/errors.go | 7 +++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 pkg/protocols/http/httpclientpool/errors.go diff --git a/pkg/protocols/http/httpclientpool/clientpool.go b/pkg/protocols/http/httpclientpool/clientpool.go index 94ed61ff3f..c5c5d45a5a 100644 --- a/pkg/protocols/http/httpclientpool/clientpool.go +++ b/pkg/protocols/http/httpclientpool/clientpool.go @@ -3,6 +3,7 @@ package httpclientpool import ( "context" "crypto/tls" + "fmt" "net" "net/http" "net/http/cookiejar" @@ -17,14 +18,15 @@ import ( "golang.org/x/net/publicsuffix" "github.com/projectdiscovery/fastdialer/fastdialer/ja3/impersonate" + "github.com/projectdiscovery/nuclei/v3/pkg/prothttpclientpoolocols/common/protocolstate" "github.com/projectdiscovery/nuclei/v3/pkg/protocols" - "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/utils" "github.com/projectdiscovery/nuclei/v3/pkg/types" "github.com/projectdiscovery/nuclei/v3/pkg/types/scanstrategy" "github.com/projectdiscovery/rawhttp" "github.com/projectdiscovery/retryablehttp-go" mapsutil "github.com/projectdiscovery/utils/maps" + urlutil "github.com/projectdiscovery/utils/url" ) var ( @@ -377,7 +379,7 @@ func makeCheckRedirectFunc(redirectType RedirectFlow, maxRedirects int) checkRed } } -func checkMaxRedirects(_ *http.Request, via []*http.Request, maxRedirects int) error { +func checkMaxRedirects(req *http.Request, via []*http.Request, maxRedirects int) error { if maxRedirects == 0 { if len(via) > defaultMaxRedirects { return http.ErrUseLastResponse @@ -388,5 +390,29 @@ func checkMaxRedirects(_ *http.Request, via []*http.Request, maxRedirects int) e if len(via) > maxRedirects { return http.ErrUseLastResponse } + + // NOTE(dwisiswant0): rebuild request URL. See #5900. + if u := req.URL.String(); !isURLEncoded(u) { + parsed, err := urlutil.Parse(u) + if err != nil { + return fmt.Errorf("%w: %w", ErrRebuildURL, err) + } + + req.URL = parsed.URL + } + return nil } + +// isURLEncoded is an helper function to check if the URL is already encoded +// +// NOTE(dwisiswant0): shall we move this under `projectdiscovery/utils/urlutil`? +func isURLEncoded(s string) bool { + decoded, err := url.QueryUnescape(s) + if err != nil { + // If decoding fails, it may indicate a malformed URL/invalid encoding. + return false + } + + return decoded != s +} diff --git a/pkg/protocols/http/httpclientpool/errors.go b/pkg/protocols/http/httpclientpool/errors.go new file mode 100644 index 0000000000..e5c915f93e --- /dev/null +++ b/pkg/protocols/http/httpclientpool/errors.go @@ -0,0 +1,7 @@ +package httpclientpool + +import "errors" + +var ( + ErrRebuildURL = errors.New("could not rebuild request URL") +)