mirror of
https://github.com/trufflesecurity/trufflehog.git
synced 2024-11-14 00:47:21 +00:00
2f7029bc4d
This PR: Creates an optional interface that detectors can use to customize their false positive detection Implements this interface on detectors that have custom logic In most cases this "custom logic" is simply a no-op because the detector does not participate in false positive detection Eliminates inline (old-style) false positive exclusion in a few detectors that #2643 missed
131 lines
3.2 KiB
Go
131 lines
3.2 KiB
Go
package mongodb
|
|
|
|
import (
|
|
"context"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
|
|
regexp "github.com/wasilibs/go-re2"
|
|
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
"go.mongodb.org/mongo-driver/mongo/readpref"
|
|
"go.mongodb.org/mongo-driver/x/mongo/driver/auth"
|
|
"go.mongodb.org/mongo-driver/x/mongo/driver/topology"
|
|
|
|
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
|
)
|
|
|
|
type Scanner struct {
|
|
timeout time.Duration // Zero value means "default timeout"
|
|
}
|
|
|
|
// Ensure the Scanner satisfies the interface at compile time.
|
|
var _ detectors.Detector = (*Scanner)(nil)
|
|
var _ detectors.CustomFalsePositiveChecker = (*Scanner)(nil)
|
|
|
|
var (
|
|
defaultTimeout = 2 * time.Second
|
|
// Make sure that your group is surrounded in boundary characters such as below to reduce false positives.
|
|
keyPat = regexp.MustCompile(`\b(mongodb(\+srv)?://[\S]{3,50}:([\S]{3,88})@[-.%\w\/:]+)\b`)
|
|
// TODO: Add support for sharded cluster, replica set and Atlas Deployment.
|
|
)
|
|
|
|
// Keywords are used for efficiently pre-filtering chunks.
|
|
// Use identifiers in the secret preferably, or the provider name.
|
|
func (s Scanner) Keywords() []string {
|
|
return []string{"mongodb"}
|
|
}
|
|
|
|
// FromData will find and optionally verify MongoDB secrets in a given set of bytes.
|
|
func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {
|
|
dataStr := string(data)
|
|
|
|
matches := keyPat.FindAllStringSubmatch(dataStr, -1)
|
|
|
|
for _, match := range matches {
|
|
resMatch := strings.TrimSpace(match[1])
|
|
|
|
s1 := detectors.Result{
|
|
DetectorType: detectorspb.DetectorType_MongoDB,
|
|
Raw: []byte(resMatch),
|
|
}
|
|
s1.ExtraData = map[string]string{
|
|
"rotation_guide": "https://howtorotate.com/docs/tutorials/mongo/",
|
|
}
|
|
|
|
if verify {
|
|
timeout := s.timeout
|
|
if timeout == 0 {
|
|
timeout = defaultTimeout
|
|
}
|
|
err := verifyUri(resMatch, timeout)
|
|
s1.Verified = err == nil
|
|
if !isErrDeterminate(err) {
|
|
s1.SetVerificationError(err, resMatch)
|
|
}
|
|
}
|
|
results = append(results, s1)
|
|
}
|
|
|
|
return results, nil
|
|
}
|
|
|
|
func (s Scanner) IsFalsePositive(_ detectors.Result) bool {
|
|
return false
|
|
}
|
|
|
|
func isErrDeterminate(err error) bool {
|
|
switch e := err.(type) {
|
|
case topology.ConnectionError:
|
|
switch e.Unwrap().(type) {
|
|
case *auth.Error:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func verifyUri(uri string, timeout time.Duration) error {
|
|
parsed, err := url.Parse(uri)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
params := url.Values{}
|
|
for k, v := range parsed.Query() {
|
|
if len(v) > 0 {
|
|
switch k {
|
|
case "tls":
|
|
if v[0] == "false" {
|
|
params.Set("tls", "false")
|
|
} else {
|
|
params.Set("tls", "true")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
parsed.RawQuery = params.Encode()
|
|
parsed.Path = "/"
|
|
uri = parsed.String()
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
defer cancel()
|
|
client, err := mongo.Connect(ctx, options.Client().SetTimeout(timeout).ApplyURI(uri))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer func() {
|
|
_ = client.Disconnect(ctx)
|
|
}()
|
|
return client.Ping(ctx, readpref.Primary())
|
|
}
|
|
|
|
func (s Scanner) Type() detectorspb.DetectorType {
|
|
return detectorspb.DetectorType_MongoDB
|
|
}
|