diff --git a/go.mod b/go.mod index 6b6321496818..cf05134192a7 100644 --- a/go.mod +++ b/go.mod @@ -43,7 +43,6 @@ require ( github.com/mholt/archiver/v4 v4.0.0-alpha.7 github.com/paulbellamy/ratecounter v0.2.0 github.com/pkg/errors v0.9.1 - github.com/razorpay/razorpay-go v0.0.0-20210728161131-0341409a6ab2 github.com/rs/zerolog v1.28.0 github.com/sergi/go-diff v1.2.0 github.com/sirupsen/logrus v1.9.0 diff --git a/go.sum b/go.sum index 8050055bd4c4..b821e539fddf 100644 --- a/go.sum +++ b/go.sum @@ -410,8 +410,6 @@ github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qR github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/razorpay/razorpay-go v0.0.0-20210728161131-0341409a6ab2 h1:8XGvK6qfvE4l749HHWSdmkrXczWJPQLKNDFosFYDbOE= -github.com/razorpay/razorpay-go v0.0.0-20210728161131-0341409a6ab2/go.mod h1:VcljkUylUJAUEvFfGVv/d5ht1to1dUgF4H1+3nv7i+Q= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= diff --git a/pkg/detectors/razorpay/razorpay.go b/pkg/detectors/razorpay/razorpay.go index c5eb5ac28d7e..cccfcee3adb7 100644 --- a/pkg/detectors/razorpay/razorpay.go +++ b/pkg/detectors/razorpay/razorpay.go @@ -2,13 +2,14 @@ package razorpay import ( "context" + "encoding/json" + "io" + "net/http" "regexp" - log "github.com/sirupsen/logrus" + "github.com/trufflesecurity/trufflehog/v3/pkg/common" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" - - "github.com/razorpay/razorpay-go" ) type Scanner struct{} @@ -18,8 +19,10 @@ var _ detectors.Detector = (*Scanner)(nil) // The (`) character adds secondary encoding to parsed strings by Golang which also allows for escape sequences var ( - keyPat = regexp.MustCompile(`(?i)\brzp_\w{2,6}_\w{10,20}\b`) - secretPat = regexp.MustCompile(`(?:razor|secret|rzp|key)[-\w]*[\" :=']*([A-Za-z0-9]{20,50})`) + client = common.SaneHttpClient() + + keyPat = regexp.MustCompile(`(?i)\brzp_live_\w{10,20}\b`) + secretPat = regexp.MustCompile(detectors.PrefixRegex([]string{"razor|secret|rzp|key"}) + `([A-Za-z0-9]{20,50})`) ) // Keywords are used for efficiently pre-filtering chunks. @@ -32,54 +35,54 @@ func (s Scanner) Keywords() []string { func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { dataStr := string(data) - matches := keyPat.FindAllString(dataStr, -1) + keyMatches := keyPat.FindAllString(dataStr, -1) - for _, match := range matches { - token := match - - s := detectors.Result{ - DetectorType: detectorspb.DetectorType_RazorPay, - Raw: []byte(token), - Redacted: token, - } + for _, key := range keyMatches { if verify { - //https://dashboard.razorpay.com/#/access/signin - //https://gitlab.com/trufflesec/trufflehog/-/blob/master/webapi/secrets/razorpay.py - secMatches := secretPat.FindAllStringSubmatch(dataStr, -1) - if len(secMatches) == 0 { - //no secret keys were found. Declare unverified (This is how AWS secret handles the same logic) - //TODO determine if key alone without secret is reportable - s.Verified = false - return - } - //we only want the secret, not its surrounding info - grabbing capture groups - for _, secMatch := range secMatches { - client := razorpay.NewClient(token, secMatch[1]) - resp, err := client.Order.All(nil, nil) - //TODO Error handling is broken in SDK, fixed by https://github.com/razorpay/razorpay-go/pull/23 - //waiting to be reviewed and merged - if resp == nil { - continue + secMatches := secretPat.FindAllString(dataStr, -1) + + for _, secret := range secMatches { + + s1 := detectors.Result{ + DetectorType: detectorspb.DetectorType_RazorPay, + Raw: []byte(key), + RawV2: []byte(key + secret), + Redacted: key, } + + req, err := http.NewRequest("GET", "https://api.razorpay.com/v1/items?count=1", nil) if err != nil { - log.Debugf("Error verifying likely razorpay key/secret combo: %v", err) continue } - //TODO debug with responses. could still be invalid at this stage - - s.Verified = true - } - } + req.SetBasicAuth(key, secret) + res, err := client.Do(req) + if err == nil { + bodyBytes, err := io.ReadAll(res.Body) + if err != nil { + continue + } + defer res.Body.Close() + if res.StatusCode >= 200 && res.StatusCode < 300 { + if json.Valid(bodyBytes) { + s1.Verified = true + } else { + s1.Verified = false + } + } else { + // This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key. + if detectors.IsKnownFalsePositive(key, detectors.DefaultFalsePositives, true) { + continue + } + } + } - if !s.Verified { - if detectors.IsKnownFalsePositive(string(s.Raw), detectors.DefaultFalsePositives, false) { - continue + results = append(results, s1) } } - results = append(results, s) } + results = detectors.CleanResults(results) return } diff --git a/pkg/detectors/razorpay/razorpay_test.go b/pkg/detectors/razorpay/razorpay_test.go index c4d35eafbe03..07997fadc503 100644 --- a/pkg/detectors/razorpay/razorpay_test.go +++ b/pkg/detectors/razorpay/razorpay_test.go @@ -42,13 +42,13 @@ func TestRazorPay_FromChunk(t *testing.T) { s: Scanner{}, args: args{ ctx: context.Background(), - data: []byte(fmt.Sprintf("25:RAZORPAY_KEY='rzp_test_SnDTaP1ncfliDt'\n\"rzp_secret\" : \" %s\", ", secretInactive)), + data: []byte(fmt.Sprintf("25:RAZORPAY_KEY='rzp_live_SnDTaP1ncfliDt'\n\"rzp_secret\" : \" %s\", ", secretInactive)), verify: true, }, want: []detectors.Result{ { DetectorType: detectorspb.DetectorType_RazorPay, - Redacted: "rzp_test_SnDTaP1ncfliDt", + Redacted: "rzp_live_SnDTaP1ncfliDt", Verified: false, }, }, @@ -82,6 +82,7 @@ func TestRazorPay_FromChunk(t *testing.T) { t.Fatal("no raw secret present") } got[i].Raw = nil + got[i].RawV2 = nil } if diff := pretty.Compare(got, tt.want); diff != "" { t.Errorf("RazorPay.FromData() %s diff: (-got +want)\n%s", tt.name, diff)