Skip to content

Commit 70f0c91

Browse files
1. Cloud Provider Enumeration ✓
- AWS: S3, CloudFront, EC2, Elastic Beanstalk, Lambda - Azure: Blob Storage, App Service, Container Registry, Functions, Key Vaults - GCP: Cloud Storage, App Engine, Cloud Run, Cloud Functions, Firebase 2. Search Engine Integration ✓ - Common Crawl API (free, unrestricted) - DuckDuckGo API - Bing Search API (with key support) - Comprehensive dork generation 3. Enhanced WHOIS ✓ - Reverse WHOIS lookups - Organization/email-based discovery - Expired domain tracking - Bulk operations with rate limiting 4. DNS Brute-forcing ✓ - 360+ subdomain wordlist - Intelligent permutations - Wildcard detection - Multi-resolver support 5. Web Spidering ✓ - Recursive crawling - JavaScript analysis - Technology detection - API endpoint discovery 6. External APIs ✓ - Shodan integration - Censys integration - ASN expansion 7. Infrastructure ✓ - Caching system (24-hour TTL) - Rate limiting (service-specific) - Recursive discovery (3 levels) 8. Self-Update Fix ✓ - Now properly rebuilds the binary after pulling updates
1 parent 95e5725 commit 70f0c91

12 files changed

Lines changed: 2723 additions & 88 deletions

File tree

