yellow.git


yellow

~ opinionated web scanning pipeline for pentesters in a hurry
git clone https://github.com/djnnvx/yellow.git
log | files | refs | archive | README | LICENSE

gobuster.go (2507B)

      1 package scan
      2 
      3 import (
      4 	"context"
      5 	"errors"
      6 	"fmt"
      7 	"net/url"
      8 	"time"
      9 
     10 	"evil.djnn.sh/djnn/yellow/core"
     11 	"evil.djnn.sh/djnn/yellow/helpers"
     12 	"github.com/OJ/gobuster/v3/cli"
     13 	"github.com/OJ/gobuster/v3/gobusterdir"
     14 	"github.com/OJ/gobuster/v3/libgobuster"
     15 )
     16 
     17 type Gobuster struct {
     18 	MaxURLs int
     19 }
     20 
     21 func (*Gobuster) Name() string { return "gobuster" }
     22 
     23 func (g *Gobuster) Run(ctx *core.Context) error {
     24 	fmt.Println("Running gobuster on", ctx.Domain)
     25 	if ctx.DryRun {
     26 		return nil
     27 	}
     28 
     29 	roots := capURLs(dirRoots(ctx.URLs), g.MaxURLs, "gobuster")
     30 	if len(roots) == 0 {
     31 		roots = []string{ctx.Domain}
     32 	}
     33 
     34 	for i, root := range roots {
     35 		outfile := ctx.ScanPath + "/gobuster.txt"
     36 		if len(roots) > 1 {
     37 			outfile = fmt.Sprintf("%s/gobuster-%d.txt", ctx.ScanPath, i+1)
     38 		}
     39 		bustDir(ctx, root, outfile)
     40 	}
     41 	return nil
     42 }
     43 
     44 func bustDir(ctx *core.Context, rawUrl, outfile string) {
     45 	globalOpts := libgobuster.Options{}
     46 	globalOpts.Wordlist = ctx.Wordlist
     47 	globalOpts.OutputFilename = outfile
     48 	globalOpts.Quiet = false
     49 	globalOpts.Threads = 50
     50 
     51 	globalOpts.WordlistOffset = 0
     52 	globalOpts.Debug = false
     53 	globalOpts.DiscoverPatternFile = ""
     54 	globalOpts.Patterns = make([]string, 0)
     55 	globalOpts.DiscoverPatterns = make([]string, 0)
     56 	globalOpts.NoError = false
     57 	globalOpts.NoProgress = false
     58 	globalOpts.Delay = time.Second
     59 
     60 	u, err := url.Parse(rawUrl)
     61 	if err != nil {
     62 		fmt.Printf("[!] gobuster: invalid URL %s: %v\n", rawUrl, err)
     63 		return
     64 	}
     65 
     66 	pluginOpts := gobusterdir.NewOptions()
     67 	pluginOpts.Proxy = ctx.Proxy
     68 	pluginOpts.NoTLSValidation = ctx.Insecure
     69 	pluginOpts.UserAgent = helper.GetUserAgent()
     70 	pluginOpts.URL = u
     71 	pluginOpts.Method = "GET"
     72 	pluginOpts.Timeout = time.Second * 5
     73 
     74 	ssc, _ := libgobuster.ParseCommaSeparatedInt("302,404,500")
     75 	pluginOpts.StatusCodesBlacklistParsed = ssc
     76 
     77 	log := libgobuster.NewLogger(globalOpts.Debug)
     78 	plugin, err := gobusterdir.New(&globalOpts, pluginOpts, log)
     79 	if err != nil {
     80 		fmt.Printf("[!] gobuster: cannot load plugin: %v\n", err)
     81 		return
     82 	}
     83 
     84 	mainContext, cancel := context.WithCancel(context.Background())
     85 	defer cancel()
     86 	if err := cli.Gobuster(mainContext, &globalOpts, plugin, log); err != nil {
     87 
     88 		var wErr *gobusterdir.WildcardError
     89 		if errors.As(err, &wErr) {
     90 			fmt.Printf("%v.\nTo continue please exclude the status code or the length\n", wErr)
     91 			fmt.Printf("\nSince gobuster cannot make the difference between good and bad urls, it will be skipped.\n\n")
     92 			return
     93 		}
     94 	}
     95 
     96 	fmt.Printf("[SCAN %s] Gobuster scan for %s completed\n\n", rawUrl, rawUrl)
     97 }