diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index eababe2..1281c3a 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -11,9 +11,9 @@ jobs: name: Test Builds runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - uses: actions/setup-go@v2 + - uses: actions/setup-go@v3 with: go-version: 1.17 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 545cdea..9f533f8 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -23,16 +23,16 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 \ No newline at end of file + uses: github/codeql-action/analyze@v2 \ No newline at end of file diff --git a/.github/workflows/dockerhub-push.yml b/.github/workflows/dockerhub-push.yml index 33fd6c4..2f9d972 100644 --- a/.github/workflows/dockerhub-push.yml +++ b/.github/workflows/dockerhub-push.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Get Github tag id: meta @@ -20,19 +20,19 @@ jobs: echo "::set-output name=tag::$(curl --silent "https://api.github.com/repos/projectdiscovery/chaos-client/releases/latest" | jq -r .tag_name)" - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_TOKEN }} - name: Build and push - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v3 with: context: . platforms: linux/amd64,linux/arm64,linux/arm diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml index b777b2d..5baf150 100644 --- a/.github/workflows/lint-test.yml +++ b/.github/workflows/lint-test.yml @@ -10,10 +10,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Run golangci-lint - uses: golangci/golangci-lint-action@v2 + uses: golangci/golangci-lint-action@v3.2.0 with: version: latest args: --timeout 5m diff --git a/.github/workflows/release-binary.yml b/.github/workflows/release-binary.yml index a86411a..2975180 100644 --- a/.github/workflows/release-binary.yml +++ b/.github/workflows/release-binary.yml @@ -10,13 +10,13 @@ jobs: if: ${{ startsWith(github.ref, 'refs/tags/v') }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - uses: actions/setup-go@v2 + - uses: actions/setup-go@v3 with: - go-version: 1.17 + go-version: 1.18 - - uses: goreleaser/goreleaser-action@v2 + - uses: goreleaser/goreleaser-action@v3 with: args: "release --rm-dist" version: latest diff --git a/Dockerfile b/Dockerfile index 60fcebb..c269e6e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ -FROM golang:1.17.6-alpine as build-env -RUN GO111MODULE=on go get -v github.com/projectdiscovery/chaos-client/cmd/chaos +FROM golang:1.19.0-alpine as build-env +RUN go install -v github.com/projectdiscovery/chaos-client/cmd/chaos@latest FROM alpine:latest RUN apk add --no-cache bind-tools ca-certificates diff --git a/README.md b/README.md index 34dae2f..e25cf80 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +

+Chaos Client +

+

Go client to communicate with Chaos dataset API.

+

@@ -8,10 +13,6 @@