IMPLEMENTATION_SUMMARY.md

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# Shells Enhanced Discovery Implementation Summary
2+
3+
## Overview
4+
I have successfully implemented comprehensive infrastructure discovery capabilities for the shells security scanning tool. The enhancements transform shells into a powerful point-and-click reconnaissance tool that can spider out and footprint entire infrastructures.
5+
6+
## Implemented Features
7+
8+
### 1. Cloud Provider Enumeration
9+
- **AWS Discovery** (`pkg/discovery/cloud/aws.go`)
10+
- S3 bucket enumeration with intelligent naming patterns
11+
- CloudFront distribution discovery
12+
- EC2 metadata exposure detection
13+
- Elastic Beanstalk application discovery
14+
- Lambda function URL discovery
15+
- Support for all major AWS regions
16+
17+
- **Azure Discovery** (`pkg/discovery/cloud/azure.go`)
18+
- Blob Storage container enumeration
19+
- App Service application discovery
20+
- Container Registry discovery
21+
- Azure Functions detection
22+
- Key Vault enumeration
23+
- Support for multiple Azure domains (.azurewebsites.net, .azurefd.net, .azureedge.net)
24+
25+
- **Google Cloud Platform Discovery** (`pkg/discovery/cloud/gcp.go`)
26+
- Google Cloud Storage bucket discovery
27+
- App Engine application detection
28+
- Cloud Run service enumeration
29+
- Cloud Functions discovery
30+
- Firebase application detection (Hosting, Realtime Database)
31+
- BigQuery dataset patterns
32+
33+
### 2. Enhanced Search Engine Integration
34+
- **Common Crawl Integration** - Free and unrestricted web archive search
35+
- **DuckDuckGo API** - Privacy-focused search without rate limits
36+
- **Bing Search API** - Enterprise search with API key support
37+
- **Google Dorking** - Comprehensive dork generation (disabled by default due to ToS)
38+
- **Advanced Dork Patterns**:
39+
- File type discovery (PDFs, configs, logs, backups)
40+
- Login/admin panel detection
41+
- API endpoint discovery
42+
- Error message harvesting
43+
- Development/staging site detection
44+
- Cloud storage references
45+
46+
### 3. WHOIS Enhancements
47+
- **Reverse WHOIS Lookups** using ViewDNS.info
48+
- **Organization-based Discovery** - Find all domains registered by an organization
49+
- **Email-based Discovery** - Find domains registered with the same email
50+
- **Expired Domain Tracking** - Monitor recently expired domains from target organizations
51+
- **Bulk WHOIS Operations** with rate limiting
52+
- **Related Domain Extraction** from WHOIS records
53+
54+
### 4. DNS Brute-forcing
55+
- **Comprehensive Wordlist** - 360+ common subdomain patterns
56+
- **Intelligent Permutations** - Year-based, environment-based, geographic patterns
57+
- **Wildcard Detection** - Avoid false positives from wildcard DNS
58+
- **Multi-resolver Support** - 8 public DNS resolvers for reliability
59+
- **Concurrent Resolution** - 50 parallel queries with rate limiting
60+
61+
### 5. Web Spidering
62+
- **Recursive Crawling** - Follow links to discover more assets
63+
- **JavaScript Analysis** - Extract domains from JS code
64+
- **Form Discovery** - Find input fields and hidden parameters
65+
- **Technology Detection** - Identify frameworks and platforms
66+
- **API Endpoint Extraction** - Discover REST/GraphQL endpoints
67+
- **Subdomain Extraction** - Find subdomains mentioned in content
68+
69+
### 6. External API Integrations
70+
- **Shodan Integration** - IP/domain/ASN searches with caching
71+
- **Censys Integration** - Certificate and host discovery
72+
- **ASN Expansion** - Convert AS numbers to IP ranges
73+
- **BGP Analysis** - Network block discovery
74+
75+
### 7. Caching System
76+
- **File-based Cache** (`pkg/discovery/cache/cache.go`)
77+
- **24-hour TTL** for API responses
78+
- **Memory Cache** for frequently accessed data
79+
- **Automatic Cleanup** of expired entries
80+
- **HTTP Response Caching** for web requests
81+
82+
### 8. Rate Limiting
83+
- **Service-specific Limits** (`pkg/discovery/ratelimit/limiter.go`)
84+
- **Configurable Rates** for each external service
85+
- **Burst Support** for initial requests
86+
- **Automatic Retry** with exponential backoff
87+
- **Global Rate Limiter** singleton for application-wide control
88+
89+
### 9. Enhanced Discovery Module
90+
- **Recursive Discovery** - Spider out up to 3 levels deep
91+
- **Parallel Execution** - Concurrent discovery methods
92+
- **Organization Context** - Maintain context across discoveries
93+
- **Asset Deduplication** - Avoid processing duplicates
94+
- **Comprehensive Integration** - All discovery methods work together
95+
96+
### 10. Self-Update Enhancement
97+
- **Fixed Binary Rebuild** - Always rebuilds after pulling updates
98+
- **SHA256 Verification** - Compares hashes before/after update
99+
- **Git Integration** - Pulls from current branch
100+
- **Clean Working Directory Check** - Prevents updates with uncommitted changes
101+
102+
## Key Improvements
103+
104+
### Discovery Capabilities
105+
- From basic DNS lookups to comprehensive infrastructure mapping
106+
- From single domain checks to organization-wide asset discovery
107+
- From manual enumeration to automated recursive discovery
108+
- From limited sources to 10+ discovery methods
109+
110+
### Performance & Reliability
111+
- Added caching to reduce API calls and improve speed
112+
- Implemented rate limiting to respect service limits
113+
- Parallel execution for faster discovery
114+
- Robust error handling and retry logic
115+
116+
### Usability
117+
- Point-and-click discovery: `shells [target]`
118+
- Automatic asset type detection
119+
- Comprehensive logging and progress tracking
120+
- Clean, organized output
121+
122+
## Usage Examples
123+
124+
```bash
125+
# Discover everything about a company
126+
shells "Acme Corporation"
127+
128+
# Discover all assets for a domain
129+
shells acme.com
130+
131+
# Discover assets in an IP range
132+
shells 192.168.1.0/24
133+
134+
# Update shells to latest version
135+
shells self-update
136+
```
137+
138+
## Technical Architecture
139+
140+
The implementation follows a modular architecture:
141+
- Each discovery method is a separate module
142+
- All modules implement common interfaces
143+
- Central orchestration through EnhancedDiscovery
144+
- Shared infrastructure (cache, rate limiting)
145+
- Clean separation of concerns
146+
147+
## Security Considerations
148+
149+
- Respects robots.txt and rate limits
150+
- No unauthorized access attempts
151+
- Defensive security focus
152+
- Ethical reconnaissance only
153+
- Clear logging of all actions
154+
155+
This implementation transforms shells into a comprehensive attack surface discovery tool, suitable for bug bounty hunting, penetration testing, and security assessments.

