diff --git a/http_modifier.go b/http_modifier.go index 8d000ee4..776db6a9 100644 --- a/http_modifier.go +++ b/http_modifier.go @@ -16,6 +16,7 @@ func NewHTTPModifier(config *HTTPModifierConfig) *HTTPModifier { if len(config.urlRegexp) == 0 && len(config.urlNegativeRegexp) == 0 && len(config.urlRewrite) == 0 && + len(config.headerRewrite) == 0 && len(config.headerFilters) == 0 && len(config.headerNegativeFilters) == 0 && len(config.headerHashFilters) == 0 && @@ -153,5 +154,19 @@ func (m *HTTPModifier) Rewrite(payload []byte) (response []byte) { } } + if len(m.config.headerRewrite) > 0 { + for _, f := range m.config.headerRewrite { + value := proto.Header(payload, f.header) + if len(value) == 0 { + break + } + + if f.src.Match(value) { + newValue := f.src.ReplaceAll(value, f.target) + payload = proto.SetHeader(payload, f.header, newValue) + } + } + } + return payload } diff --git a/http_modifier_settings.go b/http_modifier_settings.go index 3bea9f9e..ba0f0e0b 100644 --- a/http_modifier_settings.go +++ b/http_modifier_settings.go @@ -13,6 +13,7 @@ type HTTPModifierConfig struct { urlNegativeRegexp HTTPUrlRegexp urlRegexp HTTPUrlRegexp urlRewrite UrlRewriteMap + headerRewrite HeaderRewriteMap headerFilters HTTPHeaderFilters headerNegativeFilters HTTPHeaderFilters headerHashFilters HTTPHashFilters @@ -196,6 +197,43 @@ func (r *UrlRewriteMap) Set(value string) error { return nil } +// +// Handling of --http-rewrite-header option +// +type headerRewrite struct { + header []byte + src *regexp.Regexp + target []byte +} + +type HeaderRewriteMap []headerRewrite + +func (r *HeaderRewriteMap) String() string { + return fmt.Sprint(*r) +} + +func (r *HeaderRewriteMap) Set(value string) error { + headerArr := strings.SplitN(value, ":", 2) + if len(headerArr) < 2 { + return errors.New("need both header, regexp and rewrite target, colon-delimited (ex. Header: regexp,target)") + } + + header := headerArr[0] + valArr := strings.SplitN(strings.TrimSpace(headerArr[1]), ",", 2) + + if len(valArr) < 2 { + return errors.New("need both header, regexp and rewrite target, colon-delimited (ex. Header: regexp,target)") + } + + regexp, err := regexp.Compile(valArr[0]) + if err != nil { + return err + } + *r = append(*r, headerRewrite{header: []byte(header), src: regexp, target: []byte(valArr[1])}) + return nil +} + + // // Handling of --http-allow-url option // diff --git a/http_modifier_test.go b/http_modifier_test.go index 343be5fc..6e4ee488 100644 --- a/http_modifier_test.go +++ b/http_modifier_test.go @@ -107,6 +107,27 @@ func TestHTTPModifierURLRewrite(t *testing.T) { } } +func TestHTTPModifierHeaderRewrite(t *testing.T) { + var header, newHeader []byte + + rewrites := HeaderRewriteMap{} + payload := []byte("GET / HTTP/1.1\r\nContent-Length: 7\r\nHost: www.w3.org\r\n\r\na=1&b=2") + + err := rewrites.Set("Host: (.*).w3.org,$1.beta.w3.org") + if err != nil { + t.Error("Should not error", err) + } + + modifier := NewHTTPModifier(&HTTPModifierConfig{ + headerRewrite: rewrites, + }) + + header = []byte("www.beta.w3.org") + if newHeader = proto.Header(modifier.Rewrite(payload), []byte("Host")); !bytes.Equal(newHeader, header) { + t.Error("Request header should have been rewritten, wasn't", string(newHeader), string(header)) + } +} + func TestHTTPModifierHeaderHashFilters(t *testing.T) { filters := HTTPHashFilters{} filters.Set("Header2:1/2") diff --git a/settings.go b/settings.go index a44aee1d..654b1dbd 100644 --- a/settings.go +++ b/settings.go @@ -148,6 +148,8 @@ func init() { flag.Var(&Settings.modifierConfig.headers, "http-set-header", "Inject additional headers to http reqest:\n\tgor --input-raw :8080 --output-http staging.com --http-set-header 'User-Agent: Gor'") flag.Var(&Settings.modifierConfig.headers, "output-http-header", "WARNING: `--output-http-header` DEPRECATED, use `--http-set-header` instead") + flag.Var(&Settings.modifierConfig.headerRewrite, "http-rewrite-header", "Rewrite the request header based on a mapping:\n\tgor --input-raw :8080 --output-http staging.com --http-rewrite-header Host: (.*).example.com,$1.beta.example.com") + flag.Var(&Settings.modifierConfig.params, "http-set-param", "Set request url param, if param already exists it will be overwritten:\n\tgor --input-raw :8080 --output-http staging.com --http-set-param api_key=1") flag.Var(&Settings.modifierConfig.methods, "http-allow-method", "Whitelist of HTTP methods to replay. Anything else will be dropped:\n\tgor --input-raw :8080 --output-http staging.com --http-allow-method GET --http-allow-method OPTIONS")