mirror of
https://github.com/buger/goreplay.git
synced 2024-04-21 12:32:02 +00:00
Filter requests using regex on base64 decoded userId:passwd of basic auth (#475)
Example snippet: --http-basic-auth-filter "^customer[0-9].*"
This commit is contained in:
committed by
Leonid Bugaev
parent
16b6a3cc31
commit
9cf1ad65df
@@ -2,7 +2,9 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"hash/fnv"
|
||||
"encoding/base64"
|
||||
|
||||
"github.com/buger/goreplay/proto"
|
||||
)
|
||||
@@ -19,6 +21,7 @@ func NewHTTPModifier(config *HTTPModifierConfig) *HTTPModifier {
|
||||
len(config.headerRewrite) == 0 &&
|
||||
len(config.headerFilters) == 0 &&
|
||||
len(config.headerNegativeFilters) == 0 &&
|
||||
len(config.headerBasicAuthFilters) == 0 &&
|
||||
len(config.headerHashFilters) == 0 &&
|
||||
len(config.paramHashFilters) == 0 &&
|
||||
len(config.params) == 0 &&
|
||||
@@ -111,6 +114,23 @@ func (m *HTTPModifier) Rewrite(payload []byte) (response []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
if len(m.config.headerBasicAuthFilters) > 0 {
|
||||
for _, f := range m.config.headerBasicAuthFilters {
|
||||
value := proto.Header(payload, []byte("Authorization"))
|
||||
|
||||
if len(value) > 0 {
|
||||
valueString := string(value)
|
||||
trimmedBasicAuthEncoded := strings.TrimPrefix(valueString, "Basic ")
|
||||
if strings.Compare(valueString, trimmedBasicAuthEncoded) != 0 {
|
||||
decodedAuth, _ := base64.StdEncoding.DecodeString(trimmedBasicAuthEncoded)
|
||||
if !f.regexp.Match(decodedAuth) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(m.config.headerHashFilters) > 0 {
|
||||
for _, f := range m.config.headerHashFilters {
|
||||
value := proto.Header(payload, f.name)
|
||||
|
||||
@@ -10,14 +10,15 @@ import (
|
||||
|
||||
// HTTPModifierConfig holds configuration options for built-in traffic modifier
|
||||
type HTTPModifierConfig struct {
|
||||
urlNegativeRegexp HTTPUrlRegexp
|
||||
urlRegexp HTTPUrlRegexp
|
||||
urlRewrite UrlRewriteMap
|
||||
headerRewrite HeaderRewriteMap
|
||||
headerFilters HTTPHeaderFilters
|
||||
headerNegativeFilters HTTPHeaderFilters
|
||||
headerHashFilters HTTPHashFilters
|
||||
paramHashFilters HTTPHashFilters
|
||||
urlNegativeRegexp HTTPUrlRegexp
|
||||
urlRegexp HTTPUrlRegexp
|
||||
urlRewrite UrlRewriteMap
|
||||
headerRewrite HeaderRewriteMap
|
||||
headerFilters HTTPHeaderFilters
|
||||
headerNegativeFilters HTTPHeaderFilters
|
||||
headerBasicAuthFilters HTTPHeaderBasicAuthFilters
|
||||
headerHashFilters HTTPHashFilters
|
||||
paramHashFilters HTTPHashFilters
|
||||
|
||||
params HTTPParams
|
||||
headers HTTPHeaders
|
||||
@@ -55,6 +56,32 @@ func (h *HTTPHeaderFilters) Set(value string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
// Handling of --http-basic-auth-filter option
|
||||
//
|
||||
type basicAuthFilter struct {
|
||||
regexp *regexp.Regexp
|
||||
}
|
||||
|
||||
// HTTPHeaderFilters holds list of headers and their regexps
|
||||
type HTTPHeaderBasicAuthFilters []basicAuthFilter
|
||||
|
||||
func (h *HTTPHeaderBasicAuthFilters) String() string {
|
||||
return fmt.Sprint(*h)
|
||||
}
|
||||
|
||||
func (h *HTTPHeaderBasicAuthFilters) Set(value string) error {
|
||||
r, err := regexp.Compile(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*h = append(*h, basicAuthFilter{regexp: r})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Handling of --http-allow-header-hash and --http-allow-param-hash options
|
||||
//
|
||||
|
||||
@@ -79,6 +79,45 @@ func TestHTTPModifierHeaderNegativeFilters(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPHeaderBasicAuthFilters(t *testing.T) {
|
||||
filters := HTTPHeaderBasicAuthFilters{}
|
||||
filters.Set("^customer[0-9].*")
|
||||
|
||||
modifier := NewHTTPModifier(&HTTPModifierConfig{
|
||||
headerBasicAuthFilters: filters,
|
||||
})
|
||||
|
||||
//Encoded UserId:Password = customer3:welcome
|
||||
payload := []byte("POST /post HTTP/1.1\r\nContent-Length: 7\r\nAuthorization: Basic Y3VzdG9tZXIzOndlbGNvbWU=\r\n\r\na=1&b=2")
|
||||
if len(modifier.Rewrite(payload)) == 0 {
|
||||
t.Error("Request should pass filters")
|
||||
}
|
||||
|
||||
//customer6:rest@123^TEST
|
||||
payload = []byte("POST /post HTTP/1.1\r\nContent-Length: 88\r\nAuthorization: Basic Y3VzdG9tZXI2OnJlc3RAMTIzXlRFU1Q==\r\n\r\na=1&b=2")
|
||||
if len(modifier.Rewrite(payload)) == 0 {
|
||||
t.Error("Request should pass filters")
|
||||
}
|
||||
|
||||
filters = HTTPHeaderBasicAuthFilters{}
|
||||
// Setting filter that not match our header
|
||||
filters.Set("^(homer simpson|mickey mouse).*")
|
||||
|
||||
modifier = NewHTTPModifier(&HTTPModifierConfig{
|
||||
headerBasicAuthFilters: filters,
|
||||
})
|
||||
|
||||
if len(modifier.Rewrite(payload)) != 0 {
|
||||
t.Error("Request should not pass filters")
|
||||
}
|
||||
|
||||
//mickey mouse:happy123
|
||||
payload = []byte("POST /post HTTP/1.1\r\nContent-Length: 88\r\nAuthorization: Basic bWlja2V5IG1vdXNlOmhhcHB5MTIz\r\n\r\na=1&b=2")
|
||||
if len(modifier.Rewrite(payload)) == 0 {
|
||||
t.Error("Request should pass filters")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPModifierURLRewrite(t *testing.T) {
|
||||
var url, newURL []byte
|
||||
|
||||
|
||||
+4
-1
@@ -178,7 +178,10 @@ func init() {
|
||||
|
||||
flag.Var(&Settings.modifierConfig.headerNegativeFilters, "http-disallow-header", "A regexp to match a specific header against. Requests with matching headers will be dropped:\n\t gor --input-raw :8080 --output-http staging.com --http-disallow-header \"User-Agent: Replayed by Gor\"")
|
||||
|
||||
flag.Var(&Settings.modifierConfig.headerHashFilters, "http-header-limiter", "Takes a fraction of requests, consistently taking or rejecting a request based on the FNV32-1A hash of a specific header:\n\t gor --input-raw :8080 --output-http staging.com --http-header-limiter user-id:25%")
|
||||
flag.Var(&Settings.modifierConfig.headerBasicAuthFilters, "http-basic-auth-filter", "A regexp to match the decoded basic auth string against. Requests with non-matching headers will be dropped:\n\t gor --input-raw :8080 --output-http staging.com --http-basic-auth-filter \"^customer[0-9].*\"")
|
||||
|
||||
flag.Var(&Settings.modifierConfig.headerHashFilters, "http-header-limiter", "Takes a fraction of requests, consistently taking or rejecting a request based on the FNV32-1A hash of a specific header:\n\t gor --input-raw :8080 --output-http staging.com --http-header-limiter user-id:25%")
|
||||
|
||||
flag.Var(&Settings.modifierConfig.headerHashFilters, "output-http-header-hash-filter", "WARNING: `output-http-header-hash-filter` DEPRECATED, use `--http-header-hash-limiter` instead")
|
||||
|
||||
flag.Var(&Settings.modifierConfig.paramHashFilters, "http-param-limiter", "Takes a fraction of requests, consistently taking or rejecting a request based on the FNV32-1A hash of a specific GET param:\n\t gor --input-raw :8080 --output-http staging.com --http-param-limiter user_id:25%")
|
||||
|
||||
Reference in New Issue
Block a user