Codebase list gobuster / 6d0dfc0
New upstream snapshot. Kali Janitor 1 year, 7 months ago
44 changed file(s) with 447 addition(s) and 458 deletion(s). Raw diff Collapse all Expand all
55 runs-on: ubuntu-latest
66 strategy:
77 matrix:
8 go: ["1.13.10", "1.14.2"]
8 go: ["1.17", "1.18", "1.19"]
99 steps:
1010 - name: Set up Go ${{ matrix.go }}
11 uses: actions/setup-go@v1
11 uses: actions/setup-go@v2
1212 with:
1313 go-version: ${{ matrix.go }}
14 id: go
1514
16 - name: Check out code into the Go module directory
15 - name: Check out code
1716 uses: actions/checkout@v2
17
18 - name: build cache
19 uses: actions/cache@v2
20 with:
21 path: ~/go/pkg/mod
22 key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
23 restore-keys: |
24 ${{ runner.os }}-go-
1825
1926 - name: Get dependencies
2027 run: |
2128 go get -v -t -d ./...
22 if [ -f Gopkg.toml ]; then
23 curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
24 dep ensure
25 fi
2629
2730 - name: Build
2831 run: go build -v .
2932
3033 - name: Test
3134 run: make test
32
33 - name: Lint
34 run: make lint
0 name: golangci-lint
1 on: [push, pull_request]
2 jobs:
3 golangci:
4 name: lint
5 runs-on: ubuntu-latest
6 steps:
7 - uses: actions/checkout@v2
8 - name: golangci-lint
9 uses: golangci/golangci-lint-action@v2
10 with:
11 version: latest
+0
-43
.golangci.yml less more
0 linters:
1 enable-all: true
2 disable:
3 - wsl
4 - gocyclo
5 - gocognit
6 - funlen
7 - lll
8 - dogsled
9 - gomnd
10 - nestif
11 - testpackage
12 - godot
13 - goerr113
14 - gofumpt
15
16 issues:
17 exclude-rules:
18 - text: "TLS InsecureSkipVerify may be true"
19 linters:
20 - gosec
21
22 - text: ifElseChain
23 linters:
24 - gocritic
25
26 - path: cli\\cmd\\.+\.go
27 linters:
28 - gochecknoinits
29 - gochecknoglobals
30
31 - path: cli/cmd/.+\.go
32 linters:
33 - gochecknoinits
34 - gochecknoglobals
35
36 - path: helper/useragents.go
37 linters:
38 - gochecknoglobals
39
40 - path: _test\.go
41 linters:
42 - scopelint
00 FROM golang:latest AS build-env
11 WORKDIR /src
2 ENV GO111MODULE=on
2 ENV CGO_ENABLED=0
33 COPY go.mod /src/
44 RUN go mod download
55 COPY . .
6 RUN CGO_ENABLED=0 GOOS=linux go build -a -o gobuster -ldflags="-s -w" -gcflags="all=-trimpath=/src" -asmflags="all=-trimpath=/src"
6 RUN go build -a -o gobuster -ldflags="-s -w" -gcflags="all=-trimpath=/src" -asmflags="all=-trimpath=/src"
77
88 FROM alpine:latest
99
11 ARCHS=amd64 386
22 LDFLAGS="-s -w"
33
4 .PHONY: current
45 current:
56 @go build -o ./gobuster; \
67 echo "Done."
78
9 .PHONY: fmt
810 fmt:
911 @go fmt ./...; \
1012 echo "Done."
1113
14 .PHONY: update
1215 update:
1316 @go get -u; \
1417 go mod tidy -v; \
1518 echo "Done."
1619
20 .PHONY: windows
1721 windows:
1822 @for GOARCH in ${ARCHS}; do \
1923 echo "Building for windows $${GOARCH} ..." ; \
2226 done; \
2327 echo "Done."
2428
29 .PHONY: linux
2530 linux:
2631 @for GOARCH in ${ARCHS}; do \
2732 echo "Building for linux $${GOARCH} ..." ; \
3035 done; \
3136 echo "Done."
3237
38 .PHONY: darwin
3339 darwin:
3440 @for GOARCH in ${ARCHS}; do \
3541 echo "Building for darwin $${GOARCH} ..." ; \
3844 done; \
3945 echo "Done."
4046
47 .PHONY: all
4148 all: clean fmt update test lint darwin linux windows
4249
50 .PHONY: test
4351 test:
4452 @go test -v -race ./... ; \
4553 echo "Done."
4654
55 .PHONY: lint
4756 lint:
48 @if [ ! -f "$$(go env GOPATH)/bin/golangci-lint" ]; then \
49 curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $$(go env GOPATH)/bin v1.29.0; \
50 fi
5157 "$$(go env GOPATH)/bin/golangci-lint" run ./...
5258 go mod tidy
5359
60 .PHONY: lint-update
61 lint-update:
62 curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $$(go env GOPATH)/bin
63 $$(go env GOPATH)/bin/golangci-lint --version
64
65 .PHONY: lint-docker
66 lint-docker:
67 docker pull golangci/golangci-lint:latest
68 docker run --rm -v $$(pwd):/app -w /app golangci/golangci-lint:latest golangci-lint run
69
70 .PHONY: clean
5471 clean:
5572 @rm -rf ${TARGET}/* ; \
5673 go clean ./... ; \
11
22 Gobuster is a tool used to brute-force:
33
4 * URIs (directories and files) in web sites.
5 * DNS subdomains (with wildcard support).
6 * Virtual Host names on target web servers.
7 * Open Amazon S3 buckets
4 - URIs (directories and files) in web sites.
5 - DNS subdomains (with wildcard support).
6 - Virtual Host names on target web servers.
7 - Open Amazon S3 buckets
88
99 ## Tags, Statuses, etc
1010
2828
2929 Yes, you're probably correct. Feel free to:
3030
31 * Not use it.
32 * Show me how to do it better.
31 - Not use it.
32 - Show me how to do it better.
3333
3434 ## Love this tool? Back it!
3535
3939
4040 All funds that are donated to this project will be donated to charity. A full log of charity donations will be available in this repository as they are processed.
4141
42 ## Changes in 3.1-dev
43
44 - Use go 1.16
45 - use contexts in the correct way
46 - get rid of the wildcard flag (except in DNS mode)
47
4248 ## Changes in 3.1
4349
44 * enumerate public AWS S3 buckets
45 * fuzzing mode
46 * specify HTTP method
47 * added support for patterns. You can now specify a file containing patterns that are applied to every word, one by line. Every occurrence of the term `{GOBUSTER}` in it will be replaced with the current wordlist item. Please use with caution as this can cause increase the number of requests issued a lot.
48 * The shorthand `p` flag which was assigned to proxy is now used by the pattern flag
50 - enumerate public AWS S3 buckets
51 - fuzzing mode
52 - specify HTTP method
53 - added support for patterns. You can now specify a file containing patterns that are applied to every word, one by line. Every occurrence of the term `{GOBUSTER}` in it will be replaced with the current wordlist item. Please use with caution as this can cause increase the number of requests issued a lot.
54 - The shorthand `p` flag which was assigned to proxy is now used by the pattern flag
4955
5056 ## Changes in 3.0
5157
52 * New CLI options so modes are strictly separated (`-m` is now gone!)
53 * Performance Optimizations and better connection handling
54 * Ability to enumerate vhost names
55 * Option to supply custom HTTP headers
58 - New CLI options so modes are strictly separated (`-m` is now gone!)
59 - Performance Optimizations and better connection handling
60 - Ability to enumerate vhost names
61 - Option to supply custom HTTP headers
5662
5763 ## Available Modes
5864
59 * dir - the classic directory brute-forcing mode
60 * dns - DNS subdomain brute-forcing mode
61 * s3 - Enumerate open S3 buckets and look for existence and bucket listings
62 * vhost - virtual host brute-forcing mode (not the same as DNS!)
65 - dir - the classic directory brute-forcing mode
66 - dns - DNS subdomain brute-forcing mode
67 - s3 - Enumerate open S3 buckets and look for existence and bucket listings
68 - vhost - virtual host brute-forcing mode (not the same as DNS!)
6369
6470 ## Built-in Help
6571
6672 Help is built-in!
6773
68 * `gobuster help` - outputs the top-level help.
69 * `gobuster help <mode>` - outputs the help specific to that mode.
74 - `gobuster help` - outputs the top-level help.
75 - `gobuster help <mode>` - outputs the help specific to that mode.
7076
7177 ## `dns` Mode Help
7278
168174
169175 If you're stupid enough to trust binaries that I've put together, you can download them from the [releases](https://github.com/OJ/gobuster/releases) page.
170176
171 ### Using `go get`
172
173 If you have a [Go](https://golang.org/) environment ready to go, it's as easy as:
174
175 ```bash
176 go get github.com/OJ/gobuster
177 ```
177 ### Using `go install`
178
179 If you have a [Go](https://golang.org/) environment ready to go (at least go 1.17), it's as easy as:
180
181 ```bash
182 go install github.com/OJ/gobuster/v3@latest
183 ```
184
185 PS: You need at least go 1.17.0 to compile gobuster.
178186
179187 ## Building From Source
180188
181 Since this tool is written in [Go](https://golang.org/) you need to install the Go language/compiler/etc. Full details of installation and set up can be found [on the Go language website](https://golang.org/doc/install). Once installed you have two options.
189 Since this tool is written in [Go](https://golang.org/) you need to install the Go language/compiler/etc. Full details of installation and set up can be found [on the Go language website](https://golang.org/doc/install). Once installed you have two options. You need at least go 1.17.0 to compile gobuster.
182190
183191 ### Compiling
184192
185 `gobuster` now has external dependencies, and so they need to be pulled in first:
193 `gobuster` has external dependencies, and so they need to be pulled in first:
186194
187195 ```bash
188196 go get && go build
196204
197205 If you have all the dependencies already, you can make use of the build scripts:
198206
199 * `make` - builds for the current Go configuration (ie. runs `go build`).
200 * `make windows` - builds 32 and 64 bit binaries for windows, and writes them to the `build` folder.
201 * `make linux` - builds 32 and 64 bit binaries for linux, and writes them to the `build` folder.
202 * `make darwin` - builds 32 and 64 bit binaries for darwin, and writes them to the `build` folder.
203 * `make all` - builds for all platforms and architectures, and writes the resulting binaries to the `build` folder.
204 * `make clean` - clears out the `build` folder.
205 * `make test` - runs the tests.
207 - `make` - builds for the current Go configuration (ie. runs `go build`).
208 - `make windows` - builds 32 and 64 bit binaries for windows, and writes them to the `build` folder.
209 - `make linux` - builds 32 and 64 bit binaries for linux, and writes them to the `build` folder.
210 - `make darwin` - builds 32 and 64 bit binaries for darwin, and writes them to the `build` folder.
211 - `make all` - builds for all platforms and architectures, and writes the resulting binaries to the `build` folder.
212 - `make clean` - clears out the `build` folder.
213 - `make test` - runs the tests.
206214
207215 ## Wordlists via STDIN
208216
576584
577585 #### Use case in combination with patterns
578586
579 * Create a custom wordlist for the target containing company names and so on
580 * Create a pattern file to use for common bucket names.
587 - Create a custom wordlist for the target containing company names and so on
588 - Create a pattern file to use for common bucket names.
581589
582590 ```bash
583591 curl -s --output - https://raw.githubusercontent.com/eth0izzle/bucket-stream/master/permutations/extended.txt | sed -s 's/%s/{GOBUSTER}/' > patterns.txt
584592 ```
585593
586 * Run gobuster with the custom input. Be sure to turn verbose mode on to see the bucket details
594 - Run gobuster with the custom input. Be sure to turn verbose mode on to see the bucket details
587595
588596 ```bash
589597 gobuster s3 --wordlist my.custom.wordlist -p patterns.txt -v
00 package cmd
11
22 import (
3 "errors"
34 "fmt"
45 "log"
56
1011 "github.com/spf13/cobra"
1112 )
1213
14 // nolint:gochecknoglobals
1315 var cmdDir *cobra.Command
1416
1517 func runDir(cmd *cobra.Command, args []string) error {
1820 return fmt.Errorf("error on parsing arguments: %w", err)
1921 }
2022
21 plugin, err := gobusterdir.NewGobusterDir(mainContext, globalopts, pluginopts)
23 plugin, err := gobusterdir.NewGobusterDir(globalopts, pluginopts)
2224 if err != nil {
2325 return fmt.Errorf("error on creating gobusterdir: %w", err)
2426 }
2527
2628 if err := cli.Gobuster(mainContext, globalopts, plugin); err != nil {
27 if goberr, ok := err.(*gobusterdir.ErrWildcard); ok {
28 return fmt.Errorf("%s. To continue please exclude the status code, the length or use the --wildcard switch", goberr.Error())
29 var wErr *gobusterdir.ErrWildcard
30 if errors.As(err, &wErr) {
31 return fmt.Errorf("%w. To continue please exclude the status code or the length", wErr)
2932 }
3033 return fmt.Errorf("error on running gobuster: %w", err)
3134 }
6063 if err != nil {
6164 return nil, nil, fmt.Errorf("invalid value for extensions: %w", err)
6265 }
66 ret, err := helper.ParseExtensions(plugin.Extensions)
67 if err != nil {
68 return nil, nil, fmt.Errorf("invalid value for extensions: %w", err)
69 }
70 plugin.ExtensionsParsed = ret
6371
64 if plugin.Extensions != "" {
65 ret, err := helper.ParseExtensions(plugin.Extensions)
66 if err != nil {
67 return nil, nil, fmt.Errorf("invalid value for extensions: %w", err)
68 }
69 plugin.ExtensionsParsed = ret
72 // parse normal status codes
73 plugin.StatusCodes, err = cmdDir.Flags().GetString("status-codes")
74 if err != nil {
75 return nil, nil, fmt.Errorf("invalid value for status-codes: %w", err)
7076 }
77 ret2, err := helper.ParseCommaSeparatedInt(plugin.StatusCodes)
78 if err != nil {
79 return nil, nil, fmt.Errorf("invalid value for status-codes: %w", err)
80 }
81 plugin.StatusCodesParsed = ret2
7182
83 // blacklist will override the normal status codes
7284 plugin.StatusCodesBlacklist, err = cmdDir.Flags().GetString("status-codes-blacklist")
7385 if err != nil {
7486 return nil, nil, fmt.Errorf("invalid value for status-codes-blacklist: %w", err)
7587 }
88 ret3, err := helper.ParseCommaSeparatedInt(plugin.StatusCodesBlacklist)
89 if err != nil {
90 return nil, nil, fmt.Errorf("invalid value for status-codes-blacklist: %w", err)
91 }
92 plugin.StatusCodesBlacklistParsed = ret3
7693
77 // blacklist will override the normal status codes
78 if plugin.StatusCodesBlacklist != "" {
79 ret, err := helper.ParseCommaSeparatedInt(plugin.StatusCodesBlacklist)
80 if err != nil {
81 return nil, nil, fmt.Errorf("invalid value for status-codes-blacklist: %w", err)
82 }
83 plugin.StatusCodesBlacklistParsed = ret
84 } else {
85 // parse normal status codes
86 plugin.StatusCodes, err = cmdDir.Flags().GetString("status-codes")
87 if err != nil {
88 return nil, nil, fmt.Errorf("invalid value for status-codes: %w", err)
89 }
90 ret, err := helper.ParseCommaSeparatedInt(plugin.StatusCodes)
91 if err != nil {
92 return nil, nil, fmt.Errorf("invalid value for status-codes: %w", err)
93 }
94 plugin.StatusCodesParsed = ret
94 if plugin.StatusCodes != "" && plugin.StatusCodesBlacklist != "" {
95 return nil, nil, fmt.Errorf("status-codes and status-codes-blacklist are both set, please set only one")
96 }
97
98 if plugin.StatusCodes == "" && plugin.StatusCodesBlacklist == "" {
99 return nil, nil, fmt.Errorf("status-codes and status-codes-blacklist are both not set, please set one")
95100 }
96101
97102 plugin.UseSlash, err = cmdDir.Flags().GetBool("add-slash")
114119 return nil, nil, fmt.Errorf("invalid value for hide-length: %w", err)
115120 }
116121
117 plugin.WildcardForced, err = cmdDir.Flags().GetBool("wildcard")
118 if err != nil {
119 return nil, nil, fmt.Errorf("invalid value for wildcard: %w", err)
120 }
121
122122 plugin.DiscoverBackup, err = cmdDir.Flags().GetBool("discover-backup")
123123 if err != nil {
124124 return nil, nil, fmt.Errorf("invalid value for discover-backup: %w", err)
132132 return globalopts, plugin, nil
133133 }
134134
135 // nolint:gochecknoinits
135136 func init() {
136137 cmdDir = &cobra.Command{
137138 Use: "dir",
149150 cmdDir.Flags().BoolP("no-status", "n", false, "Don't print status codes")
150151 cmdDir.Flags().Bool("hide-length", false, "Hide the length of the body in the output")
151152 cmdDir.Flags().BoolP("add-slash", "f", false, "Append / to each request")
152 cmdDir.Flags().Bool("wildcard", false, "Force continued operation when wildcard found")
153153 cmdDir.Flags().BoolP("discover-backup", "d", false, "Upon finding a file search for backup files")
154154 cmdDir.Flags().IntSlice("exclude-length", []int{}, "exclude the following content length (completely ignores the status). Supply multiple times to exclude multiple sizes.")
155155
22 import (
33 "context"
44 "fmt"
5 "io/ioutil"
5 "io"
66 "log"
77 "net/http"
88 "net/http/httptest"
3030 pluginopts := gobusterdir.NewOptionsDir()
3131 pluginopts.URL = h.URL
3232 pluginopts.Timeout = 10 * time.Second
33 pluginopts.WildcardForced = true
3433
3534 pluginopts.Extensions = ".php,.csv"
3635 tmpExt, err := helper.ParseExtensions(pluginopts.Extensions)
4645 }
4746 pluginopts.StatusCodesParsed = tmpStat
4847
49 wordlist, err := ioutil.TempFile("", "")
48 wordlist, err := os.CreateTemp("", "")
5049 if err != nil {
5150 b.Fatalf("could not create tempfile: %v", err)
5251 }
7271 }
7372 defer devnull.Close()
7473 log.SetFlags(0)
75 log.SetOutput(ioutil.Discard)
74 log.SetOutput(io.Discard)
7675
7776 // Run the real benchmark
7877 for x := 0; x < b.N; x++ {
7978 os.Stdout = devnull
8079 os.Stderr = devnull
81 plugin, err := gobusterdir.NewGobusterDir(ctx, &globalopts, pluginopts)
80 plugin, err := gobusterdir.NewGobusterDir(&globalopts, pluginopts)
8281 if err != nil {
8382 b.Fatalf("error on creating gobusterdir: %v", err)
8483 }
00 package cmd
11
22 import (
3 "errors"
34 "fmt"
45 "log"
56 "runtime"
1112 "github.com/spf13/cobra"
1213 )
1314
15 // nolint:gochecknoglobals
1416 var cmdDNS *cobra.Command
1517
1618 func runDNS(cmd *cobra.Command, args []string) error {
2527 }
2628
2729 if err := cli.Gobuster(mainContext, globalopts, plugin); err != nil {
28 if goberr, ok := err.(*gobusterdns.ErrWildcard); ok {
29 return fmt.Errorf("%s. To force processing of Wildcard DNS, specify the '--wildcard' switch", goberr.Error())
30 var wErr *gobusterdns.ErrWildcard
31 if errors.As(err, &wErr) {
32 return fmt.Errorf("%w. To force processing of Wildcard DNS, specify the '--wildcard' switch", wErr)
3033 }
3134 return fmt.Errorf("error on running gobuster: %w", err)
3235 }
7780 return globalopts, plugin, nil
7881 }
7982
83 // nolint:gochecknoinits
8084 func init() {
8185 cmdDNS = &cobra.Command{
8286 Use: "dns",
00 package cmd
11
22 import (
3 "errors"
34 "fmt"
45 "log"
56
1011 "github.com/spf13/cobra"
1112 )
1213
14 // nolint:gochecknoglobals
1315 var cmdFuzz *cobra.Command
1416
1517 func runFuzz(cmd *cobra.Command, args []string) error {
1820 return fmt.Errorf("error on parsing arguments: %w", err)
1921 }
2022
21 plugin, err := gobusterfuzz.NewGobusterFuzz(mainContext, globalopts, pluginopts)
23 plugin, err := gobusterfuzz.NewGobusterFuzz(globalopts, pluginopts)
2224 if err != nil {
2325 return fmt.Errorf("error on creating gobusterfuzz: %w", err)
2426 }
2527
2628 if err := cli.Gobuster(mainContext, globalopts, plugin); err != nil {
27 if goberr, ok := err.(*gobusterfuzz.ErrWildcard); ok {
28 return fmt.Errorf("%s. To force processing of Wildcard responses, specify the '--wildcard' switch", goberr.Error())
29 var wErr *gobusterfuzz.ErrWildcard
30 if errors.As(err, &wErr) {
31 return fmt.Errorf("%w. To continue please exclude the status code or the length", wErr)
2932 }
3033 return fmt.Errorf("error on running gobuster: %w", err)
3134 }
5659 plugin.Headers = httpOpts.Headers
5760 plugin.Method = httpOpts.Method
5861
62 // blacklist will override the normal status codes
5963 plugin.ExcludedStatusCodes, err = cmdFuzz.Flags().GetString("excludestatuscodes")
6064 if err != nil {
6165 return nil, nil, fmt.Errorf("invalid value for excludestatuscodes: %w", err)
6266 }
63
64 // blacklist will override the normal status codes
65 if plugin.ExcludedStatusCodes != "" {
66 ret, err := helper.ParseCommaSeparatedInt(plugin.ExcludedStatusCodes)
67 if err != nil {
68 return nil, nil, fmt.Errorf("invalid value for excludestatuscodes: %w", err)
69 }
70 plugin.ExcludedStatusCodesParsed = ret
67 ret, err := helper.ParseCommaSeparatedInt(plugin.ExcludedStatusCodes)
68 if err != nil {
69 return nil, nil, fmt.Errorf("invalid value for excludestatuscodes: %w", err)
7170 }
72
73 plugin.WildcardForced, err = cmdFuzz.Flags().GetBool("wildcard")
74 if err != nil {
75 return nil, nil, fmt.Errorf("invalid value for wildcard: %w", err)
76 }
71 plugin.ExcludedStatusCodesParsed = ret
7772
7873 plugin.ExcludeLength, err = cmdFuzz.Flags().GetIntSlice("exclude-length")
7974 if err != nil {
8378 return globalopts, plugin, nil
8479 }
8580
81 // nolint:gochecknoinits
8682 func init() {
8783 cmdFuzz = &cobra.Command{
8884 Use: "fuzz",
9591 }
9692 cmdFuzz.Flags().StringP("excludestatuscodes", "b", "", "Negative status codes (will override statuscodes if set)")
9793 cmdFuzz.Flags().IntSlice("exclude-length", []int{}, "exclude the following content length (completely ignores the status). Supply multiple times to exclude multiple sizes.")
98 cmdFuzz.Flags().BoolP("wildcard", "", false, "Force continued operation when wildcard found")
9994
10095 cmdFuzz.PersistentPreRun = func(cmd *cobra.Command, args []string) {
10196 configureGlobalOptions()
1010 "github.com/OJ/gobuster/v3/helper"
1111 "github.com/OJ/gobuster/v3/libgobuster"
1212 "github.com/spf13/cobra"
13 "golang.org/x/crypto/ssh/terminal"
13 "golang.org/x/term"
1414 )
1515
1616 func addBasicHTTPOptions(cmd *cobra.Command) {
1818 cmd.Flags().BoolP("random-agent", "", false, "Use a random User-Agent string")
1919 cmd.Flags().StringP("proxy", "", "", "Proxy to use for requests [http(s)://host:port]")
2020 cmd.Flags().DurationP("timeout", "", 10*time.Second, "HTTP Timeout")
21 cmd.Flags().BoolP("no-tls-validation", "k", false, "Skip TLS certificate verification")
2122 }
2223
2324 func addCommonHTTPOptions(cmd *cobra.Command) error {
2728 cmd.Flags().StringP("username", "U", "", "Username for Basic Auth")
2829 cmd.Flags().StringP("password", "P", "", "Password for Basic Auth")
2930 cmd.Flags().BoolP("follow-redirect", "r", false, "Follow redirects")
30 cmd.Flags().BoolP("no-tls-validation", "k", false, "Skip TLS certificate verification")
3131 cmd.Flags().StringArrayP("headers", "H", []string{""}, "Specify HTTP headers, -H 'Header1: val1' -H 'Header2: val2'")
3232 cmd.Flags().StringP("method", "m", "GET", "Use the following HTTP method")
3333
5151 return options, fmt.Errorf("invalid value for random-agent: %w", err)
5252 }
5353 if randomUA {
54 options.UserAgent = helper.GetRandomUserAgent()
54 ua, err := helper.GetRandomUserAgent()
55 if err != nil {
56 return options, err
57 }
58 options.UserAgent = ua
5559 }
5660
5761 options.Proxy, err = cmd.Flags().GetString("proxy")
6266 options.Timeout, err = cmd.Flags().GetDuration("timeout")
6367 if err != nil {
6468 return options, fmt.Errorf("invalid value for timeout: %w", err)
69 }
70
71 options.NoTLSValidation, err = cmd.Flags().GetBool("no-tls-validation")
72 if err != nil {
73 return options, fmt.Errorf("invalid value for no-tls-validation: %w", err)
6574 }
6675 return options, nil
6776 }
7786 options.Proxy = basic.Proxy
7887 options.Timeout = basic.Timeout
7988 options.UserAgent = basic.UserAgent
89 options.NoTLSValidation = basic.NoTLSValidation
8090
8191 options.URL, err = cmd.Flags().GetString("url")
8292 if err != nil {
123133 return options, fmt.Errorf("invalid value for follow-redirect: %w", err)
124134 }
125135
126 options.NoTLSValidation, err = cmd.Flags().GetBool("no-tls-validation")
127 if err != nil {
128 return options, fmt.Errorf("invalid value for no-tls-validation: %w", err)
129 }
130
131136 options.Method, err = cmd.Flags().GetString("method")
132137 if err != nil {
133138 return options, fmt.Errorf("invalid value for method: %w", err)
156161 if options.Username != "" && options.Password == "" {
157162 fmt.Printf("[?] Auth Password: ")
158163 // please don't remove the int cast here as it is sadly needed on windows :/
159 passBytes, err := terminal.ReadPassword(int(syscall.Stdin)) //nolint:unconvert
164 passBytes, err := term.ReadPassword(int(syscall.Stdin)) //nolint:unconvert
160165 // print a newline to simulate the newline that was entered
161166 // this means that formatting/printing after doesn't look bad.
162167 fmt.Println("")
88 "os/signal"
99
1010 "github.com/OJ/gobuster/v3/libgobuster"
11
1211 "github.com/spf13/cobra"
1312 )
1413
14 // nolint:gochecknoglobals
1515 var rootCmd = &cobra.Command{
1616 Use: "gobuster",
1717 SilenceUsage: true,
1818 }
1919
20 // nolint:gochecknoglobals
2021 var mainContext context.Context
2122
2223 // Execute is the main cobra method
4647 // Once before and once after the help output. Not sure if
4748 // this is going to be needed to output other errors that
4849 // aren't automatically outputted.
49 //fmt.Println(err)
50 // fmt.Println(err)
5051 os.Exit(1)
5152 }
5253 }
147148 }
148149 }
149150
151 // nolint:gochecknoinits
150152 func init() {
151153 rootCmd.PersistentFlags().DurationP("delay", "", 0, "Time each thread waits between requests (e.g. 1500ms)")
152154 rootCmd.PersistentFlags().IntP("threads", "t", 10, "Number of concurrent threads")
88 "github.com/spf13/cobra"
99 )
1010
11 // nolint:gochecknoglobals
1112 var cmdS3 *cobra.Command
1213
1314 func runS3(cmd *cobra.Command, args []string) error {
1617 return fmt.Errorf("error on parsing arguments: %w", err)
1718 }
1819
19 plugin, err := gobusters3.NewGobusterS3(mainContext, globalopts, pluginopts)
20 plugin, err := gobusters3.NewGobusterS3(globalopts, pluginopts)
2021 if err != nil {
2122 return fmt.Errorf("error on creating gobusters3: %w", err)
2223 }
4344 plugin.UserAgent = httpOpts.UserAgent
4445 plugin.Proxy = httpOpts.Proxy
4546 plugin.Timeout = httpOpts.Timeout
47 plugin.NoTLSValidation = httpOpts.NoTLSValidation
4648
4749 plugin.MaxFilesToList, err = cmdS3.Flags().GetInt("maxfiles")
4850 if err != nil {
5254 return globalopts, plugin, nil
5355 }
5456
57 // nolint:gochecknoinits
5558 func init() {
5659 cmdS3 = &cobra.Command{
5760 Use: "s3",
66 "github.com/spf13/cobra"
77 )
88
9 // nolint:gochecknoglobals
910 var cmdVersion *cobra.Command
1011
1112 func runVersion(cmd *cobra.Command, args []string) error {
1314 return nil
1415 }
1516
17 // nolint:gochecknoinits
1618 func init() {
1719 cmdVersion = &cobra.Command{
1820 Use: "version",
99 "github.com/spf13/cobra"
1010 )
1111
12 // nolint:gochecknoglobals
1213 var cmdVhost *cobra.Command
1314
1415 func runVhost(cmd *cobra.Command, args []string) error {
1718 return fmt.Errorf("error on parsing arguments: %w", err)
1819 }
1920
20 plugin, err := gobustervhost.NewGobusterVhost(mainContext, globalopts, pluginopts)
21 plugin, err := gobustervhost.NewGobusterVhost(globalopts, pluginopts)
2122 if err != nil {
2223 return fmt.Errorf("error on creating gobustervhost: %w", err)
2324 }
5152 plugin.Headers = httpOpts.Headers
5253 plugin.Method = httpOpts.Method
5354
55 plugin.AppendDomain, err = cmdVhost.Flags().GetBool("append-domain")
56 if err != nil {
57 return nil, nil, fmt.Errorf("invalid value for append-domain: %w", err)
58 }
59
60 plugin.ExcludeLength, err = cmdVhost.Flags().GetIntSlice("exclude-length")
61 if err != nil {
62 return nil, nil, fmt.Errorf("invalid value for excludelength: %w", err)
63 }
64
65 plugin.Domain, err = cmdVhost.Flags().GetString("domain")
66 if err != nil {
67 return nil, nil, fmt.Errorf("invalid value for domain: %w", err)
68 }
69
5470 return globalopts, &plugin, nil
5571 }
5672
73 // nolint:gochecknoinits
5774 func init() {
5875 cmdVhost = &cobra.Command{
5976 Use: "vhost",
60 Short: "Uses VHOST enumeration mode",
77 Short: "Uses VHOST enumeration mode (you most probably want to use the IP adress as the URL parameter",
6178 RunE: runVhost,
6279 }
6380 if err := addCommonHTTPOptions(cmdVhost); err != nil {
6481 log.Fatalf("%v", err)
6582 }
83 cmdVhost.Flags().BoolP("append-domain", "", false, "Append main domain from URL to words from wordlist. Otherwise the fully qualified domains need to be specified in the wordlist.")
84 cmdVhost.Flags().IntSlice("exclude-length", []int{}, "exclude the following content length (completely ignores the status). Supply multiple times to exclude multiple sizes.")
85 cmdVhost.Flags().String("domain", "", "the domain to append when using an IP address as URL. If left empty and you specify a domain based URL the hostname from the URL is extracted")
6686
6787 cmdVhost.PersistentPreRun = func(cmd *cobra.Command, args []string) {
6888 configureGlobalOptions()
22 import (
33 "context"
44 "fmt"
5 "io/ioutil"
5 "io"
66 "log"
77 "os"
88 "testing"
2121 pluginopts.URL = h.URL
2222 pluginopts.Timeout = 10 * time.Second
2323
24 wordlist, err := ioutil.TempFile("", "")
24 wordlist, err := os.CreateTemp("", "")
2525 if err != nil {
2626 b.Fatalf("could not create tempfile: %v", err)
2727 }
4747 }
4848 defer devnull.Close()
4949 log.SetFlags(0)
50 log.SetOutput(ioutil.Discard)
50 log.SetOutput(io.Discard)
5151
5252 // Run the real benchmark
5353 for x := 0; x < b.N; x++ {
5454 os.Stdout = devnull
5555 os.Stderr = devnull
56 plugin, err := gobustervhost.NewGobusterVhost(ctx, &globalopts, &pluginopts)
56 plugin, err := gobustervhost.NewGobusterVhost(&globalopts, &pluginopts)
5757 if err != nil {
5858 b.Fatalf("error on creating gobusterdir: %v", err)
5959 }
9191
9292 // progressWorker outputs the progress every tick. It will stop once cancel() is called
9393 // on the context
94 func progressWorker(c context.Context, g *libgobuster.Gobuster, wg *sync.WaitGroup, output *outputType) {
94 func progressWorker(ctx context.Context, g *libgobuster.Gobuster, wg *sync.WaitGroup, output *outputType) {
9595 defer wg.Done()
9696
9797 tick := time.NewTicker(cliProgressUpdate)
120120 output.Mu.Unlock()
121121 g.RequestsCountMutex.RUnlock()
122122 }
123 case <-c.Done():
123 case <-ctx.Done():
124124 return
125125 }
126126 }
135135 }
136136
137137 // Gobuster is the main entry point for the CLI
138 func Gobuster(prevCtx context.Context, opts *libgobuster.Options, plugin libgobuster.GobusterPlugin) error {
138 func Gobuster(ctx context.Context, opts *libgobuster.Options, plugin libgobuster.GobusterPlugin) error {
139139 // Sanity checks
140140 if opts == nil {
141141 return fmt.Errorf("please provide valid options")
145145 return fmt.Errorf("please provide a valid plugin")
146146 }
147147
148 ctx, cancel := context.WithCancel(prevCtx)
148 ctxCancel, cancel := context.WithCancel(ctx)
149149 defer cancel()
150150
151 gobuster, err := libgobuster.NewGobuster(ctx, opts, plugin)
151 gobuster, err := libgobuster.NewGobuster(opts, plugin)
152152 if err != nil {
153153 return err
154154 }
187187 if !opts.Quiet && !opts.NoProgress {
188188 // if not quiet add a new workgroup entry and start the goroutine
189189 wg.Add(1)
190 go progressWorker(ctx, gobuster, &wg, o)
191 }
192
193 err = gobuster.Start()
190 go progressWorker(ctxCancel, gobuster, &wg, o)
191 }
192
193 err = gobuster.Run(ctxCancel)
194194
195195 // call cancel func so progressWorker will exit (the only goroutine in this
196196 // file using the context) and to free resources
0 gobuster (3.1.0+git20220910.1.9ea1da4-0kali1) UNRELEASED; urgency=low
1
2 * New upstream snapshot.
3
4 -- Kali Janitor <[email protected]> Wed, 28 Sep 2022 16:25:34 -0000
5
06 gobuster (3.1.0-0kali1) kali-dev; urgency=medium
17
28 * Remove useless patches
00 module github.com/OJ/gobuster/v3
11
22 require (
3 github.com/google/uuid v1.1.1
4 github.com/spf13/cobra v1.0.0
5 github.com/spf13/pflag v1.0.5 // indirect
6 golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de
7 golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed // indirect
3 github.com/google/uuid v1.3.0
4 github.com/spf13/cobra v1.5.0
5 golang.org/x/term v0.0.0-20220722155259-a9ba230a4035
86 )
97
10 go 1.15
8 require (
9 github.com/inconshreveable/mousetrap v1.0.1 // indirect
10 github.com/spf13/pflag v1.0.5 // indirect
11 golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2 // indirect
12 )
13
14 go 1.17
+14
-138
go.sum less more
0 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
1 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
2 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
3 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
4 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
5 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
6 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
7 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
8 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
9 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
10 github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
11 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
12 github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
13 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
14 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
15 github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
16 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
17 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
18 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
19 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
20 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
21 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
22 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
23 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
24 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
25 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
26 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
27 github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
28 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
29 github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
30 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
31 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
32 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
33 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
34 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
35 github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
36 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
37 github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
38 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
39 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
40 github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
41 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
42 github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
0 github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
1 github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
2 github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
433 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
44 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
45 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
46 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
47 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
48 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
49 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
50 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
51 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
52 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
53 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
54 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
55 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
56 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
57 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
58 github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
59 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
60 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
61 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
62 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
63 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
64 github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
65 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
66 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
67 github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
68 github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
69 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
70 github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
71 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
72 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
73 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
74 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
75 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
76 github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
77 github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
78 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
79 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
80 github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
81 github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
82 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
83 github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
84 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
4 github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
5 github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
6 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
7 github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
8 github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
859 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
8610 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
87 github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
88 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
89 github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
90 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
91 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
92 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
93 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
94 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
95 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
96 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
97 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
98 go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
99 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
100 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
101 golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig=
102 golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
103 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
104 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
105 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
106 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
107 golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
108 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
109 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
110 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
111 golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
112 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
113 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
114 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
115 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
116 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
117 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
118 golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
119 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
120 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
121 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
122 golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed h1:WBkVNH1zd9jg/dK4HCM4lNANnmd12EHC9z+LmcCG4ns=
123 golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
124 golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
125 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
126 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
127 golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
128 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
129 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
130 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
131 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
132 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
133 google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
134 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
11 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
12 golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2 h1:wM1k/lXfpc5HdkJJyW9GELpd8ERGdnh8sMGL6Gzq3Ho=
13 golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
14 golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc=
15 golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
13516 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
136 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
137 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
138 gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
139 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
140 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
141 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
17 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
3939 }
4040
4141 // NewGobusterDir creates a new initialized GobusterDir
42 func NewGobusterDir(cont context.Context, globalopts *libgobuster.Options, opts *OptionsDir) (*GobusterDir, error) {
42 func NewGobusterDir(globalopts *libgobuster.Options, opts *OptionsDir) (*GobusterDir, error) {
4343 if globalopts == nil {
4444 return nil, fmt.Errorf("please provide valid global options")
4545 }
5454 }
5555
5656 basicOptions := libgobuster.BasicHTTPOptions{
57 Proxy: opts.Proxy,
58 Timeout: opts.Timeout,
59 UserAgent: opts.UserAgent,
57 Proxy: opts.Proxy,
58 Timeout: opts.Timeout,
59 UserAgent: opts.UserAgent,
60 NoTLSValidation: opts.NoTLSValidation,
6061 }
6162
6263 httpOpts := libgobuster.HTTPOptions{
6364 BasicHTTPOptions: basicOptions,
6465 FollowRedirect: opts.FollowRedirect,
65 NoTLSValidation: opts.NoTLSValidation,
6666 Username: opts.Username,
6767 Password: opts.Password,
6868 Headers: opts.Headers,
7070 Method: opts.Method,
7171 }
7272
73 h, err := libgobuster.NewHTTPClient(cont, &httpOpts)
73 h, err := libgobuster.NewHTTPClient(&httpOpts)
7474 if err != nil {
7575 return nil, err
7676 }
105105 }
106106
107107 // PreRun is the pre run implementation of gobusterdir
108 func (d *GobusterDir) PreRun() error {
108 func (d *GobusterDir) PreRun(ctx context.Context) error {
109109 // add trailing slash
110110 if !strings.HasSuffix(d.options.URL, "/") {
111111 d.options.URL = fmt.Sprintf("%s/", d.options.URL)
112112 }
113113
114 _, _, _, _, err := d.http.Request(d.options.URL, libgobuster.RequestOptions{})
114 _, _, _, _, err := d.http.Request(ctx, d.options.URL, libgobuster.RequestOptions{})
115115 if err != nil {
116116 return fmt.Errorf("unable to connect to %s: %w", d.options.URL, err)
117117 }
122122 url = fmt.Sprintf("%s/", url)
123123 }
124124
125 wildcardResp, wildcardLength, _, _, err := d.http.Request(url, libgobuster.RequestOptions{})
125 wildcardResp, wildcardLength, _, _, err := d.http.Request(ctx, url, libgobuster.RequestOptions{})
126126 if err != nil {
127127 return err
128128 }
133133 }
134134
135135 if d.options.StatusCodesBlacklistParsed.Length() > 0 {
136 if !d.options.StatusCodesBlacklistParsed.Contains(*wildcardResp) && !d.options.WildcardForced {
136 if !d.options.StatusCodesBlacklistParsed.Contains(*wildcardResp) {
137137 return &ErrWildcard{url: url, statusCode: *wildcardResp, length: wildcardLength}
138138 }
139139 } else if d.options.StatusCodesParsed.Length() > 0 {
140 if d.options.StatusCodesParsed.Contains(*wildcardResp) && !d.options.WildcardForced {
140 if d.options.StatusCodesParsed.Contains(*wildcardResp) {
141141 return &ErrWildcard{url: url, statusCode: *wildcardResp, length: wildcardLength}
142142 }
143143 } else {
163163 }
164164
165165 // Run is the process implementation of gobusterdir
166 func (d *GobusterDir) Run(word string, resChannel chan<- libgobuster.Result) error {
166 func (d *GobusterDir) Run(ctx context.Context, word string, resChannel chan<- libgobuster.Result) error {
167167 suffix := ""
168168 if d.options.UseSlash {
169169 suffix = "/"
196196 }
197197
198198 for entity, url := range urlsToCheck {
199 statusCode, size, header, _, err := d.http.Request(url, libgobuster.RequestOptions{})
199 statusCode, size, header, _, err := d.http.Request(ctx, url, libgobuster.RequestOptions{})
200200 if err != nil {
201201 return err
202202 }
1313 StatusCodesBlacklist string
1414 StatusCodesBlacklistParsed libgobuster.IntSet
1515 UseSlash bool
16 WildcardForced bool
1716 HideLength bool
1817 Expanded bool
1918 NoStatus bool
1919 Size int64
2020 }
2121
22 // ToString converts the Result to it's textual representation
22 // ResultToString converts the Result to it's textual representation
2323 func (r Result) ResultToString() (string, error) {
2424 buf := &bytes.Buffer{}
2525
8181 }
8282
8383 // PreRun is the pre run implementation of gobusterdns
84 func (d *GobusterDNS) PreRun() error {
84 func (d *GobusterDNS) PreRun(ctx context.Context) error {
8585 // Resolve a subdomain that probably shouldn't exist
8686 guid := uuid.New()
87 wildcardIps, err := d.dnsLookup(fmt.Sprintf("%s.%s", guid, d.options.Domain))
87 wildcardIps, err := d.dnsLookup(ctx, fmt.Sprintf("%s.%s", guid, d.options.Domain))
8888 if err == nil {
8989 d.isWildcard = true
9090 d.wildcardIps.AddRange(wildcardIps)
9595
9696 if !d.globalopts.Quiet {
9797 // Provide a warning if the base domain doesn't resolve (in case of typo)
98 _, err = d.dnsLookup(d.options.Domain)
98 _, err = d.dnsLookup(ctx, d.options.Domain)
9999 if err != nil {
100100 // Not an error, just a warning. Eg. `yp.to` doesn't resolve, but `cr.yp.to` does!
101101 log.Printf("[-] Unable to validate base domain: %s (%v)", d.options.Domain, err)
106106 }
107107
108108 // Run is the process implementation of gobusterdns
109 func (d *GobusterDNS) Run(word string, resChannel chan<- libgobuster.Result) error {
109 func (d *GobusterDNS) Run(ctx context.Context, word string, resChannel chan<- libgobuster.Result) error {
110110 subdomain := fmt.Sprintf("%s.%s", word, d.options.Domain)
111 ips, err := d.dnsLookup(subdomain)
111 ips, err := d.dnsLookup(ctx, subdomain)
112112 if err == nil {
113113 if !d.isWildcard || !d.wildcardIps.ContainsAny(ips) {
114114 result := Result{
120120 if d.options.ShowIPs {
121121 result.IPs = ips
122122 } else if d.options.ShowCNAME {
123 cname, err := d.dnsLookupCname(subdomain)
123 cname, err := d.dnsLookupCname(ctx, subdomain)
124124 if err == nil {
125125 result.CNAME = cname
126126 }
218218 return strings.TrimSpace(buffer.String()), nil
219219 }
220220
221 func (d *GobusterDNS) dnsLookup(domain string) ([]string, error) {
222 ctx, cancel := context.WithTimeout(context.Background(), d.options.Timeout)
221 func (d *GobusterDNS) dnsLookup(ctx context.Context, domain string) ([]string, error) {
222 ctx2, cancel := context.WithTimeout(ctx, d.options.Timeout)
223223 defer cancel()
224 return d.resolver.LookupHost(ctx, domain)
225 }
226
227 func (d *GobusterDNS) dnsLookupCname(domain string) (string, error) {
228 ctx, cancel := context.WithTimeout(context.Background(), d.options.Timeout)
224 return d.resolver.LookupHost(ctx2, domain)
225 }
226
227 func (d *GobusterDNS) dnsLookupCname(ctx context.Context, domain string) (string, error) {
228 ctx2, cancel := context.WithTimeout(ctx, d.options.Timeout)
229229 defer cancel()
230230 time.Sleep(time.Second)
231 return d.resolver.LookupCNAME(ctx, domain)
232 }
231 return d.resolver.LookupCNAME(ctx2, domain)
232 }
1515 CNAME string
1616 }
1717
18 // ToString converts the Result to it's textual representation
18 // ResultToString converts the Result to it's textual representation
1919 func (r Result) ResultToString() (string, error) {
2020 buf := &bytes.Buffer{}
2121
3030 }
3131
3232 // NewGobusterFuzz creates a new initialized GobusterFuzz
33 func NewGobusterFuzz(cont context.Context, globalopts *libgobuster.Options, opts *OptionsFuzz) (*GobusterFuzz, error) {
33 func NewGobusterFuzz(globalopts *libgobuster.Options, opts *OptionsFuzz) (*GobusterFuzz, error) {
3434 if globalopts == nil {
3535 return nil, fmt.Errorf("please provide valid global options")
3636 }
4545 }
4646
4747 basicOptions := libgobuster.BasicHTTPOptions{
48 Proxy: opts.Proxy,
49 Timeout: opts.Timeout,
50 UserAgent: opts.UserAgent,
48 Proxy: opts.Proxy,
49 Timeout: opts.Timeout,
50 UserAgent: opts.UserAgent,
51 NoTLSValidation: opts.NoTLSValidation,
5152 }
5253
5354 httpOpts := libgobuster.HTTPOptions{
5455 BasicHTTPOptions: basicOptions,
5556 FollowRedirect: opts.FollowRedirect,
56 NoTLSValidation: opts.NoTLSValidation,
5757 Username: opts.Username,
5858 Password: opts.Password,
5959 Headers: opts.Headers,
6161 Method: opts.Method,
6262 }
6363
64 h, err := libgobuster.NewHTTPClient(cont, &httpOpts)
64 h, err := libgobuster.NewHTTPClient(&httpOpts)
6565 if err != nil {
6666 return nil, err
6767 }
8080 }
8181
8282 // PreRun is the pre run implementation of gobusterfuzz
83 func (d *GobusterFuzz) PreRun() error {
83 func (d *GobusterFuzz) PreRun(ctx context.Context) error {
8484 return nil
8585 }
8686
8787 // Run is the process implementation of gobusterfuzz
88 func (d *GobusterFuzz) Run(word string, resChannel chan<- libgobuster.Result) error {
88 func (d *GobusterFuzz) Run(ctx context.Context, word string, resChannel chan<- libgobuster.Result) error {
8989 workingURL := strings.ReplaceAll(d.options.URL, "FUZZ", word)
90 statusCode, size, _, _, err := d.http.Request(workingURL, libgobuster.RequestOptions{})
90 statusCode, size, _, _, err := d.http.Request(ctx, workingURL, libgobuster.RequestOptions{})
9191 if err != nil {
9292 return err
9393 }
88 libgobuster.HTTPOptions
99 ExcludedStatusCodes string
1010 ExcludedStatusCodesParsed libgobuster.IntSet
11 WildcardForced bool
1211 ExcludeLength []int
1312 }
1413
1313 Size int64
1414 }
1515
16 // ToString converts the Result to it's textual representation
16 // ResultToString converts the Result to it's textual representation
1717 func (r Result) ResultToString() (string, error) {
1818 buf := &bytes.Buffer{}
1919
2222 }
2323
2424 // NewGobusterS3 creates a new initialized GobusterS3
25 func NewGobusterS3(cont context.Context, globalopts *libgobuster.Options, opts *OptionsS3) (*GobusterS3, error) {
25 func NewGobusterS3(globalopts *libgobuster.Options, opts *OptionsS3) (*GobusterS3, error) {
2626 if globalopts == nil {
2727 return nil, fmt.Errorf("please provide valid global options")
2828 }
3737 }
3838
3939 basicOptions := libgobuster.BasicHTTPOptions{
40 Proxy: opts.Proxy,
41 Timeout: opts.Timeout,
42 UserAgent: opts.UserAgent,
40 Proxy: opts.Proxy,
41 Timeout: opts.Timeout,
42 UserAgent: opts.UserAgent,
43 NoTLSValidation: opts.NoTLSValidation,
4344 }
4445
4546 httpOpts := libgobuster.HTTPOptions{
4849 FollowRedirect: true,
4950 }
5051
51 h, err := libgobuster.NewHTTPClient(cont, &httpOpts)
52 h, err := libgobuster.NewHTTPClient(&httpOpts)
5253 if err != nil {
5354 return nil, err
5455 }
6970 }
7071
7172 // PreRun is the pre run implementation of GobusterS3
72 func (s *GobusterS3) PreRun() error {
73 func (s *GobusterS3) PreRun(ctx context.Context) error {
7374 return nil
7475 }
7576
7677 // Run is the process implementation of GobusterS3
77 func (s *GobusterS3) Run(word string, resChannel chan<- libgobuster.Result) error {
78 func (s *GobusterS3) Run(ctx context.Context, word string, resChannel chan<- libgobuster.Result) error {
7879 // only check for valid bucket names
7980 if !s.isValidBucketName(word) {
8081 return nil
8182 }
8283
83 bucketURL := fmt.Sprintf("http://%s.s3.amazonaws.com/?max-keys=%d", word, s.options.MaxFilesToList)
84 status, _, _, body, err := s.http.Request(bucketURL, libgobuster.RequestOptions{ReturnBody: true})
84 bucketURL := fmt.Sprintf("https://%s.s3.amazonaws.com/?max-keys=%d", word, s.options.MaxFilesToList)
85 status, _, _, body, err := s.http.Request(ctx, bucketURL, libgobuster.RequestOptions{ReturnBody: true})
8586 if err != nil {
8687 return err
8788 }
1111 Status string
1212 }
1313
14 // ToString converts the Result to it's textual representation
14 // ResultToString converts the Result to it's textual representation
1515 func (r Result) ResultToString() (string, error) {
1616 buf := &bytes.Buffer{}
1717
88 "strings"
99 "text/tabwriter"
1010
11 "github.com/OJ/gobuster/v3/helper"
1112 "github.com/OJ/gobuster/v3/libgobuster"
1213 "github.com/google/uuid"
1314 )
2324 }
2425
2526 // NewGobusterVhost creates a new initialized GobusterDir
26 func NewGobusterVhost(cont context.Context, globalopts *libgobuster.Options, opts *OptionsVhost) (*GobusterVhost, error) {
27 func NewGobusterVhost(globalopts *libgobuster.Options, opts *OptionsVhost) (*GobusterVhost, error) {
2728 if globalopts == nil {
2829 return nil, fmt.Errorf("please provide valid global options")
2930 }
3839 }
3940
4041 basicOptions := libgobuster.BasicHTTPOptions{
41 Proxy: opts.Proxy,
42 Timeout: opts.Timeout,
43 UserAgent: opts.UserAgent,
42 Proxy: opts.Proxy,
43 Timeout: opts.Timeout,
44 UserAgent: opts.UserAgent,
45 NoTLSValidation: opts.NoTLSValidation,
4446 }
4547
4648 httpOpts := libgobuster.HTTPOptions{
4749 BasicHTTPOptions: basicOptions,
4850 FollowRedirect: opts.FollowRedirect,
49 NoTLSValidation: opts.NoTLSValidation,
5051 Username: opts.Username,
5152 Password: opts.Password,
5253 Headers: opts.Headers,
5455 Method: opts.Method,
5556 }
5657
57 h, err := libgobuster.NewHTTPClient(cont, &httpOpts)
58 h, err := libgobuster.NewHTTPClient(&httpOpts)
5859 if err != nil {
5960 return nil, err
6061 }
7374 }
7475
7576 // PreRun is the pre run implementation of gobusterdir
76 func (v *GobusterVhost) PreRun() error {
77 func (v *GobusterVhost) PreRun(ctx context.Context) error {
7778 // add trailing slash
7879 if !strings.HasSuffix(v.options.URL, "/") {
7980 v.options.URL = fmt.Sprintf("%s/", v.options.URL)
8384 if err != nil {
8485 return fmt.Errorf("invalid url %s: %w", v.options.URL, err)
8586 }
86 v.domain = urlParsed.Host
87 if v.options.Domain != "" {
88 v.domain = v.options.Domain
89 } else {
90 v.domain = urlParsed.Host
91 }
8792
8893 // request default vhost for baseline1
89 _, _, _, tmp, err := v.http.Request(v.options.URL, libgobuster.RequestOptions{ReturnBody: true})
94 _, _, _, tmp, err := v.http.Request(ctx, v.options.URL, libgobuster.RequestOptions{ReturnBody: true})
9095 if err != nil {
9196 return fmt.Errorf("unable to connect to %s: %w", v.options.URL, err)
9297 }
9499
95100 // request non existent vhost for baseline2
96101 subdomain := fmt.Sprintf("%s.%s", uuid.New(), v.domain)
97 _, _, _, tmp, err = v.http.Request(v.options.URL, libgobuster.RequestOptions{Host: subdomain, ReturnBody: true})
102 _, _, _, tmp, err = v.http.Request(ctx, v.options.URL, libgobuster.RequestOptions{Host: subdomain, ReturnBody: true})
98103 if err != nil {
99104 return fmt.Errorf("unable to connect to %s: %w", v.options.URL, err)
100105 }
103108 }
104109
105110 // Run is the process implementation of gobusterdir
106 func (v *GobusterVhost) Run(word string, resChannel chan<- libgobuster.Result) error {
107 subdomain := fmt.Sprintf("%s.%s", word, v.domain)
108 status, size, header, body, err := v.http.Request(v.options.URL, libgobuster.RequestOptions{Host: subdomain, ReturnBody: true})
111 func (v *GobusterVhost) Run(ctx context.Context, word string, resChannel chan<- libgobuster.Result) error {
112 var subdomain string
113 if v.options.AppendDomain {
114 subdomain = fmt.Sprintf("%s.%s", word, v.domain)
115 } else {
116 // wordlist needs to include full domains
117 subdomain = word
118 }
119 status, size, header, body, err := v.http.Request(ctx, v.options.URL, libgobuster.RequestOptions{Host: subdomain, ReturnBody: true})
109120 if err != nil {
110121 return err
111122 }
113124 // subdomain must not match default vhost and non existent vhost
114125 // or verbose mode is enabled
115126 found := !bytes.Equal(body, v.baseline1) && !bytes.Equal(body, v.baseline2)
116 if found || v.globalopts.Verbose {
127 if (found && !helper.SliceContains(v.options.ExcludeLength, int(size))) || v.globalopts.Verbose {
117128 resultStatus := false
118129 if found {
119130 resultStatus = true
201212 return "", err
202213 }
203214
215 if _, err := fmt.Fprintf(tw, "[+] Append Domain:\t%t\n", v.options.AppendDomain); err != nil {
216 return "", err
217 }
218
219 if len(o.ExcludeLength) > 0 {
220 if _, err := fmt.Fprintf(tw, "[+] Exclude Length:\t%s\n", helper.JoinIntSlice(v.options.ExcludeLength)); err != nil {
221 return "", err
222 }
223 }
224
204225 if err := tw.Flush(); err != nil {
205226 return "", fmt.Errorf("error on tostring: %w", err)
206227 }
66 // OptionsVhost is the struct to hold all options for this plugin
77 type OptionsVhost struct {
88 libgobuster.HTTPOptions
9 AppendDomain bool
10 ExcludeLength []int
11 Domain string
912 }
1414 Header http.Header
1515 }
1616
17 // ToString converts the Result to it's textual representation
17 // ResultToString converts the Result to it's textual representation
1818 func (r Result) ResultToString() (string, error) {
1919 buf := &bytes.Buffer{}
2020
1010 // ParseExtensions parses the extensions provided as a comma separated list
1111 func ParseExtensions(extensions string) (libgobuster.StringSet, error) {
1212 if extensions == "" {
13 return libgobuster.StringSet{}, fmt.Errorf("invalid extension string provided")
13 return libgobuster.StringSet{}, nil
1414 }
1515
1616 ret := libgobuster.NewStringSet()
2525 // ParseCommaSeparatedInt parses the status codes provided as a comma separated list
2626 func ParseCommaSeparatedInt(inputString string) (libgobuster.IntSet, error) {
2727 if inputString == "" {
28 return libgobuster.IntSet{}, fmt.Errorf("invalid string provided")
28 return libgobuster.IntSet{}, nil
2929 }
3030
3131 ret := libgobuster.NewIntSet()
88
99 func TestParseExtensions(t *testing.T) {
1010 t.Parallel()
11
1211 var tt = []struct {
1312 testName string
1413 extensions string
2322 }
2423
2524 for _, x := range tt {
25 x := x // NOTE: https://github.com/golang/go/wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables
2626 t.Run(x.testName, func(t *testing.T) {
27 t.Parallel()
2728 ret, err := ParseExtensions(x.extensions)
2829 if x.expectedError != "" {
2930 if err != nil && err.Error() != x.expectedError {
3839
3940 func TestParseCommaSeparatedInt(t *testing.T) {
4041 t.Parallel()
41
4242 var tt = []struct {
4343 testName string
4444 stringCodes string
5454 }
5555
5656 for _, x := range tt {
57 x := x // NOTE: https://github.com/golang/go/wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables
5758 t.Run(x.testName, func(t *testing.T) {
59 t.Parallel()
5860 ret, err := ParseCommaSeparatedInt(x.stringCodes)
5961 if x.expectedError != "" {
6062 if err != nil && err.Error() != x.expectedError {
8284 }
8385
8486 for _, x := range tt {
87 x := x // NOTE: https://github.com/golang/go/wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables
8588 b.Run(x.testName, func(b2 *testing.B) {
8689 for y := 0; y < b2.N; y++ {
8790 _, _ = ParseExtensions(x.extensions)
106109 }
107110
108111 for _, x := range tt {
112 x := x // NOTE: https://github.com/golang/go/wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables
109113 b.Run(x.testName, func(b2 *testing.B) {
110114 for y := 0; y < b2.N; y++ {
111115 _, _ = ParseCommaSeparatedInt(x.stringCodes)
00 package helper
11
22 import (
3 "math/rand"
4 "time"
3 "crypto/rand"
4 "math/big"
55 )
66
7 // molint:gochecknoglobals
78 var userAgents = [...]string{
89 "Mozilla/5.0 (X11; Linux i686; rv:64.0) Gecko/20100101 Firefox/64.0",
910 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0",
46654666 }
46664667
46674668 // GetRandomUserAgent picks a random user agent from a predefined list
4668 func GetRandomUserAgent() string {
4669 rand.Seed(time.Now().Unix())
4670 return userAgents[rand.Intn(len(userAgents))]
4669 func GetRandomUserAgent() (string, error) {
4670 n, err := rand.Int(rand.Reader, big.NewInt(int64(len(userAgents))))
4671 if err != nil {
4672 return "", err
4673 }
4674 return userAgents[n.Int64()], err
46714675 }
11
22 import (
33 "bytes"
4 "errors"
45 "fmt"
56 "io"
67 "sort"
115116 count += bytes.Count(buf[:c], lineSep)
116117
117118 switch {
118 case err == io.EOF:
119 case errors.Is(err, io.EOF):
119120 return count, nil
120121
121122 case err != nil:
77 )
88
99 func TestNewStringSet(t *testing.T) {
10 t.Parallel()
1011 if NewStringSet().Set == nil {
1112 t.Fatal("newStringSet returned nil Set")
1213 }
1314 }
1415
1516 func TestNewIntSet(t *testing.T) {
17 t.Parallel()
1618 if NewIntSet().Set == nil {
1719 t.Fatal("newIntSet returned nil Set")
1820 }
1921 }
2022
2123 func TestStringSetAdd(t *testing.T) {
24 t.Parallel()
2225 x := NewStringSet()
2326 x.Add("test")
2427 if len(x.Set) != 1 {
2730 }
2831
2932 func TestStringSetAddDouble(t *testing.T) {
33 t.Parallel()
3034 x := NewStringSet()
3135 x.Add("test")
3236 x.Add("test")
3640 }
3741
3842 func TestStringSetAddRange(t *testing.T) {
43 t.Parallel()
3944 x := NewStringSet()
4045 x.AddRange([]string{"string1", "string2"})
4146 if len(x.Set) != 2 {
4449 }
4550
4651 func TestStringSetAddRangeDouble(t *testing.T) {
52 t.Parallel()
4753 x := NewStringSet()
4854 x.AddRange([]string{"string1", "string2", "string1", "string2"})
4955 if len(x.Set) != 2 {
5258 }
5359
5460 func TestStringSetContains(t *testing.T) {
61 t.Parallel()
5562 x := NewStringSet()
5663 v := []string{"string1", "string2", "1234", "5678"}
5764 x.AddRange(v)
6370 }
6471
6572 func TestStringSetContainsAny(t *testing.T) {
73 t.Parallel()
6674 x := NewStringSet()
6775 v := []string{"string1", "string2", "1234", "5678"}
6876 x.AddRange(v)
7785 }
7886
7987 func TestStringSetStringify(t *testing.T) {
88 t.Parallel()
8089 x := NewStringSet()
8190 v := []string{"string1", "string2", "1234", "5678"}
8291 x.AddRange(v)
9099 }
91100
92101 func TestIntSetAdd(t *testing.T) {
102 t.Parallel()
93103 x := NewIntSet()
94104 x.Add(1)
95105 if len(x.Set) != 1 {
98108 }
99109
100110 func TestIntSetAddDouble(t *testing.T) {
111 t.Parallel()
101112 x := NewIntSet()
102113 x.Add(1)
103114 x.Add(1)
107118 }
108119
109120 func TestIntSetContains(t *testing.T) {
121 t.Parallel()
110122 x := NewIntSet()
111123 v := []int{1, 2, 3, 4}
112124 for _, y := range v {
120132 }
121133
122134 func TestIntSetStringify(t *testing.T) {
135 t.Parallel()
123136 x := NewIntSet()
124137 v := []int{1, 3, 2, 4}
125138 expected := "1,2,3,4"
134147 }
135148
136149 func TestLineCounter(t *testing.T) {
150 t.Parallel()
137151 var tt = []struct {
138152 testName string
139153 s string
146160 {"Empty", "", 1},
147161 }
148162 for _, x := range tt {
163 x := x // NOTE: https://github.com/golang/go/wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables
149164 t.Run(x.testName, func(t *testing.T) {
165 t.Parallel()
150166 r := strings.NewReader(x.s)
151167 l, err := lineCounter(r)
152168 if err != nil {
160176 }
161177
162178 func TestLineCounterError(t *testing.T) {
179 t.Parallel()
163180 r := iotest.TimeoutReader(strings.NewReader("test"))
164181 _, err := lineCounter(r)
165182 if !errors.Is(err, iotest.ErrTimeout) {
55 "errors"
66 "fmt"
77 "io"
8 "io/ioutil"
98 "net/http"
109 "net/url"
1110 "strings"
2019 // HTTPClient represents a http object
2120 type HTTPClient struct {
2221 client *http.Client
23 context context.Context
2422 userAgent string
2523 defaultUserAgent string
2624 username string
2826 headers []HTTPHeader
2927 cookies string
3028 method string
29 host string
3130 }
3231
3332 // RequestOptions is used to pass options to a single individual request
3837 }
3938
4039 // NewHTTPClient returns a new HTTPClient
41 func NewHTTPClient(c context.Context, opt *HTTPOptions) (*HTTPClient, error) {
40 func NewHTTPClient(opt *HTTPOptions) (*HTTPClient, error) {
4241 var proxyURLFunc func(*http.Request) (*url.URL, error)
4342 var client HTTPClient
4443 proxyURLFunc = http.ProxyFromEnvironment
7574 InsecureSkipVerify: opt.NoTLSValidation,
7675 },
7776 }}
78 client.context = c
7977 client.username = opt.Username
8078 client.password = opt.Password
8179 client.userAgent = opt.UserAgent
8684 if client.method == "" {
8785 client.method = http.MethodGet
8886 }
87 // Host header needs to be set separately
88 for _, h := range opt.Headers {
89 if h.Name == "Host" {
90 client.host = h.Value
91 break
92 }
93 }
8994 return &client, nil
9095 }
9196
9297 // Request makes an http request and returns the status, the content length, the headers, the body and an error
9398 // if you want the body returned set the corresponding property inside RequestOptions
94 func (client *HTTPClient) Request(fullURL string, opts RequestOptions) (*int, int64, http.Header, []byte, error) {
95 resp, err := client.makeRequest(fullURL, opts.Host, opts.Body)
99 func (client *HTTPClient) Request(ctx context.Context, fullURL string, opts RequestOptions) (*int, int64, http.Header, []byte, error) {
100 resp, err := client.makeRequest(ctx, fullURL, opts.Host, opts.Body)
96101 if err != nil {
97102 // ignore context canceled errors
98 if errors.Is(client.context.Err(), context.Canceled) {
103 if errors.Is(ctx.Err(), context.Canceled) {
99104 return nil, 0, nil, nil, nil
100105 }
101106 return nil, 0, nil, nil, err
105110 var body []byte
106111 var length int64
107112 if opts.ReturnBody {
108 body, err = ioutil.ReadAll(resp.Body)
113 body, err = io.ReadAll(resp.Body)
109114 if err != nil {
110115 return nil, 0, nil, nil, fmt.Errorf("could not read body %w", err)
111116 }
113118 } else {
114119 // DO NOT REMOVE!
115120 // absolutely needed so golang will reuse connections!
116 length, err = io.Copy(ioutil.Discard, resp.Body)
121 length, err = io.Copy(io.Discard, resp.Body)
117122 if err != nil {
118123 return nil, 0, nil, nil, err
119124 }
122127 return &resp.StatusCode, length, resp.Header, body, nil
123128 }
124129
125 func (client *HTTPClient) makeRequest(fullURL, host string, data io.Reader) (*http.Response, error) {
130 func (client *HTTPClient) makeRequest(ctx context.Context, fullURL, host string, data io.Reader) (*http.Response, error) {
126131 req, err := http.NewRequest(client.method, fullURL, data)
127132 if err != nil {
128133 return nil, err
129134 }
130135
131136 // add the context so we can easily cancel out
132 req = req.WithContext(client.context)
137 req = req.WithContext(ctx)
133138
134139 if client.cookies != "" {
135140 req.Header.Set("Cookie", client.cookies)
136141 }
137142
143 // Use host for VHOST mode on a per request basis, otherwise the one provided from headers
138144 if host != "" {
139145 req.Host = host
146 } else if client.host != "" {
147 req.Host = client.host
140148 }
141149
142150 if client.userAgent != "" {
156164
157165 resp, err := client.client.Do(req)
158166 if err != nil {
159 if ue, ok := err.(*url.Error); ok {
167 var ue *url.Error
168 if errors.As(err, &ue) {
160169 if strings.HasPrefix(ue.Err.Error(), "x509") {
161170 return nil, fmt.Errorf("invalid certificate: %w", ue.Err)
162171 }
22 import (
33 "bytes"
44 "context"
5 "crypto/rand"
56 "fmt"
6 "math/rand"
7 "math/big"
78 "net/http"
89 "net/http/httptest"
910 "testing"
2526 return ts
2627 }
2728
28 func randomString(length int) string {
29 func randomString(length int) (string, error) {
2930 var letter = []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
3031 letterLen := len(letter)
3132
3233 b := make([]byte, length)
3334 for i := range b {
34 b[i] = letter[rand.Intn(letterLen)]
35 n, err := rand.Int(rand.Reader, big.NewInt(int64(letterLen)))
36 if err != nil {
37 return "", err
38 }
39 b[i] = letter[n.Int64()]
3540 }
36 return string(b)
41 return string(b), nil
3742 }
3843
3944 func TestRequest(t *testing.T) {
40 ret := randomString(100)
45 t.Parallel()
46 ret, err := randomString(100)
47 if err != nil {
48 t.Fatal(err)
49 }
4150 h := httpServerT(t, ret)
4251 defer h.Close()
4352 var o HTTPOptions
44 c, err := NewHTTPClient(context.Background(), &o)
53 c, err := NewHTTPClient(&o)
4554 if err != nil {
4655 t.Fatalf("Got Error: %v", err)
4756 }
48 status, length, _, body, err := c.Request(h.URL, RequestOptions{ReturnBody: true})
57 status, length, _, body, err := c.Request(context.Background(), h.URL, RequestOptions{ReturnBody: true})
4958 if err != nil {
5059 t.Fatalf("Got Error: %v", err)
5160 }
6170 }
6271
6372 func BenchmarkRequestWithoutBody(b *testing.B) {
64 h := httpServerB(b, randomString(10000))
73 r, err := randomString(10000)
74 if err != nil {
75 b.Fatal(err)
76 }
77 h := httpServerB(b, r)
6578 defer h.Close()
6679 var o HTTPOptions
67 c, err := NewHTTPClient(context.Background(), &o)
80 c, err := NewHTTPClient(&o)
6881 if err != nil {
6982 b.Fatalf("Got Error: %v", err)
7083 }
7184 for x := 0; x < b.N; x++ {
72 _, _, _, _, err := c.Request(h.URL, RequestOptions{ReturnBody: false})
85 _, _, _, _, err := c.Request(context.Background(), h.URL, RequestOptions{ReturnBody: false})
7386 if err != nil {
7487 b.Fatalf("Got Error: %v", err)
7588 }
7790 }
7891
7992 func BenchmarkRequestWitBody(b *testing.B) {
80 h := httpServerB(b, randomString(10000))
93 r, err := randomString(10000)
94 if err != nil {
95 b.Fatal(err)
96 }
97 h := httpServerB(b, r)
8198 defer h.Close()
8299 var o HTTPOptions
83 c, err := NewHTTPClient(context.Background(), &o)
100 c, err := NewHTTPClient(&o)
84101 if err != nil {
85102 b.Fatalf("Got Error: %v", err)
86103 }
87104 for x := 0; x < b.N; x++ {
88 _, _, _, _, err := c.Request(h.URL, RequestOptions{ReturnBody: true})
105 _, _, _, _, err := c.Request(context.Background(), h.URL, RequestOptions{ReturnBody: true})
89106 if err != nil {
90107 b.Fatalf("Got Error: %v", err)
91108 }
93110 }
94111
95112 func BenchmarkNewHTTPClient(b *testing.B) {
96 h := httpServerB(b, randomString(500))
113 r, err := randomString(500)
114 if err != nil {
115 b.Fatal(err)
116 }
117 h := httpServerB(b, r)
97118 defer h.Close()
98119 var o HTTPOptions
99120 for x := 0; x < b.N; x++ {
100 _, err := NewHTTPClient(context.Background(), &o)
121 _, err := NewHTTPClient(&o)
101122 if err != nil {
102123 b.Fatalf("Got Error: %v", err)
103124 }
00 package libgobuster
1
2 import "context"
13
24 // GobusterPlugin is an interface which plugins must implement
35 type GobusterPlugin interface {
46 Name() string
57 RequestsPerRun() int
6 PreRun() error
7 Run(string, chan<- Result) error
8 PreRun(context.Context) error
9 Run(context.Context, string, chan<- Result) error
810 GetConfigString() (string, error)
911 }
1012
13 // Result is an interface for the Result object
1114 type Result interface {
1215 ResultToString() (string, error)
1316 }
2525 // Gobuster is the main object when creating a new run
2626 type Gobuster struct {
2727 Opts *Options
28 context context.Context
2928 RequestsExpected int
3029 RequestsIssued int
3130 RequestsCountMutex *sync.RWMutex
3736 }
3837
3938 // NewGobuster returns a new Gobuster object
40 func NewGobuster(c context.Context, opts *Options, plugin GobusterPlugin) (*Gobuster, error) {
39 func NewGobuster(opts *Options, plugin GobusterPlugin) (*Gobuster, error) {
4140 var g Gobuster
4241 g.Opts = opts
4342 g.plugin = plugin
4443 g.RequestsCountMutex = new(sync.RWMutex)
45 g.context = c
4644 g.resultChan = make(chan Result)
4745 g.errorChan = make(chan error)
4846 g.LogInfo = log.New(os.Stdout, "", log.LstdFlags)
6765 g.RequestsCountMutex.Unlock()
6866 }
6967
70 func (g *Gobuster) worker(wordChan <-chan string, wg *sync.WaitGroup) {
68 func (g *Gobuster) worker(ctx context.Context, wordChan <-chan string, wg *sync.WaitGroup) {
7169 defer wg.Done()
7270 for {
7371 select {
74 case <-g.context.Done():
72 case <-ctx.Done():
7573 return
7674 case word, ok := <-wordChan:
7775 // worker finished
8785 }
8886
8987 // Mode-specific processing
90 err := g.plugin.Run(wordCleaned, g.resultChan)
88 err := g.plugin.Run(ctx, wordCleaned, g.resultChan)
9189 if err != nil {
9290 // do not exit and continue
9391 g.errorChan <- err
9593 }
9694
9795 select {
98 case <-g.context.Done():
96 case <-ctx.Done():
9997 case <-time.After(g.Opts.Delay):
10098 }
10199 }
136134 return bufio.NewScanner(wordlist), nil
137135 }
138136
139 // Start the busting of the website with the given
137 // Run the busting of the website with the given
140138 // set of settings from the command line.
141 func (g *Gobuster) Start() error {
139 func (g *Gobuster) Run(ctx context.Context) error {
142140 defer close(g.resultChan)
143141 defer close(g.errorChan)
144142
145 if err := g.plugin.PreRun(); err != nil {
143 if err := g.plugin.PreRun(ctx); err != nil {
146144 return err
147145 }
148146
154152 // Create goroutines for each of the number of threads
155153 // specified.
156154 for i := 0; i < g.Opts.Threads; i++ {
157 go g.worker(wordChan, &workerGroup)
155 go g.worker(ctx, wordChan, &workerGroup)
158156 }
159157
160158 scanner, err := g.getWordlist()
165163 Scan:
166164 for scanner.Scan() {
167165 select {
168 case <-g.context.Done():
166 case <-ctx.Done():
169167 break Scan
170168 default:
171169 word := scanner.Text()
176174 for _, w := range perms {
177175 select {
178176 // need to check here too otherwise wordChan will block
179 case <-g.context.Done():
177 case <-ctx.Done():
180178 break Scan
181179 case wordChan <- w:
182180 }
1212 NoProgress bool
1313 NoError bool
1414 Quiet bool
15 WildcardForced bool
1615 Verbose bool
1716 Delay time.Duration
1817 }
55
66 // BasicHTTPOptions defines only core http options
77 type BasicHTTPOptions struct {
8 UserAgent string
9 Proxy string
10 Timeout time.Duration
8 UserAgent string
9 Proxy string
10 NoTLSValidation bool
11 Timeout time.Duration
1112 }
1213
1314 // HTTPOptions is the struct to pass in all http options to Gobuster
1415 type HTTPOptions struct {
1516 BasicHTTPOptions
16 Password string
17 URL string
18 Username string
19 Cookies string
20 Headers []HTTPHeader
21 FollowRedirect bool
22 NoTLSValidation bool
23 Method string
17 Password string
18 URL string
19 Username string
20 Cookies string
21 Headers []HTTPHeader
22 FollowRedirect bool
23 Method string
2424 }