From 6e608fc30fc56b7b03ff14cd6112c78f2459436d Mon Sep 17 00:00:00 2001 From: Dwi Siswanto Date: Wed, 23 Dec 2020 05:50:48 +0700 Subject: [PATCH] init 1 --- .github/workflows/gosum.yaml | 39 +++++++ .github/workflows/pr.yaml | 36 ++++++ .github/workflows/release.yaml | 27 +++++ .github/workflows/stale.yaml | 24 ++++ .gitignore | 2 + CODEOWNERS | 1 + LICENSE | 205 +++++++++++++++++++++++++++++++++ README.md | 55 +++++++++ go.mod | 14 +++ go.sum | 34 ++++++ internal/runner/constant.go | 45 ++++++++ internal/runner/parser.go | 58 ++++++++++ internal/runner/runner.go | 71 ++++++++++++ internal/runner/validator.go | 51 ++++++++ main.go | 8 ++ pkg/ssb/ssb.go | 31 +++++ 16 files changed, 701 insertions(+) create mode 100644 .github/workflows/gosum.yaml create mode 100644 .github/workflows/pr.yaml create mode 100644 .github/workflows/release.yaml create mode 100644 .github/workflows/stale.yaml create mode 100644 .gitignore create mode 100644 CODEOWNERS create mode 100644 LICENSE create mode 100644 README.md create mode 100644 go.mod create mode 100644 go.sum create mode 100644 internal/runner/constant.go create mode 100644 internal/runner/parser.go create mode 100644 internal/runner/runner.go create mode 100644 internal/runner/validator.go create mode 100644 main.go create mode 100644 pkg/ssb/ssb.go diff --git a/.github/workflows/gosum.yaml b/.github/workflows/gosum.yaml new file mode 100644 index 0000000..09a7170 --- /dev/null +++ b/.github/workflows/gosum.yaml @@ -0,0 +1,39 @@ +name: "Gosum" + +on: + push: + branches: + - "main" + paths: + - ".github/workflows/gosum.yaml" + - "go.mod" + - "go.sum" + +jobs: + gosum: + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v2 + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.14 + + - name: Tidy + run: | + rm -f go.sum + go mod tidy + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v3.5.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: ":hammer: Tidy up the Go modules" + title: "Tidy up the Go module" + body: | + Current `go.mod` and `go.sum` don't match the source code. + branch: go-mod-tidy + branch-suffix: short-commit-hash + labels: "bug" \ No newline at end of file diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml new file mode 100644 index 0000000..fc47abb --- /dev/null +++ b/.github/workflows/pr.yaml @@ -0,0 +1,36 @@ +name: Pull Request +on: + push: + paths-ignore: + - README.md + - .gitignore + tags: + - v* + branches: + - main + - development + pull_request: + +jobs: + checks: + name: Pull Request Checks + runs-on: ubuntu-latest + steps: + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.14 + + - name: Check out code + uses: actions/checkout@v2 + + - name: GolangCI-Lint + uses: golangci/golangci-lint-action@v2.3.0 + with: + version: v1.29 + + - name: Run tests + run: go test . + + - name: Compile the project + run: go build \ No newline at end of file diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..a2c027d --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,27 @@ +name: Release +on: + create: + tags: + - v* + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: "Check out code" + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: "Set up Go" + uses: actions/setup-go@v2 + with: + go-version: 1.14 + + - name: "Create release on GitHub" + uses: goreleaser/goreleaser-action@v2 + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + with: + args: "release --rm-dist" + version: latest diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml new file mode 100644 index 0000000..f432503 --- /dev/null +++ b/.github/workflows/stale.yaml @@ -0,0 +1,24 @@ +name: "Auto Close Stale PR & Issues" +on: + schedule: + - cron: "0 0 * * *" + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - name: Run Stale action + uses: actions/stale@v3 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + + stale-issue-message: "This issue won't be fixed & marked as invalid. Closed!" + stale-issue-label: "wontfix, invalid" + exempt-issue-labels: "bug" + + stale-pr-message: "This PR was abandoned. Closing now." + stale-pr-label: "abandoned" + exempt-pr-labels: "enhancement" + + days-before-stale: 30 + days-before-close: 0 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..31449fe --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.txt +bin/* \ No newline at end of file diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..bddc66a --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @dwisiswant0 \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..224deec --- /dev/null +++ b/LICENSE @@ -0,0 +1,205 @@ +Copyright 2020 Dwi Siswanto. All rights reserved. +License: Apache2.0 + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Dwi Siswanto + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..19a9171 --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ +# SSB + +[![Kitabisa SecLab](https://img.shields.io/badge/kitabisa-security%20project-blue)](#) +[![License](https://img.shields.io/badge/License-Apache%202.0-yellowgreen)](https://github.com/kitabisa/ssb/blob/master/LICENSE) +[![contributions](https://img.shields.io/badge/contributions-welcome-magenta.svg?style=flat)](https://github.com/kitabisa/ssb/issues) +[![made with Go](https://img.shields.io/badge/made%20with-Go-brightgreen)](http://golang.org) +[![Version](https://img.shields.io/badge/version-0.0.1-blueviolet)](https://github.com/kitabisa/ssb/releases) + +**S**_ecure_ **S**_hell_ **B**_ruteforcer_ — A faster & simpler way to bruteforce SSH server. + +Kitabisa SSB Demo + +--- + +## Installation + +### from Binary + +Download a pre-built binary from [releases page](https://github.com/kitabisa/ssb/releases), unpack and run! + +### from Source + +Need [go1.14+](https://golang.org/doc/install#download) compiler installed and configured, then: + +```bash +▶ GO111MODULE=on go get ktbs.dev/ssb +``` + +## Usage + +```bash +▶ ssb [-p port] [-w wordlist.txt] [-t timeout] + [-c concurrent] [-o output] [user@]hostname +``` + +### Options: + +```txt + -p port + Port to connect to on the remote host (default 22). + -w wordlist + Path to wordlist file. + -t timeout + Connection timeout (default 30s). + -c concurrent + Concurrency/threads level (default 100). + -o output + Save valid password to file. + -v + Verbose mode. +``` + +## License + +This program is free software: you can redistribute it and/or modify it under the terms of the [Apache license](https://github.com/kitabisa/ssb/blob/master/LICENSE). Kitabisa SSB and any contributions are Copyright © by Dwi Siswanto 2020. \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..5eb51c2 --- /dev/null +++ b/go.mod @@ -0,0 +1,14 @@ +module ktbs.dev/ssb + +go 1.14 + +require ( + github.com/briandowns/spinner v1.12.0 + github.com/gernest/wow v0.1.0 + github.com/logrusorgru/aurora v2.0.3+incompatible + github.com/projectdiscovery/gologger v1.0.1 + github.com/remeh/sizedwaitgroup v1.0.0 + github.com/tj/go-spin v1.1.0 + github.com/zenthangplus/goccm v0.0.0-20200608171100-39e9e08b694a + golang.org/x/crypto v0.0.0-20201217014255-9d1352758620 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ca8efa7 --- /dev/null +++ b/go.sum @@ -0,0 +1,34 @@ +github.com/briandowns/spinner v1.12.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/gernest/wow v0.1.0 h1:g9xdwCwP0+xgVYlA2sopI0gZHqXe7HjI/7/LykG4fks= +github.com/gernest/wow v0.1.0/go.mod h1:dEPabJRi5BneI1Nev1VWo0ZlcTWibHWp43qxKms4elY= +github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= +github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/projectdiscovery/gologger v1.0.1 h1:FzoYQZnxz9DCvSi/eg5A6+ET4CQ0CDUs27l6Exr8zMQ= +github.com/projectdiscovery/gologger v1.0.1/go.mod h1:Ok+axMqK53bWNwDSU1nTNwITLYMXMdZtRc8/y1c7sWE= +github.com/remeh/sizedwaitgroup v1.0.0 h1:VNGGFwNo/R5+MJBf6yrsr110p0m4/OX4S3DCy7Kyl5E= +github.com/remeh/sizedwaitgroup v1.0.0/go.mod h1:3j2R4OIe/SeS6YDhICBy22RWjJC5eNCJ1V+9+NVNYlo= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= +github.com/zenthangplus/goccm v0.0.0-20200608171100-39e9e08b694a/go.mod h1:PPYr3s9FhH/9fs7kfozlHKs2VXzk4Foyzb3Mke/Bg0U= +golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20201217014255-9d1352758620 h1:3wPMTskHO3+O6jqTEXyFcsnuxMQOqYSaHsDxcbUXpqA= +golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190116161447-11f53e031339/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/internal/runner/constant.go b/internal/runner/constant.go new file mode 100644 index 0000000..b426068 --- /dev/null +++ b/internal/runner/constant.go @@ -0,0 +1,45 @@ +package runner + +var ( + opt *Options + uhost []string +) + +const ( + version = "v0.0.1" + banner = ` + _ + ` + version + ` | | + ___ ___| |__ + / __/ __| '_ \ + \__ \__ \ |_) | + |___/___/_.__/ + +Secure Shell Bruteforcer + infosec@kitabisa.com + +` + usage = `Usage: + ssb [-p port] [-w wordlist.txt] [-t timeout] + [-c concurrent] [-o output] [user@]hostname + +Options: + -p port + Port to connect to on the remote host (default 22). + -w wordlist + Path to wordlist file. + -t timeout + Connection timeout (default 30s). + -c concurrent + Concurrency/threads level (default 100). + -o output + Save valid password to file. + -v + Verbose mode. + +Examples: + ssb -w wordlist.txt -t 1m -c 1000 root@localhost + +` + timeout = "30s" +) diff --git a/internal/runner/parser.go b/internal/runner/parser.go new file mode 100644 index 0000000..0b1970d --- /dev/null +++ b/internal/runner/parser.go @@ -0,0 +1,58 @@ +package runner + +import ( + "bufio" + "flag" + "fmt" + "os" + "time" + + "github.com/logrusorgru/aurora" + "github.com/projectdiscovery/gologger" +) + +// Options declare its options +type Options struct { + concurrent int + wordlist string + verbose bool + timeout time.Duration + output string + port int + list *bufio.Scanner + file *os.File + + user string + host string +} + +// Parse arguments +func Parse() *Options { + opt = &Options{} + opt.timeout, _ = time.ParseDuration(timeout) + + flag.IntVar(&opt.port, "p", 22, "") + flag.IntVar(&opt.concurrent, "c", 100, "") + flag.BoolVar(&opt.verbose, "v", false, "") + flag.StringVar(&opt.output, "o", "", "") + flag.StringVar(&opt.wordlist, "w", "", "") + flag.DurationVar(&opt.timeout, "t", opt.timeout, "") + + flag.Usage = func() { + showBanner() + fmt.Fprint(os.Stderr, usage) + } + flag.Parse() + + showBanner() + + if err := opt.validate(); err != nil { + gologger.Fatalf("Error! %s.", err.Error()) + } + + return opt +} + +func showBanner() { + fmt.Fprint(os.Stderr, aurora.Bold(aurora.Cyan(banner))) +} diff --git a/internal/runner/runner.go b/internal/runner/runner.go new file mode 100644 index 0000000..5dff650 --- /dev/null +++ b/internal/runner/runner.go @@ -0,0 +1,71 @@ +package runner + +import ( + "fmt" + "os" + "strconv" + + "github.com/logrusorgru/aurora" + "github.com/projectdiscovery/gologger" + "github.com/remeh/sizedwaitgroup" + "ktbs.dev/ssb/pkg/ssb" +) + +// New execute bruteforces +func New(opt *Options) { + opt.showInfo() + + job := make(chan string) + cur := opt.concurrent + swg := sizedwaitgroup.New(cur) + + for i := 0; i < cur; i++ { + swg.Add() + go func() { + defer swg.Done() + for pass := range job { + opt.run(pass) + } + }() + } + + for opt.list.Scan() { + job <- opt.list.Text() + } + + close(job) + swg.Wait() + gologger.Infof("Done!") +} + +func (opt *Options) run(password string) { + cfg := ssb.New(opt.user, password, opt.timeout) + + con, err := ssb.Connect(opt.host, opt.port, cfg) + if err != nil { + if opt.verbose { + gologger.Errorf("Failed '%s': %s.", password, err.Error()) + } + } + + if con { + fmt.Printf("[%s] Connected with '%s'.\n", aurora.Green("VLD"), aurora.Magenta(password)) + + if opt.file != nil { + fmt.Fprintf(opt.file, "%s\n", password) + } + } +} + +func (opt *Options) showInfo() { + info := "________________________\n" + info += "\n :: Username: " + opt.user + info += "\n :: Hostname: " + opt.host + info += "\n :: Port : " + strconv.Itoa(opt.port) + info += "\n :: Wordlist: " + opt.wordlist + info += "\n :: Threads : " + strconv.Itoa(opt.concurrent) + info += "\n :: Timeout : " + opt.timeout.String() + info += "\n________________________\n\n" + + fmt.Fprint(os.Stderr, info) +} diff --git a/internal/runner/validator.go b/internal/runner/validator.go new file mode 100644 index 0000000..a36d9a2 --- /dev/null +++ b/internal/runner/validator.go @@ -0,0 +1,51 @@ +package runner + +import ( + "bufio" + "errors" + "flag" + "os" + "os/user" + "strings" +) + +func (opt *Options) validate() error { + var errFile error + + if flag.Arg(0) != "" { + uhost = strings.SplitN(flag.Arg(0), "@", 2) + } else { + return errors.New("Please define a target server") + } + + if len(uhost) < 2 { + usr, err := user.Current() + if err != nil { + usr.Username = "root" + } + opt.user = usr.Username + opt.host = uhost[0] + } else { + opt.user = uhost[0] + opt.host = uhost[1] + } + + if opt.wordlist != "" { + f, err := os.Open(opt.wordlist) + if err != nil { + return err + } + opt.list = bufio.NewScanner(f) + } else { + return errors.New("No wordlist file provided") + } + + if opt.output != "" { + opt.file, errFile = os.OpenFile(opt.output, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644) + if errFile != nil { + return errFile + } + } + + return nil +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..559c811 --- /dev/null +++ b/main.go @@ -0,0 +1,8 @@ +package main + +import "ktbs.dev/ssb/internal/runner" + +func main() { + opt := runner.Parse() + runner.New(opt) +} diff --git a/pkg/ssb/ssb.go b/pkg/ssb/ssb.go new file mode 100644 index 0000000..0f6c27f --- /dev/null +++ b/pkg/ssb/ssb.go @@ -0,0 +1,31 @@ +package ssb + +import ( + "fmt" + "strconv" + "time" + + "golang.org/x/crypto/ssh" +) + +// New defines SSH client configurations +func New(username string, password string, timeout time.Duration) *ssh.ClientConfig { + return &ssh.ClientConfig{ + HostKeyCallback: ssh.InsecureIgnoreHostKey(), + Timeout: timeout, + User: username, + Auth: []ssh.AuthMethod{ + ssh.Password(password), + }, + } +} + +// Connect for dialing to SSH server +func Connect(host string, port int, config *ssh.ClientConfig) (bool, error) { + _, err := ssh.Dial("tcp", fmt.Sprintf("%s:%s", host, strconv.Itoa(port)), config) + if err != nil { + return false, err + } + + return true, nil +}