From 5f0d0faeb76ee6cee489bc3113083c6f0e1c29a6 Mon Sep 17 00:00:00 2001 From: bjhulst Date: Fri, 21 Feb 2020 22:43:19 +0200 Subject: [PATCH] Make defining User-agent header case insensitive #171 (#173) * Takes the User-Agent header from a list. * typo * base * Make defining User-agent header case insensitive #171 * -whitespaces * Make canonical http headers and set default User-Agent only once. * clean-up * formatting, canonical customer headers, docs updated * cleanup * fmt * Checking userdefined headers for excluding in canonicalization. * resolving one conflict * moved logic back and less resolve conflicts Co-authored-by: Joona Hoikkala --- CHANGELOG.md | 3 ++- CONTRIBUTORS.md | 1 + main.go | 27 +++++++++++++++++++++++++-- pkg/runner/simple.go | 8 ++++++-- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13dde4b..716fafd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ - New - Changed - - Write POST request data properly to file when ran with `-od` + - Write POST request data properly to file when ran with `-od`. + - Fixed a bug by using header canonicaliztion related to HTTP headers being case insensitive. - Properly handle relative redirect urls with `-recursion` - Calculate req/sec correctly for when using recursion - When `-request` is used, allow the user to override URL using `-u` diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 01d2ab8..9f5ed1a 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -1,5 +1,6 @@ # Contributors +* [bjhulst](https://github.com/bjhulst) * [ccsplit](https://github.com/ccsplit) * [codingo](https://github.com/codingo) * [delic](https://github.com/delic) diff --git a/main.go b/main.go index 5dd484f..cc1294c 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "fmt" "io/ioutil" "log" + "net/textproto" "net/url" "os" "strconv" @@ -341,15 +342,37 @@ func prepareConfig(parseOpts *cliOptions, conf *ffuf.Config) error { conf.Url = parseOpts.URL } - //Prepare headers + //Prepare headers and make canonical for _, v := range parseOpts.headers { hs := strings.SplitN(v, ":", 2) if len(hs) == 2 { - conf.Headers[strings.TrimSpace(hs[0])] = strings.TrimSpace(hs[1]) + // trim and make canonical + // except if used in custom defined header + var CanonicalNeeded bool = true + for _, a := range conf.CommandKeywords { + if a == hs[0] { + CanonicalNeeded = false + } + } + // check if part of InputProviders + if CanonicalNeeded { + for _, b := range conf.InputProviders { + if b.Keyword == hs[0] { + CanonicalNeeded = false + } + } + } + if CanonicalNeeded { + var CanonicalHeader string = textproto.CanonicalMIMEHeaderKey(strings.TrimSpace(hs[0])) + conf.Headers[CanonicalHeader] = strings.TrimSpace(hs[1]) + } else { + conf.Headers[strings.TrimSpace(hs[0])] = strings.TrimSpace(hs[1]) + } } else { errs.Add(fmt.Errorf("Header defined by -H needs to have a value. \":\" should be used as a separator")) } } + //Prepare delay d := strings.Split(parseOpts.delay, "-") if len(d) > 2 { diff --git a/pkg/runner/simple.go b/pkg/runner/simple.go index 7bf46f6..657b3e9 100644 --- a/pkg/runner/simple.go +++ b/pkg/runner/simple.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "net/http" "net/http/httputil" + "net/textproto" "net/url" "strconv" "strings" @@ -73,7 +74,8 @@ func (r *SimpleRunner) Prepare(input map[string][]byte) (ffuf.Request, error) { req.Method = strings.Replace(req.Method, keyword, string(inputitem), -1) headers := make(map[string]string, 0) for h, v := range req.Headers { - headers[strings.Replace(h, keyword, string(inputitem), -1)] = strings.Replace(v, keyword, string(inputitem), -1) + var CanonicalHeader string = textproto.CanonicalMIMEHeaderKey(strings.Replace(h, keyword, string(inputitem), -1)) + headers[CanonicalHeader] = strings.Replace(v, keyword, string(inputitem), -1) } req.Headers = headers req.Url = strings.Replace(req.Url, keyword, string(inputitem), -1) @@ -93,10 +95,12 @@ func (r *SimpleRunner) Execute(req *ffuf.Request) (ffuf.Response, error) { if err != nil { return ffuf.Response{}, err } - // Add user agent string if not defined + + // set default User-Agent header if not present if _, ok := req.Headers["User-Agent"]; !ok { req.Headers["User-Agent"] = fmt.Sprintf("%s v%s", "Fuzz Faster U Fool", ffuf.VERSION) } + // Handle Go http.Request special cases if _, ok := req.Headers["Host"]; ok { httpreq.Host = req.Headers["Host"]