bucket discovery: no name guessing
Remove all fabricated candidate names (suffixes and the wordlist). Discovery now only tests names that actually occur in the incoming hostname: the subdomain label and the registrable-domain label (assets.example.com -> assets, example). Nothing is permuted or drawn from a wordlist.
This commit is contained in:
1 parent
ebb020c6b7
commit
fe5c01666b
6 files changed
+56
-121
No files matched your search
@@ -45,7 +45,6 @@ type Discoverer struct {
|
||||
cfg Config
|
||||
client *http.Client
|
||||
q *domainQueue
|
||||
names *domainQueue
|
||||
tokens chan struct{}
|
||||
seen *dns.TTLCache[bool] // candidate names already tested
|
||||
stop chan struct{}
|
||||
@@ -69,7 +68,6 @@ func New(cfg Config) *Discoverer {
|
||||
cfg: cfg,
|
||||
client: &http.Client{Timeout: 6 * time.Second},
|
||||
q: newDomainQueue(cfg.Queue),
|
||||
names: newDomainQueue(cfg.Queue),
|
||||
tokens: make(chan struct{}, max(cfg.QPS, 1)),
|
||||
seen: dns.NewTTLCache[bool](1<<20, 64),
|
||||
stop: make(chan struct{}),
|
||||
@@ -138,7 +136,6 @@ func (d *Discoverer) worker(ctx context.Context) {
|
||||
case <-d.stop:
|
||||
return
|
||||
case <-d.q.notify:
|
||||
case <-d.names.notify:
|
||||
}
|
||||
for {
|
||||
host, ok := d.q.pop()
|
||||
@@ -147,13 +144,6 @@ func (d *Discoverer) worker(ctx context.Context) {
|
||||
}
|
||||
d.scanDomain(ctx, host)
|
||||
}
|
||||
for {
|
||||
name, ok := d.names.pop()
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
d.testName(ctx, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,13 +156,6 @@ func (d *Discoverer) scanDomain(ctx context.Context, host string) {
|
||||
}
|
||||
}
|
||||
|
||||
// SubmitName tests a specific candidate bucket name (e.g. from a wordlist).
|
||||
func (d *Discoverer) SubmitName(name string) {
|
||||
if validBucketName(name) {
|
||||
d.names.push(name)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Discoverer) testName(ctx context.Context, name string) {
|
||||
if _, dup := d.seen.Get(name); dup {
|
||||
return
|
||||
@@ -272,30 +255,9 @@ func (d *Discoverer) test(ctx context.Context, t Target) {
|
||||
|
||||
// --- candidate generation ---
|
||||
|
||||
var suffixes = []string{
|
||||
"", "-assets", "-static", "-backups", "-backup", "-images", "-img", "-media",
|
||||
"-prod", "-dev", "-staging", "-test", "-files", "-uploads", "-public", "-cdn",
|
||||
"-data", "-content", "-site", "-web", "-www", "-app", "-store", "-downloads",
|
||||
"-photos", "-videos", "-docs", "-documents", "-archive", "-logs", "-artifacts",
|
||||
"-build", "-deploy", "-release", "-db", "-database", "-sql", "-exports", "-reports",
|
||||
"-assets-prod", "-assets-dev", "-static-prod", "-uploads-prod",
|
||||
}
|
||||
|
||||
// Wordlist is a bounded set of common global bucket names tested once each.
|
||||
func Wordlist() []string {
|
||||
return []string{
|
||||
"backups", "backup", "images", "image", "img", "media", "static", "assets",
|
||||
"uploads", "files", "file", "data", "content", "public", "cdn", "www", "web",
|
||||
"website", "app", "store", "downloads", "docs", "documents", "archive",
|
||||
"logs", "artifacts", "build", "deploy", "release", "db", "database", "sql",
|
||||
"dump", "exports", "reports", "photos", "videos", "dev", "test", "staging",
|
||||
"prod", "production", "internal", "private", "secure", "userdata", "usercontent",
|
||||
"thumbnails", "avatars", "profiles", "attachments", "tmp", "temp", "cache",
|
||||
"config", "secrets", "keys", "certificates", "certs", "gifs", "png", "jpeg",
|
||||
"download", "uploads-test", "uploads-dev", "assets-test", "assets-dev",
|
||||
"static-assets", "web-assets", "app-assets", "site-assets", "media-assets",
|
||||
}
|
||||
}
|
||||
// No name guessing: candidates are exactly the labels that occur in the incoming
|
||||
// hostname (the subdomain label and the registrable-domain label). Nothing is
|
||||
// fabricated, permuted, or drawn from a wordlist.
|
||||
|
||||
// baseLabels returns plausible bucket-name stems from a hostname: the leftmost
|
||||
// label and the registrable-domain label.
|
||||
@@ -325,17 +287,9 @@ var skipLabel = map[string]bool{
|
||||
}
|
||||
|
||||
func candidates(host string, max int) []string {
|
||||
var out []string
|
||||
for _, b := range baseLabels(host) {
|
||||
for _, s := range suffixes {
|
||||
name := b + s
|
||||
if validBucketName(name) {
|
||||
out = append(out, name)
|
||||
}
|
||||
if max > 0 && len(out) >= max {
|
||||
return out
|
||||
}
|
||||
}
|
||||
out := baseLabels(host)
|
||||
if max > 0 && len(out) > max {
|
||||
out = out[:max]
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user