From 63f09328ecaa7893f85c3b9e462ae36239984ffa Mon Sep 17 00:00:00 2001 From: M09ic Date: Tue, 21 Dec 2021 00:34:49 +0800 Subject: [PATCH] add zoomeye domain api source --- v2/pkg/passive/sources.go | 4 + v2/pkg/runner/config.go | 4 + .../sources/zoomeyeapi/zoomeyeapi.go | 80 +++++++++++++++++++ v2/pkg/subscraping/types.go | 1 + 4 files changed, 89 insertions(+) create mode 100644 v2/pkg/subscraping/sources/zoomeyeapi/zoomeyeapi.go diff --git a/v2/pkg/passive/sources.go b/v2/pkg/passive/sources.go index 72b9a3e..933a312 100644 --- a/v2/pkg/passive/sources.go +++ b/v2/pkg/passive/sources.go @@ -36,6 +36,7 @@ import ( "github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/virustotal" "github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/waybackarchive" "github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/zoomeye" + "github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/zoomeyeapi" ) // DefaultSources contains the list of fast sources used by default. @@ -114,6 +115,7 @@ var DefaultAllSources = []string{ "virustotal", "waybackarchive", "zoomeye", + "zoomeyeapi", "fofa", } @@ -205,6 +207,8 @@ func (a *Agent) addSources(sources []string) { a.sources[source] = &waybackarchive.Source{} case "zoomeye": a.sources[source] = &zoomeye.Source{} + case "zoomeyeapi": + a.sources[source] = &zoomeyeapi.Source{} case "fofa": a.sources[source] = &fofa.Source{} } diff --git a/v2/pkg/runner/config.go b/v2/pkg/runner/config.go index 0d6d2f9..8d15bee 100644 --- a/v2/pkg/runner/config.go +++ b/v2/pkg/runner/config.go @@ -47,6 +47,7 @@ type ConfigFile struct { URLScan []string `yaml:"urlscan"` Virustotal []string `yaml:"virustotal"` ZoomEye []string `yaml:"zoomeye"` + ZoomEyeApi []string `yaml:"zoomeyeapi"` Fofa []string `yaml:"fofa"` // Version indicates the version of subfinder installed. Version string `yaml:"subfinder-version"` @@ -199,6 +200,9 @@ func (c *ConfigFile) GetKeys() subscraping.Keys { keys.ZoomEyePassword = parts[1] } } + if len(c.ZoomEyeApi) > 0 { + keys.ZoomEyeKey = c.ZoomEyeApi[rand.Intn(len(c.ZoomEyeApi))] + } if len(c.Fofa) > 0 { fofaKeys := c.Fofa[rand.Intn(len(c.Fofa))] parts := strings.Split(fofaKeys, ":") diff --git a/v2/pkg/subscraping/sources/zoomeyeapi/zoomeyeapi.go b/v2/pkg/subscraping/sources/zoomeyeapi/zoomeyeapi.go new file mode 100644 index 0000000..9ea3a63 --- /dev/null +++ b/v2/pkg/subscraping/sources/zoomeyeapi/zoomeyeapi.go @@ -0,0 +1,80 @@ +package zoomeyeapi + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + + "github.com/projectdiscovery/subfinder/v2/pkg/subscraping" +) + +//type loginResp struct { +// JWT string `json:"access_token"` +//} + +// search results +type zoomeyeResults struct { + Status int `json:"status"` + Total int `json:"total"` + List []struct { + Name string `json:"name"` + Ip []string `json:"ip"` + } `json:"list"` +} + +// Source is the passive scraping agent +type Source struct{} + +// Run function returns all subdomains found with the service +func (s *Source) Run(ctx context.Context, domain string, session *subscraping.Session) <-chan subscraping.Result { + results := make(chan subscraping.Result) + + go func() { + defer close(results) + + if session.Keys.ZoomEyeKey == "" { + return + } + + headers := map[string]string{ + "API-KEY": session.Keys.ZoomEyeKey, + "Accept": "application/json", + "Content-Type": "application/json", + } + var pages = 1 + for currentPage := 1; currentPage <= pages; currentPage++ { + api := fmt.Sprintf("https://api.zoomeye.org/domain/search?q=%s&type=1&s=1000&page=%d", domain, currentPage) + resp, err := session.Get(ctx, api, "", headers) + isForbidden := resp != nil && resp.StatusCode == http.StatusForbidden + if err != nil { + if !isForbidden && currentPage == 0 { + results <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: err} + session.DiscardHTTPResponse(resp) + } + return + } + + var res zoomeyeResults + err = json.NewDecoder(resp.Body).Decode(&res) + if err != nil { + results <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: err} + resp.Body.Close() + return + } + resp.Body.Close() + pages = int(res.Total/1000) + 1 + for _, r := range res.List { + results <- subscraping.Result{Source: s.Name(), Type: subscraping.Subdomain, Value: r.Name} + } + currentPage++ + } + }() + + return results +} + +// Name returns the name of the source +func (s *Source) Name() string { + return "zoomeyeapi" +} diff --git a/v2/pkg/subscraping/types.go b/v2/pkg/subscraping/types.go index 5d95252..753d125 100644 --- a/v2/pkg/subscraping/types.go +++ b/v2/pkg/subscraping/types.go @@ -61,6 +61,7 @@ type Keys struct { Virustotal string `json:"virustotal"` ZoomEyeUsername string `json:"zoomeye_username"` ZoomEyePassword string `json:"zoomeye_password"` + ZoomEyeKey string `json:"zoomeye_key"` FofaUsername string `json:"fofa_username"` FofaSecret string `json:"fofa_secret"` }