Update upstream source from tag 'upstream/3.4.0'
Update to upstream version '3.4.0'
with Debian dir af698f0e1c9d2ffaa853be046d23015fdc235172
Sophie Brun
1 year, 5 months ago
13 | 13 | go-version: ${{ matrix.go }} |
14 | 14 | |
15 | 15 | - name: Check out code |
16 | uses: actions/[email protected] | |
16 | uses: actions/[email protected] | |
17 | 17 | |
18 | 18 | - name: build cache |
19 | 19 | uses: actions/cache@v3 |
4 | 4 | name: lint |
5 | 5 | runs-on: ubuntu-latest |
6 | 6 | steps: |
7 | - uses: actions/[email protected] | |
7 | - uses: actions/[email protected] | |
8 | 8 | |
9 | 9 | - uses: actions/setup-go@v3 |
10 | 10 | with: |
12 | 12 | runs-on: ubuntu-latest |
13 | 13 | steps: |
14 | 14 | - name: Checkout |
15 | uses: actions/[email protected] | |
15 | uses: actions/[email protected] | |
16 | 16 | with: |
17 | 17 | fetch-depth: 0 |
18 | 18 | - name: Fetch all tags |
22 | 22 | with: |
23 | 23 | go-version: 1.19 |
24 | 24 | - name: Run GoReleaser |
25 | uses: goreleaser/goreleaser-action@v3 | |
25 | uses: goreleaser/goreleaser-action@v4 | |
26 | 26 | with: |
27 | 27 | distribution: goreleaser |
28 | 28 | version: latest |
0 | # Gobuster v3.2.0 | |
0 | # Gobuster | |
1 | 1 | |
2 | 2 | Gobuster is a tool used to brute-force: |
3 | 3 | |
21 | 21 | |
22 | 22 | # Changes |
23 | 23 | |
24 | ## 3.4 | |
25 | ||
26 | - Enable TLS1.0 and TLS1.1 support | |
27 | - Add TFTP mode to search for files on tftp servers | |
28 | ||
24 | 29 | ## 3.3 |
25 | 30 | |
26 | - Support TLS client certificates / mtl | |
31 | - Support TLS client certificates / mtls | |
27 | 32 | - support loading extensions from file |
28 | 33 | - support fuzzing POST body, HTTP headers and basic auth |
29 | 34 | - new option to not canonicalize header names |
0 | package cmd | |
1 | ||
2 | import ( | |
3 | "fmt" | |
4 | "log" | |
5 | "strings" | |
6 | "time" | |
7 | ||
8 | "github.com/OJ/gobuster/v3/cli" | |
9 | "github.com/OJ/gobuster/v3/gobustertftp" | |
10 | "github.com/OJ/gobuster/v3/libgobuster" | |
11 | "github.com/spf13/cobra" | |
12 | ) | |
13 | ||
14 | // nolint:gochecknoglobals | |
15 | var cmdTFTP *cobra.Command | |
16 | ||
17 | func runTFTP(cmd *cobra.Command, args []string) error { | |
18 | globalopts, pluginopts, err := parseTFTPOptions() | |
19 | if err != nil { | |
20 | return fmt.Errorf("error on parsing arguments: %w", err) | |
21 | } | |
22 | ||
23 | plugin, err := gobustertftp.NewGobusterTFTP(globalopts, pluginopts) | |
24 | if err != nil { | |
25 | return fmt.Errorf("error on creating gobustertftp: %w", err) | |
26 | } | |
27 | ||
28 | if err := cli.Gobuster(mainContext, globalopts, plugin); err != nil { | |
29 | return fmt.Errorf("error on running gobuster: %w", err) | |
30 | } | |
31 | return nil | |
32 | } | |
33 | ||
34 | func parseTFTPOptions() (*libgobuster.Options, *gobustertftp.OptionsTFTP, error) { | |
35 | globalopts, err := parseGlobalOptions() | |
36 | if err != nil { | |
37 | return nil, nil, err | |
38 | } | |
39 | pluginOpts := gobustertftp.NewOptionsTFTP() | |
40 | ||
41 | pluginOpts.Server, err = cmdTFTP.Flags().GetString("server") | |
42 | if err != nil { | |
43 | return nil, nil, fmt.Errorf("invalid value for domain: %w", err) | |
44 | } | |
45 | ||
46 | if !strings.Contains(pluginOpts.Server, ":") { | |
47 | pluginOpts.Server = fmt.Sprintf("%s:69", pluginOpts.Server) | |
48 | } | |
49 | ||
50 | pluginOpts.Timeout, err = cmdTFTP.Flags().GetDuration("timeout") | |
51 | if err != nil { | |
52 | return nil, nil, fmt.Errorf("invalid value for timeout: %w", err) | |
53 | } | |
54 | ||
55 | return globalopts, pluginOpts, nil | |
56 | } | |
57 | ||
58 | // nolint:gochecknoinits | |
59 | func init() { | |
60 | cmdTFTP = &cobra.Command{ | |
61 | Use: "tftp", | |
62 | Short: "Uses TFTP enumeration mode", | |
63 | RunE: runTFTP, | |
64 | } | |
65 | ||
66 | cmdTFTP.Flags().StringP("server", "s", "", "The target TFTP server") | |
67 | cmdTFTP.Flags().DurationP("timeout", "", time.Second, "TFTP timeout") | |
68 | if err := cmdTFTP.MarkFlagRequired("server"); err != nil { | |
69 | log.Fatalf("error on marking flag as required: %v", err) | |
70 | } | |
71 | ||
72 | cmdTFTP.PersistentPreRun = func(cmd *cobra.Command, args []string) { | |
73 | configureGlobalOptions() | |
74 | } | |
75 | ||
76 | rootCmd.AddCommand(cmdTFTP) | |
77 | } |
4 | 4 | require ( |
5 | 5 | github.com/fatih/color v1.13.0 |
6 | 6 | github.com/google/uuid v1.3.0 |
7 | github.com/pin/tftp/v3 v3.0.0 | |
7 | 8 | github.com/spf13/cobra v1.6.1 |
8 | golang.org/x/crypto v0.1.0 | |
9 | golang.org/x/term v0.1.0 | |
9 | golang.org/x/crypto v0.4.0 | |
10 | golang.org/x/term v0.3.0 | |
10 | 11 | ) |
11 | 12 | |
12 | 13 | require ( |
13 | github.com/inconshreveable/mousetrap v1.0.1 // indirect | |
14 | github.com/inconshreveable/mousetrap v1.1.0 // indirect | |
14 | 15 | github.com/mattn/go-colorable v0.1.13 // indirect |
15 | 16 | github.com/mattn/go-isatty v0.0.16 // indirect |
16 | 17 | github.com/spf13/pflag v1.0.5 // indirect |
17 | golang.org/x/sys v0.1.0 // indirect | |
18 | golang.org/x/net v0.4.0 // indirect | |
19 | golang.org/x/sys v0.3.0 // indirect | |
18 | 20 | ) |
2 | 2 | github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= |
3 | 3 | github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= |
4 | 4 | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= |
5 | github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= | |
6 | 5 | github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= |
6 | github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= | |
7 | github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= | |
7 | 8 | github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= |
8 | 9 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= |
9 | 10 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= |
11 | 12 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= |
12 | 13 | github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= |
13 | 14 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= |
15 | github.com/pin/tftp/v3 v3.0.0 h1:o9cQpmWBSbgiaYXuN+qJAB12XBIv4dT7OuOONucn2l0= | |
16 | github.com/pin/tftp/v3 v3.0.0/go.mod h1:xwQaN4viYL019tM4i8iecm++5cGxSqen6AJEOEyEI0w= | |
14 | 17 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= |
15 | 18 | github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= |
16 | 19 | github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= |
17 | 20 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= |
18 | 21 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= |
19 | golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= | |
20 | golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= | |
22 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | |
23 | golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8= | |
24 | golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= | |
25 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | |
26 | golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= | |
27 | golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= | |
28 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |
21 | 29 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
22 | 30 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
23 | 31 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
24 | 32 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
25 | golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= | |
26 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |
27 | golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw= | |
28 | golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= | |
33 | golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= | |
34 | golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |
35 | golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= | |
36 | golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= | |
37 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | |
29 | 38 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
30 | 39 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
0 | package gobustertftp | |
1 | ||
2 | import ( | |
3 | "bufio" | |
4 | "bytes" | |
5 | "context" | |
6 | "fmt" | |
7 | "strings" | |
8 | "text/tabwriter" | |
9 | ||
10 | "github.com/OJ/gobuster/v3/libgobuster" | |
11 | ||
12 | "github.com/pin/tftp/v3" | |
13 | ) | |
14 | ||
15 | // GobusterTFTP is the main type to implement the interface | |
16 | type GobusterTFTP struct { | |
17 | globalopts *libgobuster.Options | |
18 | options *OptionsTFTP | |
19 | } | |
20 | ||
21 | // NewGobusterTFTP creates a new initialized NewGobusterTFTP | |
22 | func NewGobusterTFTP(globalopts *libgobuster.Options, opts *OptionsTFTP) (*GobusterTFTP, error) { | |
23 | if globalopts == nil { | |
24 | return nil, fmt.Errorf("please provide valid global options") | |
25 | } | |
26 | ||
27 | if opts == nil { | |
28 | return nil, fmt.Errorf("please provide valid plugin options") | |
29 | } | |
30 | ||
31 | g := GobusterTFTP{ | |
32 | options: opts, | |
33 | globalopts: globalopts, | |
34 | } | |
35 | return &g, nil | |
36 | } | |
37 | ||
38 | // Name should return the name of the plugin | |
39 | func (d *GobusterTFTP) Name() string { | |
40 | return "TFTP enumeration" | |
41 | } | |
42 | ||
43 | // PreRun is the pre run implementation of gobustertftp | |
44 | func (d *GobusterTFTP) PreRun(ctx context.Context) error { | |
45 | _, err := tftp.NewClient(d.options.Server) | |
46 | if err != nil { | |
47 | return err | |
48 | } | |
49 | return nil | |
50 | } | |
51 | ||
52 | // ProcessWord is the process implementation of gobustertftp | |
53 | func (d *GobusterTFTP) ProcessWord(ctx context.Context, word string, progress *libgobuster.Progress) error { | |
54 | c, err := tftp.NewClient(d.options.Server) | |
55 | if err != nil { | |
56 | return err | |
57 | } | |
58 | c.SetTimeout(d.options.Timeout) | |
59 | wt, err := c.Receive(word, "octet") | |
60 | if err != nil { | |
61 | // file not found | |
62 | if d.globalopts.Verbose { | |
63 | progress.ResultChan <- Result{ | |
64 | Filename: word, | |
65 | Found: false, | |
66 | ErrorMessage: err.Error(), | |
67 | } | |
68 | } | |
69 | ||
70 | return nil | |
71 | } | |
72 | result := Result{ | |
73 | Filename: word, | |
74 | Found: true, | |
75 | } | |
76 | if n, ok := wt.(tftp.IncomingTransfer).Size(); ok { | |
77 | result.Size = n | |
78 | } | |
79 | progress.ResultChan <- result | |
80 | return nil | |
81 | } | |
82 | ||
83 | func (d *GobusterTFTP) AdditionalWords(word string) []string { | |
84 | return []string{} | |
85 | } | |
86 | ||
87 | // GetConfigString returns the string representation of the current config | |
88 | func (d *GobusterTFTP) GetConfigString() (string, error) { | |
89 | var buffer bytes.Buffer | |
90 | bw := bufio.NewWriter(&buffer) | |
91 | tw := tabwriter.NewWriter(bw, 0, 5, 3, ' ', 0) | |
92 | o := d.options | |
93 | ||
94 | if _, err := fmt.Fprintf(tw, "[+] Server:\t%s\n", o.Server); err != nil { | |
95 | return "", err | |
96 | } | |
97 | ||
98 | if _, err := fmt.Fprintf(tw, "[+] Threads:\t%d\n", d.globalopts.Threads); err != nil { | |
99 | return "", err | |
100 | } | |
101 | ||
102 | if d.globalopts.Delay > 0 { | |
103 | if _, err := fmt.Fprintf(tw, "[+] Delay:\t%s\n", d.globalopts.Delay); err != nil { | |
104 | return "", err | |
105 | } | |
106 | } | |
107 | ||
108 | if _, err := fmt.Fprintf(tw, "[+] Timeout:\t%s\n", o.Timeout.String()); err != nil { | |
109 | return "", err | |
110 | } | |
111 | ||
112 | wordlist := "stdin (pipe)" | |
113 | if d.globalopts.Wordlist != "-" { | |
114 | wordlist = d.globalopts.Wordlist | |
115 | } | |
116 | if _, err := fmt.Fprintf(tw, "[+] Wordlist:\t%s\n", wordlist); err != nil { | |
117 | return "", err | |
118 | } | |
119 | ||
120 | if d.globalopts.PatternFile != "" { | |
121 | if _, err := fmt.Fprintf(tw, "[+] Patterns:\t%s (%d entries)\n", d.globalopts.PatternFile, len(d.globalopts.Patterns)); err != nil { | |
122 | return "", err | |
123 | } | |
124 | } | |
125 | ||
126 | if d.globalopts.Verbose { | |
127 | if _, err := fmt.Fprintf(tw, "[+] Verbose:\ttrue\n"); err != nil { | |
128 | return "", err | |
129 | } | |
130 | } | |
131 | ||
132 | if err := tw.Flush(); err != nil { | |
133 | return "", fmt.Errorf("error on tostring: %w", err) | |
134 | } | |
135 | ||
136 | if err := bw.Flush(); err != nil { | |
137 | return "", fmt.Errorf("error on tostring: %w", err) | |
138 | } | |
139 | ||
140 | return strings.TrimSpace(buffer.String()), nil | |
141 | } |
0 | package gobustertftp | |
1 | ||
2 | import ( | |
3 | "time" | |
4 | ) | |
5 | ||
6 | // OptionsTFTP holds all options for the tftp plugin | |
7 | type OptionsTFTP struct { | |
8 | Server string | |
9 | Timeout time.Duration | |
10 | } | |
11 | ||
12 | // NewOptionsTFTP returns a new initialized OptionsTFTP | |
13 | func NewOptionsTFTP() *OptionsTFTP { | |
14 | return &OptionsTFTP{} | |
15 | } |
0 | package gobustertftp | |
1 | ||
2 | import ( | |
3 | "bytes" | |
4 | "fmt" | |
5 | ||
6 | "github.com/fatih/color" | |
7 | ) | |
8 | ||
9 | var ( | |
10 | red = color.New(color.FgRed).FprintfFunc() | |
11 | green = color.New(color.FgGreen).FprintfFunc() | |
12 | ) | |
13 | ||
14 | // Result represents a single result | |
15 | type Result struct { | |
16 | Filename string | |
17 | Found bool | |
18 | Size int64 | |
19 | ErrorMessage string | |
20 | } | |
21 | ||
22 | // ResultToString converts the Result to it's textual representation | |
23 | func (r Result) ResultToString() (string, error) { | |
24 | buf := &bytes.Buffer{} | |
25 | ||
26 | if r.Found { | |
27 | green(buf, "Found: ") | |
28 | if _, err := fmt.Fprintf(buf, "%s", r.Filename); err != nil { | |
29 | return "", err | |
30 | } | |
31 | if r.Size > 0 { | |
32 | if _, err := fmt.Fprintf(buf, " [%d]", r.Size); err != nil { | |
33 | return "", err | |
34 | } | |
35 | } | |
36 | } else { | |
37 | red(buf, "Missed: ") | |
38 | if _, err := fmt.Fprintf(buf, "%s - %s", r.Filename, r.ErrorMessage); err != nil { | |
39 | return "", err | |
40 | } | |
41 | } | |
42 | ||
43 | s := buf.String() | |
44 | return s, nil | |
45 | } |