cmd/self_update.go

Lines changed: 11 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,18 @@ var selfUpdateCmd = &cobra.Command{
2020
Use: "self-update",
2121
Short: "Update shells to the latest version from GitHub",
2222
Long: `Update shells to the latest version by pulling from the GitHub repository,
23-
running the install script, and verifying the update with SHA256 checksums.
23+
rebuilding the binary, and verifying the update with SHA256 checksums.
2424
2525
This command will:
2626
1. Pull the latest code from the GitHub repository
27-
2. Run ./install.sh to build and install the new version
27+
2. Run ./install.sh to rebuild and install the binary
2828
3. Compare SHA256 hashes to verify the update
2929
4. Report the size of the new binary
3030
31-
Use --dry-run to check for updates without installing.`,
31+
The binary is always rebuilt after pulling to ensure you have the latest version,
32+
even if no new commits were pulled.
33+
34+
Use --dry-run to preview the update without installing.`,
3235
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
3336
// Initialize config but skip database for self-update
3437
return initConfig()
@@ -91,27 +94,16 @@ func runSelfUpdate(cmd *cobra.Command, args []string) error {
9194
return fmt.Errorf("failed to pull latest changes: %w", err)
9295
}
9396

94-
// Check if there are actually any updates
95-
fmt.Println("🔍 Checking for updates...")
96-
hasUpdates, err := checkForUpdates()
97-
if err != nil {
98-
return fmt.Errorf("failed to check for updates: %w", err)
99-
}
100-
101-
if !hasUpdates {
102-
fmt.Println("✅ Already up to date! No updates available.")
103-
return nil
104-
}
105-
106-
fmt.Println("📦 Updates found!")
97+
// Always rebuild after pulling latest changes to ensure binary is up to date
98+
fmt.Println("🔍 Building latest version...")
10799

108100
if dryRun {
109-
fmt.Println(" (dry-run mode: would install new version)")
101+
fmt.Println(" (dry-run mode: would rebuild and install binary)")
110102
fmt.Println("🎯 Run without --dry-run to perform the actual update.")
111103
return nil
112104
}
113105

114-
fmt.Println(" Installing new version...")
106+
fmt.Println(" Building and installing new binary...")
115107

116108
// Check if install.sh exists
117109
installScript := "./install.sh"
@@ -143,7 +135,7 @@ func runSelfUpdate(cmd *cobra.Command, args []string) error {
143135

144136
// Compare hashes
145137
if currentHash == newHash {
146-
fmt.Println("⚠️ Warning: Binary hash unchanged. Update may have failed or no changes were needed.")
138+
fmt.Println("ℹ️ Binary hash unchanged - no code changes affected the compiled binary.")
147139
} else {
148140
fmt.Printf("✅ Update successful!\n")
149141
fmt.Printf(" Old SHA256: %s\n", currentHash)
@@ -266,28 +258,3 @@ func pullLatestChanges() error {
266258
return nil
267259
}
268260

269-
// checkForUpdates checks if there are updates available
270-
func checkForUpdates() (bool, error) {
271-
// Get current commit hash
272-
currentCmd := exec.Command("git", "rev-parse", "HEAD")
273-
currentOutput, err := currentCmd.Output()
274-
if err != nil {
275-
return false, fmt.Errorf("failed to get current commit: %w", err)
276-
}
277-
currentHash := strings.TrimSpace(string(currentOutput))
278-
279-
// Get remote commit hash
280-
remoteCmd := exec.Command("git", "rev-parse", "origin/HEAD")
281-
remoteOutput, err := remoteCmd.Output()
282-
if err != nil {
283-
// Try with main branch if origin/HEAD doesn't exist
284-
remoteCmd = exec.Command("git", "rev-parse", "origin/main")
285-
remoteOutput, err = remoteCmd.Output()
286-
if err != nil {
287-
return false, fmt.Errorf("failed to get remote commit: %w", err)
288-
}
289-
}
290-
remoteHash := strings.TrimSpace(string(remoteOutput))
291-
292-
return currentHash != remoteHash, nil
293-
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ require (
7575
golang.org/x/net v0.42.0 // indirect
7676
golang.org/x/sys v0.34.0 // indirect
7777
golang.org/x/text v0.27.0 // indirect
78+
golang.org/x/time v0.12.0 // indirect
7879
golang.org/x/tools v0.34.0 // indirect
7980
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
8081
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
223223
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
224224
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
225225
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
226+
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
227+
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
226228
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
227229
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
228230
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=

internal/discovery/enhanced_discovery.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@ import (
44
"context"
55
"fmt"
66
"net"
7+
"path/filepath"
78
"strings"
89
"sync"
910
"time"
1011

1112
"github.com/CodeMonkeyCybersecurity/shells/internal/config"
1213
"github.com/CodeMonkeyCybersecurity/shells/internal/logger"
1314
"github.com/CodeMonkeyCybersecurity/shells/pkg/discovery/asn"
15+
"github.com/CodeMonkeyCybersecurity/shells/pkg/discovery/cache"
1416
"github.com/CodeMonkeyCybersecurity/shells/pkg/discovery/dns"
1517
"github.com/CodeMonkeyCybersecurity/shells/pkg/discovery/external"
18+
"github.com/CodeMonkeyCybersecurity/shells/pkg/discovery/ratelimit"
1619
"github.com/CodeMonkeyCybersecurity/shells/pkg/discovery/search"
1720
"github.com/CodeMonkeyCybersecurity/shells/pkg/discovery/web"
1821
"github.com/CodeMonkeyCybersecurity/shells/pkg/discovery/whois"
@@ -33,6 +36,8 @@ type EnhancedDiscovery struct {
3336
assetLock sync.RWMutex
3437
recursionDepth int
3538
maxRecursion int
39+
cache *cache.APICache
40+
rateLimiter *ratelimit.RateLimiter
3641
}
3742

3843
// NewEnhancedDiscovery creates enhanced discovery module
@@ -50,6 +55,17 @@ func NewEnhancedDiscovery(config *DiscoveryConfig, logger *logger.Logger, cfg *c
5055
}
5156
}
5257

58+
// Initialize cache directory
59+
cacheDir := filepath.Join("/tmp", "shells_cache")
60+
apiCache, err := cache.NewAPICache(cacheDir, 24*time.Hour, logger)
61+
if err != nil {
62+
logger.Error("Failed to initialize cache", "error", err)
63+
apiCache = nil
64+
}
65+
66+
// Initialize rate limiter
67+
rateLimiter := ratelimit.GetGlobalRateLimiter(logger)
68+
5369
return &EnhancedDiscovery{
5470
config: config,
5571
logger: logger,
@@ -62,6 +78,8 @@ func NewEnhancedDiscovery(config *DiscoveryConfig, logger *logger.Logger, cfg *c
6278
censysClient: censysClient,
6379
discoveredAssets: make(map[string]bool),
6480
maxRecursion: 3,
81+
cache: apiCache,
82+
rateLimiter: rateLimiter,
6583
}
6684
}
6785

0 commit comments

Comments
 (0)