Use constant time string compare for match value

Fixes #364
This commit is contained in:
Cameron Moore 2019-12-10 22:21:30 -06:00
parent c47c06e822
commit 31e76bcd00
2 changed files with 21 additions and 1 deletions

View file

@ -6,6 +6,7 @@ import (
"crypto/sha1" "crypto/sha1"
"crypto/sha256" "crypto/sha256"
"crypto/sha512" "crypto/sha512"
"crypto/subtle"
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
@ -787,7 +788,7 @@ func (r MatchRule) Evaluate(headers, query, payload *map[string]interface{}, bod
if arg, ok := r.Parameter.Get(headers, query, payload); ok { if arg, ok := r.Parameter.Get(headers, query, payload); ok {
switch r.Type { switch r.Type {
case MatchValue: case MatchValue:
return arg == r.Value, nil return compare(arg, r.Value), nil
case MatchRegex: case MatchRegex:
return regexp.MatchString(r.Regex, arg) return regexp.MatchString(r.Regex, arg)
case MatchHashSHA1: case MatchHashSHA1:
@ -804,6 +805,11 @@ func (r MatchRule) Evaluate(headers, query, payload *map[string]interface{}, bod
return false, nil return false, nil
} }
// compare is a helper function for constant time string comparisons.
func compare(a, b string) bool {
return subtle.ConstantTimeCompare([]byte(a), []byte(b)) == 1
}
// getenv provides a template function to retrieve OS environment variables. // getenv provides a template function to retrieve OS environment variables.
func getenv(s string) string { func getenv(s string) string {
return os.Getenv(s) return os.Getenv(s)

View file

@ -628,3 +628,17 @@ func TestNotRule(t *testing.T) {
} }
} }
} }
func TestCompare(t *testing.T) {
for _, tt := range []struct {
a, b string
ok bool
}{
{"abcd", "abcd", true},
{"zyxw", "abcd", false},
} {
if ok := compare(tt.a, tt.b); ok != tt.ok {
t.Errorf("compare failed for %q and %q: got %v\n", tt.a, tt.b, ok)
}
}
}