From 31e76bcd008a2d39f6d58a52c7bcf4b99dc9428c Mon Sep 17 00:00:00 2001 From: Cameron Moore Date: Tue, 10 Dec 2019 22:21:30 -0600 Subject: [PATCH] Use constant time string compare for match value Fixes #364 --- hook/hook.go | 8 +++++++- hook/hook_test.go | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/hook/hook.go b/hook/hook.go index 20a2664..72acb01 100644 --- a/hook/hook.go +++ b/hook/hook.go @@ -6,6 +6,7 @@ import ( "crypto/sha1" "crypto/sha256" "crypto/sha512" + "crypto/subtle" "encoding/base64" "encoding/hex" "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 { switch r.Type { case MatchValue: - return arg == r.Value, nil + return compare(arg, r.Value), nil case MatchRegex: return regexp.MatchString(r.Regex, arg) case MatchHashSHA1: @@ -804,6 +805,11 @@ func (r MatchRule) Evaluate(headers, query, payload *map[string]interface{}, bod 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. func getenv(s string) string { return os.Getenv(s) diff --git a/hook/hook_test.go b/hook/hook_test.go index c2dc16d..ce6d760 100644 --- a/hook/hook_test.go +++ b/hook/hook_test.go @@ -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) + } + } +}