From 661c6b47b75cb118abc5ed4175a7a9c0a1f95d62 Mon Sep 17 00:00:00 2001 From: ahrav Date: Mon, 31 Jul 2023 11:12:52 -0700 Subject: [PATCH] [bug] - fix shodan detector (#1579) * fix shodan detector. * fix import order. --- pkg/detectors/shodankey/shodankey.go | 61 +++++++++++++++++------ pkg/detectors/shodankey/shodankey_test.go | 2 +- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/pkg/detectors/shodankey/shodankey.go b/pkg/detectors/shodankey/shodankey.go index 5ef523bcc2ee..c6600151cc9d 100644 --- a/pkg/detectors/shodankey/shodankey.go +++ b/pkg/detectors/shodankey/shodankey.go @@ -2,6 +2,8 @@ package shodankey import ( "context" + "encoding/json" + "io" "net/http" "regexp" "strings" @@ -48,31 +50,58 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result } if verify { - req, err := http.NewRequestWithContext(ctx, "GET", "https://api.shodan.io/shodan/host/count?key="+resMatch+"&query=port:22&facets=org,os", nil) - if err != nil { + s1.Verified = verifyToken(ctx, client, resMatch) + if !s1.Verified && detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) { continue } - - res, err := client.Do(req) - if err == nil { - defer res.Body.Close() - if res.StatusCode >= 200 && res.StatusCode < 300 { - s1.Verified = true - } 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(resMatch, detectors.DefaultFalsePositives, true) { - continue - } - } - } } - results = append(results, s1) } return results, nil } +type shodanInfoRes struct { + ScanCredits int `json:"scan_credits"` + UsageLimits struct { + ScanCredits int `json:"scan_credits"` + QueryCredits int `json:"query_credits"` + MonitoredIps int `json:"monitored_ips"` + } `json:"usage_limits"` + Plan string `json:"plan"` + HTTPS bool `json:"https"` + Unlocked bool `json:"unlocked"` + QueryCredits int `json:"query_credits"` + MonitoredIps int `json:"monitored_ips"` + UnlockedLeft int `json:"unlocked_left"` + Telnet bool `json:"telnet"` +} + +func verifyToken(ctx context.Context, client *http.Client, token string) bool { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.shodan.io/api-info?key="+token, nil) + if err != nil { + return false + } + + res, err := client.Do(req) + if err != nil { + return false + } + defer res.Body.Close() + + if res.StatusCode < 200 || res.StatusCode >= 300 { + return false + } + + bytes, err := io.ReadAll(res.Body) + if err != nil { + return false + } + + var info shodanInfoRes + return json.Unmarshal(bytes, &info) == nil +} + func (s Scanner) Type() detectorspb.DetectorType { return detectorspb.DetectorType_ShodanKey } diff --git a/pkg/detectors/shodankey/shodankey_test.go b/pkg/detectors/shodankey/shodankey_test.go index dbdd5d929089..e7afbc867a57 100644 --- a/pkg/detectors/shodankey/shodankey_test.go +++ b/pkg/detectors/shodankey/shodankey_test.go @@ -10,9 +10,9 @@ import ( "time" "github.com/kylelemons/godebug/pretty" - "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" "github.com/trufflesecurity/trufflehog/v3/pkg/common" + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" )