-# Chaos Client - -Go client to communicate with Chaos dataset API. - ## Installation ```bash @@ -26,25 +27,16 @@ chaos -h This will display help for the tool. Here are all the switches it supports. -| Flag | Description | Example | -| ------------------------ | ---------------------------------------- | -------------------------------------------------------- | -| -d | Domain to find subdomains for | chaos -d uber.com | -| -count | Show statistics for the specified domain | chaos -d uber.com -count | -| -o | File to write output to (optional) | chaos -d uber.com -o uber.txt | -| -json | Print output as json | chaos -d uber.com -json | -| -key | Chaos key for API | chaos -key API_KEY | -| -dL | File with list of domains (optional) | chaos -dL domains.txt | -| -dns-record-type | Filter by dns record type | chaos -bbq -d uber.com -dns-record-type cname | -| -dns-status-code | Filter by dns status code | chaos -bbq -d uber.com -dns-status-code noerror | -| -filter-wildcard | Filter DNS wildcards | chaos -bbq -d uber.com -filter-wildcard | -| -http-url | Print URL of the subdomains | chaos -bbq -d uber.com -http-url | -| -http-title | Print title of the URL | chaos -bbq -d uber.com -http-title | -| -http-status-code | Print http status code | chaos -bbq -d uber.com -http-status-code | -| -http-status-code-filter | Filter http status code | chaos -bbq -d uber.com -http-status-code-filter 200 | -| -resp | Print DNS record with response | chaos -bbq -d uber.com -resp | -| -resp-only | Print the response of DNS record | chaos -bbq -d uber.com -dns-record-type cname -resp-only | -| -silent | Make the output silent | chaos -d uber.com -silent | -| -version | Print current version of chaos client | chaos -version | +| Flag | Description | Example | +|----------------------------|------------------------------------------|------------------------------------------------------------| +| `-d` | Domain to find subdomains for | `chaos -d uber.com` | +| `-count` | Show statistics for the specified domain | `chaos -d uber.com -count` | +| `-o` | File to write output to (optional) | `chaos -d uber.com -o uber.txt` | +| `-json` | Print output as json | `chaos -d uber.com -json` | +| `-key` | Chaos key for API | `chaos -key API_KEY` | +| `-dL` | File with list of domains (optional) | `chaos -dL domains.txt` | +| `-silent` | Make the output silent | `chaos -d uber.com -silent` | +| `-version` | Print current version of chaos client | `chaos -version` | You can also set the API key as environment variable in your bash profile. @@ -86,9 +78,8 @@ kiosk-home-staging.uber.com 💡 Notes ----- -- **The API is rate-limited to 1 request at a time per token.** +- **The API is rate-limited to 60 request / min / ip** - Chaos API **only** supports domain name to query. -- Chaos recon data can be retrieved using `bbq` flag. 👨‍💻 Community ----- @@ -96,10 +87,4 @@ kiosk-home-staging.uber.com You are welcomed to join our [Discord Community](https://discord.gg/projectdiscovery). You can also follow us on [Twitter](https://twitter.com/pdchaos) to keep up with everything related to chaos project. -📌 Reference ------ - -- [Introducing Chaos Recon data API](https://blog.projectdiscovery.io/introducing-chaos-bug-bounty-recon-data-api) - - Thanks again for your contribution and keeping the community vibrant. :heart: diff --git a/go.mod b/go.mod index 6f01b5f..97c1ec7 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/projectdiscovery/chaos-client -go 1.14 +go 1.17 require ( github.com/json-iterator/go v1.1.12 @@ -9,3 +9,11 @@ require ( github.com/projectdiscovery/httputil v0.0.0-20210906072657-f3a099cb20bc github.com/projectdiscovery/retryablehttp-go v1.0.2 ) + +require ( + github.com/logrusorgru/aurora v2.0.3+incompatible // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + golang.org/x/net v0.0.0-20210521195947-fe42d452be8f // indirect + golang.org/x/text v0.3.6 // indirect +) diff --git a/go.sum b/go.sum index 492a018..b85951b 100644 --- a/go.sum +++ b/go.sum @@ -6,11 +6,9 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= @@ -45,7 +43,6 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= diff --git a/internal/runner/banner.go b/internal/runner/banner.go index 08eabb8..d927b2d 100644 --- a/internal/runner/banner.go +++ b/internal/runner/banner.go @@ -7,11 +7,11 @@ const banner = ` _____/ /_ ____ _____ _____ / ___/ __ \/ __ / __ \/ ___/ / /__/ / / / /_/ / /_/ (__ ) -\___/_/ /_/\__,_/\____/____/ v0.2.0 +\___/_/ /_/\__,_/\____/____/ v0.3.0 ` // Version is the current version of chaos -const Version = `0.2.0` +const Version = `0.3.0` // showBanner is used to show the banner to the user func showBanner() { diff --git a/internal/runner/options.go b/internal/runner/options.go index 195b768..1b25a90 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -46,17 +46,6 @@ func ParseOptions() *Options { flag.StringVar(&opts.Output, "o", "", "File to write output to (optional)") flag.StringVar(&opts.DomainsFile, "dL", "", "File containing subdomains to query (optional)") flag.BoolVar(&opts.JSONOutput, "json", false, "Print output as json") - flag.BoolVar(&opts.BBQ, "bbq", false, "Public bugbounty recon data") - flag.StringVar(&opts.DNSStatusCode, "dns-status-code", "", "Filter by dns status code") - flag.StringVar(&opts.DNSRecordType, "dns-record-type", "", "Filter by dns record type") - flag.BoolVar(&opts.FilterWildcard, "filter-wildcard", false, "Filter wildcards") - flag.BoolVar(&opts.Response, "resp", false, "Print record response") - flag.BoolVar(&opts.ResponseOnly, "resp-only", false, "Print record response only") - flag.BoolVar(&opts.HTTPUrl, "http-url", false, "Print http url if the fqdn exposes a web server") - flag.BoolVar(&opts.HTTPTitle, "http-title", false, "Print http homepage title if the fqdn exposes a web server") - flag.BoolVar(&opts.HTTPStatusCode, "http-status-code", false, "Print http status code if the fqdn exposes a web server") - flag.IntVar(&opts.HTTPStatusCodeFilter, "http-status-code-filter", -1, "Print http status code if the value equals the specified one") - flag.BoolVar(&opts.HTTPContentLength, "http-content-length", false, "Print http content length if the fqdn exposes a web server") flag.BoolVar(&opts.Version, "version", false, "Show version of chaos") flag.Parse() diff --git a/pkg/chaos/chaos.go b/pkg/chaos/chaos.go index 7d7e80d..6bcf0fd 100644 --- a/pkg/chaos/chaos.go +++ b/pkg/chaos/chaos.go @@ -50,12 +50,12 @@ func (c *Client) GetStatistics(req *GetStatisticsRequest) (*GetStatisticsRespons return nil, errors.Wrap(err, "could not make request.") } - if resp.StatusCode != 200 { + if resp.StatusCode != http.StatusOK { body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, errors.Wrap(err, "could not read response.") } - return nil, fmt.Errorf("invalid status code received: %d - %s", resp.StatusCode, string(body)) + return nil, InvalidStatusCodeError{StatusCode: resp.StatusCode, Message: body} } defer pdhttputil.DrainResponseBody(resp) @@ -101,14 +101,14 @@ func (c *Client) GetSubdomains(req *SubdomainsRequest) chan *Result { return } - if resp.StatusCode != 200 { + if resp.StatusCode != http.StatusOK { body, err := ioutil.ReadAll(resp.Body) if err != nil { results <- &Result{Error: errors.Wrap(err, "could not read response.")} return } pdhttputil.DrainResponseBody(resp) - results <- &Result{Error: fmt.Errorf("invalid status code received: %d - %s", resp.StatusCode, string(body))} + results <- &Result{Error: InvalidStatusCodeError{StatusCode: resp.StatusCode, Message: body}} return } @@ -194,14 +194,14 @@ func (c *Client) GetBBQSubdomains(req *SubdomainsRequest) chan *BBQResult { return } - if resp.StatusCode != 200 { + if resp.StatusCode != http.StatusOK { body, err := ioutil.ReadAll(resp.Body) if err != nil { results <- &BBQResult{Error: errors.Wrap(err, "could not read response.")} return } pdhttputil.DrainResponseBody(resp) - results <- &BBQResult{Error: fmt.Errorf("invalid status code received: %d - %s", resp.StatusCode, string(body))} + results <- &BBQResult{Error: InvalidStatusCodeError{StatusCode: resp.StatusCode, Message: body}} return } @@ -246,13 +246,22 @@ func (c *Client) PutSubdomains(req *PutSubdomainsRequest) (*PutSubdomainsRespons } defer resp.Body.Close() - if resp.StatusCode != 200 { + if resp.StatusCode != http.StatusOK { body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, errors.Wrap(err, "could not read response.") } - return nil, fmt.Errorf("invalid status code received: %d - %s", resp.StatusCode, string(body)) + return nil, InvalidStatusCodeError{StatusCode: resp.StatusCode, Message: body} } _, _ = io.Copy(ioutil.Discard, resp.Body) return &PutSubdomainsResponse{}, nil } + +type InvalidStatusCodeError struct { + StatusCode int + Message []byte +} + +func (e InvalidStatusCodeError) Error() string { + return fmt.Sprintf("invalid status code received: %d - %s", e.StatusCode, e.Message) +}