Skip to content

Commit 52cf511

Browse files
committed
add RSECloud
1 parent 3acf6d5 commit 52cf511

3 files changed

Lines changed: 122 additions & 0 deletions

File tree

v2/pkg/passive/sources.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/rapiddns"
4040
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/redhuntlabs"
4141
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/robtex"
42+
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/rsecloud"
4243
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/securitytrails"
4344
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/shodan"
4445
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/sitedossier"
@@ -81,6 +82,7 @@ var AllSources = [...]subscraping.Source{
8182
&redhuntlabs.Source{},
8283
// &riddler.Source{}, // failing due to cloudfront protection
8384
&robtex.Source{},
85+
&rsecloud.Source{},
8486
&securitytrails.Source{},
8587
&shodan.Source{},
8688
&sitedossier.Source{},

v2/pkg/passive/sources_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ var (
3838
"redhuntlabs",
3939
// "riddler", // failing due to cloudfront protection
4040
"robtex",
41+
"rsecloud",
4142
"securitytrails",
4243
"shodan",
4344
"sitedossier",
@@ -79,6 +80,7 @@ var (
7980
"redhuntlabs",
8081
"robtex",
8182
// "riddler", // failing due to cloudfront protection
83+
"rsecloud",
8284
"securitytrails",
8385
"shodan",
8486
"virustotal",
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package rsecloud
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"time"
7+
8+
jsoniter "github.com/json-iterator/go"
9+
10+
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping"
11+
)
12+
13+
type response struct {
14+
Count int `json:"count"`
15+
Data []string `json:"data"`
16+
Page int `json:"page"`
17+
PageSize int `json:"pagesize"`
18+
TotalPages int `json:"total_pages"`
19+
}
20+
21+
// Source is the passive scraping agent
22+
type Source struct {
23+
apiKeys []string
24+
timeTaken time.Duration
25+
errors int
26+
results int
27+
skipped bool
28+
}
29+
30+
// Run function returns all subdomains found with the service
31+
func (s *Source) Run(ctx context.Context, domain string, session *subscraping.Session) <-chan subscraping.Result {
32+
results := make(chan subscraping.Result)
33+
s.errors = 0
34+
s.results = 0
35+
36+
go func() {
37+
defer func(startTime time.Time) {
38+
s.timeTaken = time.Since(startTime)
39+
close(results)
40+
}(time.Now())
41+
42+
randomApiKey := subscraping.PickRandom(s.apiKeys, s.Name())
43+
if randomApiKey == "" {
44+
s.skipped = true
45+
return
46+
}
47+
48+
headers := map[string]string{"Content-Type": "application/json", "X-API-Key": randomApiKey}
49+
50+
fetchSubdomains := func(endpoint string) {
51+
page := 1
52+
for {
53+
resp, err := session.Get(ctx, fmt.Sprintf("https://api.rsecloud.com/api/v2/subdomains/%s/%s?page=%d", endpoint, domain, page), "", headers)
54+
if err != nil {
55+
results <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: err}
56+
s.errors++
57+
session.DiscardHTTPResponse(resp)
58+
return
59+
}
60+
defer session.DiscardHTTPResponse(resp)
61+
62+
var rseCloudResponse response
63+
err = jsoniter.NewDecoder(resp.Body).Decode(&rseCloudResponse)
64+
if err != nil {
65+
results <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: err}
66+
s.errors++
67+
resp.Body.Close()
68+
return
69+
}
70+
71+
for _, subdomain := range rseCloudResponse.Data {
72+
results <- subscraping.Result{Source: s.Name(), Type: subscraping.Subdomain, Value: subdomain}
73+
s.results++
74+
}
75+
76+
if page >= rseCloudResponse.TotalPages {
77+
break
78+
}
79+
page++
80+
}
81+
}
82+
83+
fetchSubdomains("active")
84+
fetchSubdomains("passive")
85+
}()
86+
87+
return results
88+
}
89+
90+
// Name returns the name of the source
91+
func (s *Source) Name() string {
92+
return "rsecloud"
93+
}
94+
95+
func (s *Source) IsDefault() bool {
96+
return true
97+
}
98+
99+
func (s *Source) HasRecursiveSupport() bool {
100+
return true
101+
}
102+
103+
func (s *Source) NeedsKey() bool {
104+
return true
105+
}
106+
107+
func (s *Source) AddApiKeys(keys []string) {
108+
s.apiKeys = keys
109+
}
110+
111+
func (s *Source) Statistics() subscraping.Statistics {
112+
return subscraping.Statistics{
113+
Errors: s.errors,
114+
Results: s.results,
115+
TimeTaken: s.timeTaken,
116+
Skipped: s.skipped,
117+
}
118+
}

0 commit comments

Comments
 (0)