|
0 |
package threatbook
|
|
1 |
|
|
2 |
import (
|
|
3 |
"context"
|
|
4 |
"fmt"
|
|
5 |
"strconv"
|
|
6 |
|
|
7 |
jsoniter "github.com/json-iterator/go"
|
|
8 |
"github.com/projectdiscovery/subfinder/pkg/subscraping"
|
|
9 |
)
|
|
10 |
|
|
11 |
type threatBookResponse struct {
|
|
12 |
ResponseCode int64 `json:"response_code"`
|
|
13 |
VerboseMsg string `json:"verbose_msg"`
|
|
14 |
Data struct {
|
|
15 |
Domain string `json:"domain"`
|
|
16 |
SubDomains struct {
|
|
17 |
Total string `json:"total"`
|
|
18 |
Data []string `json:"data"`
|
|
19 |
} `json:"sub_domains"`
|
|
20 |
} `json:"data"`
|
|
21 |
}
|
|
22 |
|
|
23 |
// Source is the passive scraping agent
|
|
24 |
type Source struct{}
|
|
25 |
|
|
26 |
// Run function returns all subdomains found with the service
|
|
27 |
func (s *Source) Run(ctx context.Context, domain string, session *subscraping.Session) <-chan subscraping.Result {
|
|
28 |
results := make(chan subscraping.Result)
|
|
29 |
|
|
30 |
go func() {
|
|
31 |
defer close(results)
|
|
32 |
|
|
33 |
if session.Keys.ThreatBook == "" {
|
|
34 |
return
|
|
35 |
}
|
|
36 |
|
|
37 |
resp, err := session.SimpleGet(ctx, fmt.Sprintf("https://api.threatbook.cn/v3/domain/sub_domains?apikey=%s&resource=%s", session.Keys.ThreatBook, domain))
|
|
38 |
if err != nil && resp == nil {
|
|
39 |
results <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: err}
|
|
40 |
session.DiscardHTTPResponse(resp)
|
|
41 |
return
|
|
42 |
}
|
|
43 |
|
|
44 |
var response threatBookResponse
|
|
45 |
err = jsoniter.NewDecoder(resp.Body).Decode(&response)
|
|
46 |
if err != nil {
|
|
47 |
results <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: err}
|
|
48 |
resp.Body.Close()
|
|
49 |
return
|
|
50 |
}
|
|
51 |
resp.Body.Close()
|
|
52 |
|
|
53 |
if response.ResponseCode != 0 {
|
|
54 |
results <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: fmt.Errorf("code %d, %s", response.ResponseCode, response.VerboseMsg)}
|
|
55 |
return
|
|
56 |
}
|
|
57 |
|
|
58 |
total, err := strconv.ParseInt(response.Data.SubDomains.Total, 10, 64)
|
|
59 |
if err != nil {
|
|
60 |
results <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: err}
|
|
61 |
return
|
|
62 |
}
|
|
63 |
|
|
64 |
if total > 0 {
|
|
65 |
for _, subdomain := range response.Data.SubDomains.Data {
|
|
66 |
results <- subscraping.Result{Source: s.Name(), Type: subscraping.Subdomain, Value: subdomain}
|
|
67 |
}
|
|
68 |
}
|
|
69 |
}()
|
|
70 |
|
|
71 |
return results
|
|
72 |
}
|
|
73 |
|
|
74 |
// Name returns the name of the source
|
|
75 |
func (s *Source) Name() string {
|
|
76 |
return "threatbook"
|
|
77 |
}
|