Files
god-eye/internal/scanner/helpers.go
Vyntral b1bf119c82 v0.1.1: Major AI improvements, new security modules, and documentation fixes
## AI & CVE Improvements
- Fix AI report to display actual subdomain names instead of generic placeholders
- Add 10-year CVE filter to reduce false positives from outdated vulnerabilities
- Integrate CISA KEV (Known Exploited Vulnerabilities) database support
- Improve AI analysis prompt for more accurate security findings

## New Security Modules
- Add wildcard DNS detection with multi-phase validation (DNS + HTTP)
- Add TLS certificate analyzer for certificate chain inspection
- Add comprehensive rate limiting module for API requests
- Add retry mechanism with exponential backoff
- Add stealth mode for reduced detection during scans
- Add progress tracking module for better UX

## Code Refactoring
- Extract scanner output logic to dedicated module
- Add base source interface for consistent passive source implementation
- Reduce admin panel paths to common generic patterns only
- Improve HTTP client with connection pooling
- Add JSON output formatter

## Documentation Updates
- Correct passive source count to 20 (was incorrectly stated as 34)
- Fix AI model names: deepseek-r1:1.5b (fast) + qwen2.5-coder:7b (deep)
- Update all markdown files for consistency
- Relocate demo GIFs to assets/ directory
- Add benchmark disclaimer for test variability

## Files Changed
- 4 documentation files updated (README, AI_SETUP, BENCHMARK, EXAMPLES)
- 11 new source files added
- 12 existing files modified
2025-11-21 12:00:58 +01:00

178 lines
3.7 KiB
Go

package scanner
import (
"bufio"
"fmt"
"net"
"os"
"sort"
"strings"
"sync"
"time"
"god-eye/internal/config"
)
// LoadWordlist loads words from a file
func LoadWordlist(path string) ([]string, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
var words []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
word := strings.TrimSpace(scanner.Text())
if word != "" && !strings.HasPrefix(word, "#") {
words = append(words, word)
}
}
return words, scanner.Err()
}
// ScanPorts scans ports on an IP address
func ScanPorts(ip string, ports []int, timeout int) []int {
var openPorts []int
var mu sync.Mutex
var wg sync.WaitGroup
for _, port := range ports {
wg.Add(1)
go func(p int) {
defer wg.Done()
address := fmt.Sprintf("%s:%d", ip, p)
conn, err := net.DialTimeout("tcp", address, time.Duration(timeout)*time.Second)
if err == nil {
conn.Close()
mu.Lock()
openPorts = append(openPorts, p)
mu.Unlock()
}
}(port)
}
wg.Wait()
sort.Ints(openPorts)
return openPorts
}
// Helper functions for AI analysis
func countSubdomainsWithAI(results map[string]*config.SubdomainResult) int {
count := 0
for _, r := range results {
if len(r.AIFindings) > 0 {
count++
}
}
return count
}
func countActive(results map[string]*config.SubdomainResult) int {
count := 0
for _, r := range results {
if r.StatusCode >= 200 && r.StatusCode < 400 {
count++
}
}
return count
}
func countVulns(results map[string]*config.SubdomainResult) int {
count := 0
for _, r := range results {
if r.OpenRedirect || r.CORSMisconfig != "" || len(r.DangerousMethods) > 0 ||
r.GitExposed || r.SvnExposed || len(r.BackupFiles) > 0 {
count++
}
}
return count
}
func buildAISummary(results map[string]*config.SubdomainResult) string {
var summary strings.Builder
criticalCount := 0
highCount := 0
mediumCount := 0
for sub, r := range results {
if len(r.AIFindings) == 0 {
continue
}
switch r.AISeverity {
case "critical":
criticalCount++
summary.WriteString(fmt.Sprintf("\n[CRITICAL] %s:\n", sub))
case "high":
highCount++
summary.WriteString(fmt.Sprintf("\n[HIGH] %s:\n", sub))
case "medium":
mediumCount++
summary.WriteString(fmt.Sprintf("\n[MEDIUM] %s:\n", sub))
default:
continue
}
// Add first 3 findings
for i, finding := range r.AIFindings {
if i >= 3 {
break
}
summary.WriteString(fmt.Sprintf(" - %s\n", finding))
}
// Add CVE findings
if len(r.CVEFindings) > 0 {
summary.WriteString(" CVEs:\n")
for _, cve := range r.CVEFindings {
summary.WriteString(fmt.Sprintf(" - %s\n", cve))
}
}
}
header := fmt.Sprintf("Summary: %d critical, %d high, %d medium findings\n", criticalCount, highCount, mediumCount)
return header + summary.String()
}
// ParseResolvers parses custom resolvers string
func ParseResolvers(resolversStr string) []string {
var resolvers []string
if resolversStr != "" {
for _, r := range strings.Split(resolversStr, ",") {
r = strings.TrimSpace(r)
if r != "" {
if !strings.Contains(r, ":") {
r = r + ":53"
}
resolvers = append(resolvers, r)
}
}
}
if len(resolvers) == 0 {
resolvers = config.DefaultResolvers
}
return resolvers
}
// ParsePorts parses custom ports string
func ParsePorts(portsStr string) []int {
var customPorts []int
if portsStr != "" {
for _, p := range strings.Split(portsStr, ",") {
p = strings.TrimSpace(p)
var port int
if _, err := fmt.Sscanf(p, "%d", &port); err == nil && port > 0 && port < 65536 {
customPorts = append(customPorts, port)
}
}
}
if len(customPorts) == 0 {
customPorts = []int{80, 443, 8080, 8443}
}
return customPorts
}