yellow~ opinionated web scanning pipeline for pentesters in a hurry |
| git clone https://github.com/djnnvx/yellow.git |
| log | files | refs | archive | README | LICENSE |
run.go (2344B)
1 package scan 2 3 import ( 4 "fmt" 5 "os" 6 "time" 7 8 "evil.djnn.sh/djnn/yellow/core" 9 "evil.djnn.sh/djnn/yellow/helpers" 10 ) 11 12 type ScanOpts struct { 13 Domain string 14 ScanPath string 15 Proxy string 16 DryRun bool 17 RateLimit int32 18 WordlistPath string 19 ForceInsecure bool 20 Gobuster bool 21 PortScan bool 22 Ports string 23 Nuclei bool 24 NoKatana bool 25 KatanaDepth int 26 KatanaMaxTime time.Duration 27 KatanaMaxURLs int 28 NoSecrets bool 29 } 30 31 // context builds a per-target Context from the current options. 32 func (opts *ScanOpts) context() *core.Context { 33 return &core.Context{ 34 Domain: opts.Domain, 35 ScanPath: opts.ScanPath, 36 Proxy: opts.Proxy, 37 DryRun: opts.DryRun, 38 RateLimit: opts.RateLimit, 39 Wordlist: opts.WordlistPath, 40 Insecure: opts.ForceInsecure, 41 } 42 } 43 44 // webModules is the ordered web-scan pipeline. Gobuster is appended unless 45 // directory bruteforcing was disabled. 46 func (opts *ScanOpts) webModules() []core.Module { 47 modules := []core.Module{ 48 &Sitemap{}, 49 &RobotsTxt{}, 50 } 51 if !opts.NoKatana { 52 modules = append(modules, &Katana{Depth: opts.KatanaDepth, Duration: opts.KatanaMaxTime}) 53 } 54 if !opts.NoSecrets { 55 modules = append(modules, &Secrets{MaxURLs: opts.KatanaMaxURLs}) 56 } 57 modules = append(modules, &Tlsx{}, &WappalyzerGo{}, &Cvemap{}, &Httpx{}) 58 59 if opts.Nuclei { 60 modules = append(modules, &Nuclei{MaxURLs: opts.KatanaMaxURLs}) 61 } 62 if opts.Gobuster { 63 modules = append(modules, &Gobuster{MaxURLs: opts.KatanaMaxURLs}) 64 } 65 return modules 66 } 67 68 func (opts *ScanOpts) Run() { 69 fmt.Printf("\n[SCAN] domain: %s\n", opts.Domain) 70 71 if opts.PortScan { 72 opts.runPortScan() 73 } 74 75 fullDomain, ok := helper.ResolveWebTarget(opts.Domain, opts.ForceInsecure) 76 if !ok { 77 fmt.Printf("[SCAN %s] => no web panel online. skipping\n", opts.Domain) 78 return 79 } 80 81 fmt.Printf("[SCAN %s] web panel online (%s)....running web scans\n", opts.Domain, fullDomain) 82 83 /* per-domain output dir; setting opts.ScanPath directly would nest dirs */ 84 pathForDomain := opts.ScanPath + "/" + opts.Domain 85 if err := os.MkdirAll(pathForDomain, 0755); err != nil { 86 fmt.Printf("[!] scan: could not create %s, skipping %s: %v\n", pathForDomain, opts.Domain, err) 87 return 88 } 89 90 ctx := opts.context() 91 ctx.Domain = fullDomain 92 ctx.ScanPath = pathForDomain 93 94 core.RunModules(ctx, opts.webModules()) 95 }