ruby-gobuster 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 46da4800468b08ecbd33ac924c55be44cb5424a89cf6831e23100962f3719945
4
+ data.tar.gz: c832814d91e9f1af76f8ddb672b2363b893b7c199b926c308378c9b0cbae1d5e
5
+ SHA512:
6
+ metadata.gz: d1ba64ddefb078f45841a265dca6d152d64679533f8845293a7c86aaf29db2d2162ed6afd1319a33323ef1a130cc5b667d527e98465130a7e2d85ef46de668de
7
+ data.tar.gz: 2b3fc4de08c7e45a14e8515a7d8168ec2f49c2f92f27a0c18f4dd4acda35c7523c9305113a602b6316aae73519ed7226dae3950f23e6bb79b6a6d2a1ea70ee5a
data/.document ADDED
@@ -0,0 +1,3 @@
1
+ -
2
+ ChangeLog.md
3
+ LICENSE.txt
@@ -0,0 +1,28 @@
1
+ name: CI
2
+
3
+ on: [ push, pull_request ]
4
+
5
+ jobs:
6
+ tests:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ fail-fast: false
10
+ matrix:
11
+ ruby:
12
+ - 2.6
13
+ - 2.7
14
+ - '3.0'
15
+ - 3.1
16
+ - jruby
17
+ - truffleruby
18
+ name: Ruby ${{ matrix.ruby }}
19
+ steps:
20
+ - uses: actions/checkout@v2
21
+ - name: Set up Ruby
22
+ uses: ruby/setup-ruby@v1
23
+ with:
24
+ ruby-version: ${{ matrix.ruby }}
25
+ - name: Install dependencies
26
+ run: bundle install --jobs 4 --retry 3
27
+ - name: Run tests
28
+ run: bundle exec rake test
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /Gemfile.lock
2
+ /coverage
3
+ /doc
4
+ /pkg
5
+ /.yardoc
6
+ .DS_Store
7
+ *.db
8
+ *.log
9
+ *.swp
10
+ *~
11
+ *.gem
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup markdown --title 'Ruby Gobuster Documentation' --protected
data/ChangeLog.md ADDED
@@ -0,0 +1,13 @@
1
+ ### 0.1.0 / 2021-04-22
2
+
3
+ * Initial release:
4
+ * Added {Gobuster::Command}.
5
+ * Added {Gobuster::Hostname}.
6
+ * Added {Gobuster::OutputFile}.
7
+ * Added {Gobuster::Parsers::Dir}.
8
+ * Added {Gobuster::Parsers::DNS}.
9
+ * Added {Gobuster::Parsers::Fuzz}.
10
+ * Added {Gobuster::Parsers::S3}.
11
+ * Added {Gobuster::Response}.
12
+ * Added {Gobuster::S3Bucket}.
13
+
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ # gem 'command_mapper', '~> 0.2', github: 'postmodern/command_mapper.rb'
6
+
7
+ group :development do
8
+ gem 'rake'
9
+ gem 'rubygems-tasks', '~> 0.2'
10
+ gem 'rspec', '~> 3.0'
11
+ gem 'simplecov', '~> 0.7'
12
+
13
+ gem 'kramdown'
14
+ gem 'redcarpet', platform: :mri
15
+ gem 'yard', '~> 0.9'
16
+ gem 'yard-spellcheck', require: false
17
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2022 Hal Brodigan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ 'Software'), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # ruby-gobuster
2
+
3
+ [![CI](https://github.com/postmodern/ruby-gobuster/actions/workflows/ruby.yml/badge.svg)](https://github.com/postmodern/ruby-gobuster/actions/workflows/ruby.yml)
4
+ [![Gem Version](https://badge.fury.io/rb/ruby-gobuster.svg)](https://badge.fury.io/rb/ruby-gobuster)
5
+
6
+ * [Source](https://github.com/postmodern/ruby-gobuster/)
7
+ * [Issues](https://github.com/postmodern/ruby-gobuster/issues)
8
+ * [Documentation](http://rubydoc.info/gems/ruby-gobuster/frames)
9
+
10
+ ## Description
11
+
12
+ A Ruby interface to [gobuster], a tool used to bruteforce URIs, DNS, VHosts, S3.
13
+
14
+ ## Features
15
+
16
+ * Provides a [Ruby interface][Gobuster::Command] for running the `gobuster`
17
+ command.
18
+ * Supports [parsing][Gobuster::OutputFile] `gobuster -o ... {dir|dns|fuzz|s3}`
19
+ output files.
20
+
21
+ [Gobuster::Command]: https://rubydoc.info/gems/ruby-gobuster/Gobuster/Command
22
+ [Gobuster::OutputFile]: https://rubydoc.info/gems/ruby-gobuster/Gobuster/OutputFile
23
+
24
+ ## Examples
25
+
26
+ Run `gobuster --wordlist /path/to/wordlist.txt dir -u https://example.com` from Ruby:
27
+
28
+ ```ruby
29
+ require 'gobuster/command'
30
+
31
+ Gobuster::Command.run(wordlist: '/path/to/wordlist.txt', dir: {url: 'https://example.com'})
32
+ ```
33
+
34
+ ## Requirements
35
+
36
+ * [ruby] >= 2.0.0
37
+ * [gobuster] >= 3.1.0
38
+ * [command_mapper] ~> 0.2, >= 0.2.1
39
+
40
+ [ruby]: https://www.ruby-lang.org/
41
+ [command_mapper]: https://github.com/postmodern/command_mapper.rb#readme
42
+
43
+ ## Install
44
+
45
+ ```shell
46
+ $ gem install ruby-gobuster
47
+ ```
48
+
49
+ ### gemspec
50
+
51
+ ```ruby
52
+ gemspec.add_dependency 'ruby-gobuster', '~> 0.1'
53
+ ```
54
+
55
+ ### Gemfile
56
+
57
+ ```ruby
58
+ gem 'ruby-gobuster', '~> 0.1'
59
+ ```
60
+
61
+ ## License
62
+
63
+ Copyright (c) 2022 Hal Brodigan
64
+
65
+ See {file:LICENSE.txt} for license information.
66
+
67
+ [gobuster]: https://github.com/OJ/gobuster#readme
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+
5
+ begin
6
+ require 'bundler/setup'
7
+ rescue LoadError => e
8
+ warn e.message
9
+ warn "Run `gem install bundler` to install Bundler"
10
+ exit -1
11
+ end
12
+
13
+ require 'rubygems/tasks'
14
+ Gem::Tasks.new
15
+
16
+ require 'rspec/core/rake_task'
17
+ RSpec::Core::RakeTask.new
18
+ task :test => :spec
19
+ task :default => :spec
20
+
21
+ require 'yard'
22
+ YARD::Rake::YardocTask.new
23
+ task :doc => :yard
data/gemspec.yml ADDED
@@ -0,0 +1,27 @@
1
+ name: ruby-gobuster
2
+ summary: A Ruby interface to gobuster.
3
+ description:
4
+ A Ruby interface to gobuster, a tool used to bruteforce URIs, DNS, VHosts, S3.
5
+
6
+ license: MIT
7
+ authors: Postmodern
8
+ email: postmodern.mod3@gmail.com
9
+ homepage: https://github.com/postmodern/ruby-gobuster#readme
10
+ has_yard: true
11
+
12
+ metadata:
13
+ documentation_uri: https://rubydoc.info/gems/ruby-gobuster
14
+ source_code_uri: https://github.com/postmodern/ruby-gobuster
15
+ bug_tracker_uri: https://github.com/postmodern/ruby-gobuster/issues
16
+ changelog_uri: https://github.com/postmodern/ruby-gobuster/blob/master/ChangeLog.md
17
+ rubygems_mfa_required: 'true'
18
+
19
+ required_ruby_version: ">= 2.0.0"
20
+
21
+ requirements: gobuster >= 3.1.0
22
+
23
+ dependencies:
24
+ command_mapper: ~> 0.2, >= 0.2.1
25
+
26
+ development_dependencies:
27
+ bundler: ~> 2.0
@@ -0,0 +1,169 @@
1
+ require 'command_mapper/command'
2
+
3
+ #
4
+ # Represents the `gobuster` command
5
+ #
6
+ module Gobuster
7
+ class Command < CommandMapper::Command
8
+
9
+ #
10
+ # Represents the type for `--delay` and `--timeout` options.
11
+ #
12
+ # @api private
13
+ #
14
+ class Duration < CommandMapper::Types::Str
15
+
16
+ #
17
+ # Validates the given value.
18
+ #
19
+ # @param [Object] value
20
+ # The given value to validate.
21
+ #
22
+ # @return [true, (false, String)]
23
+ # Returns true if the value is considered valid, or false and a
24
+ # validation message if the value is not valid.
25
+ #
26
+ def validate(value)
27
+ valid, message = super(value)
28
+
29
+ unless valid
30
+ return [valid, message]
31
+ end
32
+
33
+ value = value.to_s
34
+
35
+ unless value =~ /\A\d+(?:m|s|ms|ns)\z/
36
+ return [false, "must be a number and end with 'm', 's', 'ms', or 'ns'"]
37
+ end
38
+
39
+ return true
40
+ end
41
+
42
+ end
43
+
44
+ command "gobuster" do
45
+ option "--delay", value: {type: Duration.new}
46
+ option "--no-error"
47
+ option "--no-progress"
48
+ option "--output", value: true
49
+ option "--pattern", value: true
50
+ option "--quiet"
51
+ option "--threads", value: {type: Num.new}
52
+ option "--verbose"
53
+ option "--wordlist", value: true
54
+
55
+ subcommand "completion" do
56
+ subcommand "bash" do
57
+ option "--help"
58
+ option "--no-descriptions"
59
+ end
60
+
61
+ subcommand "fish" do
62
+ option "--help"
63
+ option "--no-descriptions"
64
+ end
65
+
66
+ subcommand "powershell" do
67
+ option "--help"
68
+ option "--no-descriptions"
69
+ end
70
+
71
+ subcommand "zsh" do
72
+ option "--help"
73
+ option "--no-descriptions"
74
+ end
75
+ end
76
+
77
+ subcommand "dir" do
78
+ option "--add-slash"
79
+ option "--cookies", value: true
80
+ option "--discover-backup"
81
+ option "--exclude-length", value: {type: Num.new}, repeats: true
82
+ option "--expanded"
83
+ option "--extensions", value: true
84
+ option "--follow-redirect"
85
+ option "--headers", value: true, repeats: true
86
+ option "--help"
87
+ option "--hide-length"
88
+ option "--method", value: true
89
+ option "--no-status"
90
+ option "--no-tls-validation"
91
+ option "--password", value: true
92
+ option "--proxy", value: true
93
+ option "--random-agent"
94
+ option "--status-codes", value: true
95
+ option "--status-codes-blacklist", value: true
96
+ option "--timeout", value: {type: Duration.new}
97
+ option "--url", value: true
98
+ option "--useragent", value: true
99
+ option "--username", value: true
100
+ option "--wildcard"
101
+ end
102
+
103
+ subcommand "dns" do
104
+ option "--domain", value: true
105
+ option "--help"
106
+ option "--resolver", value: true
107
+ option "--show-cname"
108
+ option "--show-ips"
109
+ option "--timeout", value: {type: Duration.new}
110
+ option "--wildcard"
111
+ end
112
+
113
+ subcommand "fuzz" do
114
+ option "--cookies", value: true
115
+ option "--exclude-length", value: {type: Num.new}, repeats: true
116
+ option "--excludestatuscodes", value: true
117
+ option "--follow-redirect"
118
+ option "--headers", value: true, repeats: true
119
+ option "--help"
120
+ option "--method", value: true
121
+ option "--no-tls-validation"
122
+ option "--password", value: true
123
+ option "--proxy", value: true
124
+ option "--random-agent"
125
+ option "--timeout", value: {type: Duration.new}
126
+ option "--url", value: true
127
+ option "--useragent", value: true
128
+ option "--username", value: true
129
+ option "--wildcard"
130
+ end
131
+
132
+ subcommand "help" do
133
+ option "--help"
134
+
135
+ argument :command, required: false
136
+ end
137
+
138
+ subcommand "s3" do
139
+ option "--help"
140
+ option "--maxfiles", value: {type: Num.new}
141
+ option "--proxy", value: true
142
+ option "--random-agent"
143
+ option "--timeout", value: {type: Duration.new}
144
+ option "--useragent", value: true
145
+ end
146
+
147
+ subcommand "version" do
148
+ option "--help"
149
+ end
150
+
151
+ subcommand "vhost" do
152
+ option "--cookies", value: true
153
+ option "--follow-redirect"
154
+ option "--headers", value: true, repeats: true
155
+ option "--help"
156
+ option "--method", value: true
157
+ option "--no-tls-validation"
158
+ option "--password", value: true
159
+ option "--proxy", value: true
160
+ option "--random-agent"
161
+ option "--timeout", value: {type: Duration.new}
162
+ option "--url", value: true
163
+ option "--useragent", value: true
164
+ option "--username", value: true
165
+ end
166
+ end
167
+
168
+ end
169
+ end
@@ -0,0 +1,33 @@
1
+ module Gobuster
2
+ #
3
+ # Represents a hostname found by `gobuster dns`.
4
+ #
5
+ class Hostname
6
+
7
+ # The host name.
8
+ #
9
+ # @return [String]
10
+ attr_reader :name
11
+
12
+ #
13
+ # Initializes the hostname.
14
+ #
15
+ # @param [String] name
16
+ #
17
+ def initialize(name)
18
+ @name = name
19
+ end
20
+
21
+ #
22
+ # Converts the hostname to a String.
23
+ #
24
+ # @return [String]
25
+ #
26
+ def to_s
27
+ @name
28
+ end
29
+
30
+ alias to_str to_s
31
+
32
+ end
33
+ end
@@ -0,0 +1,99 @@
1
+ require 'gobuster/parsers/dir'
2
+ require 'gobuster/parsers/dns'
3
+ require 'gobuster/parsers/fuzz'
4
+ require 'gobuster/parsers/s3'
5
+
6
+ module Gobuster
7
+ #
8
+ # Parses an output file created by `gobuster -o ...`.
9
+ #
10
+ # ## Example
11
+ #
12
+ # require 'gobuster/output_file'
13
+ #
14
+ # output_file = Gobuster::OutputFile.new('/path/to/file.txt')
15
+ # output_file.each do |object|
16
+ # p object
17
+ # end
18
+ #
19
+ # @api public
20
+ #
21
+ class OutputFile
22
+
23
+ # Mapping of formats to parsers.
24
+ #
25
+ # @api semipublic
26
+ PARSERS = {
27
+ dir: Parsers::Dir,
28
+ dns: Parsers::DNS,
29
+ fuzz: Parsers::Fuzz,
30
+ s3: Parsers::S3
31
+ }
32
+
33
+ # The path to the output file.
34
+ #
35
+ # @return [String]
36
+ attr_reader :path
37
+
38
+ # The format of the output file.
39
+ #
40
+ # @return [:dir, :dns, :fuzz, :s3]
41
+ attr_reader :format
42
+
43
+ # The parser for the output file format.
44
+ #
45
+ # @return [Parsers::Dir, Parsers::DNS, Parsers::Fuzz, Parsers:S3]
46
+ #
47
+ # @api private
48
+ attr_reader :parser
49
+
50
+ #
51
+ # Initializes the output file.
52
+ #
53
+ # @param [String] path
54
+ # The path to the output file.
55
+ #
56
+ # @param [:dir, :dns, :fuzz, :s3] format
57
+ # The optional format of the output file.
58
+ #
59
+ def initialize(path, format: )
60
+ @path = File.expand_path(path)
61
+ @format = format
62
+
63
+ @parser = PARSERS.fetch(format) do
64
+ raise(ArgumentError,"unrecognized file type: #{@path.inspect}")
65
+ end
66
+ end
67
+
68
+ #
69
+ # Parses the contents of the output file.
70
+ #
71
+ # @yield [object]
72
+ # The given block will be passed each parsed object.
73
+ #
74
+ # @yieldparam [Response, Hostname, S3Bucket] object
75
+ # A parsed object from the output file.
76
+ #
77
+ # @return [Enumerator]
78
+ # If no block is given, an Enumerator object will be returned.
79
+ #
80
+ def each(&block)
81
+ return enum_for(__method__) unless block
82
+
83
+ File.open(@path) do |file|
84
+ @parser.parse(file,&block)
85
+ end
86
+ end
87
+
88
+ #
89
+ # Converts the output file to a String.
90
+ #
91
+ # @return [String]
92
+ # The path to the output file.
93
+ #
94
+ def to_s
95
+ @path
96
+ end
97
+
98
+ end
99
+ end
@@ -0,0 +1,38 @@
1
+ require 'gobuster/response'
2
+
3
+ module Gobuster
4
+ module Parsers
5
+ module Dir
6
+ #
7
+ # Parses `gobuster dir` output.
8
+ #
9
+ # @param [IO] io
10
+ # The IO stream to parse.
11
+ #
12
+ # @yield [response]
13
+ # The given block will be passed each parsed response.
14
+ #
15
+ # @yieldparam [Response] response
16
+ # The parsed response.
17
+ #
18
+ # @return [Enumerator]
19
+ # If no block is given, an Enumerator will be returned.
20
+ #
21
+ def self.parse(io)
22
+ return enum_for(__method__,io) unless block_given?
23
+
24
+ line_regexp = /^(\/[^\s]+)\s+\(Status: (\d{3})\)\s+\[Size: (\d+)\]/
25
+
26
+ io.each_line do |line|
27
+ if (match = line.match(line_regexp))
28
+ yield Response.new(
29
+ path: match[1],
30
+ status: match[2].to_i,
31
+ size: match[3].to_i
32
+ )
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,35 @@
1
+ require 'gobuster/hostname'
2
+
3
+ module Gobuster
4
+ module Parsers
5
+ module DNS
6
+ #
7
+ # Parses `gobuster dns` output.
8
+ #
9
+ # @param [IO] io
10
+ # The IO stream to parse.
11
+ #
12
+ # @yield [hostname]
13
+ # The given block will be passed each parsed hostname.
14
+ #
15
+ # @yieldparam [Hostname] hostname
16
+ # The parsed hostname.
17
+ #
18
+ # @return [Enumerator]
19
+ # If no block is given, an Enumerator will be returned.
20
+ #
21
+ def self.parse(io)
22
+ return enum_for(__method__,io) unless block_given?
23
+
24
+ io.each_line do |line|
25
+ if line.start_with?('Found: ')
26
+ line.chomp!
27
+ line.sub!('Found: ','')
28
+
29
+ yield Hostname.new(line)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,38 @@
1
+ require 'gobuster/response'
2
+
3
+ module Gobuster
4
+ module Parsers
5
+ module Fuzz
6
+ #
7
+ # Parses `gobuster fuzz` output.
8
+ #
9
+ # @param [IO] io
10
+ # The IO stream to parse.
11
+ #
12
+ # @yield [response]
13
+ # The given block will be passed each parsed response.
14
+ #
15
+ # @yieldparam [Response] response
16
+ # The parsed response.
17
+ #
18
+ # @return [Enumerator]
19
+ # If no block is given, an Enumerator will be returned.
20
+ #
21
+ def self.parse(io)
22
+ return enum_for(__method__,io) unless block_given?
23
+
24
+ line_regexp = /^Found:\s+\[Status=(\d{3})\]\s+\[Length=(\d+)\]\s+([^\s]++)/
25
+
26
+ io.each_line do |line|
27
+ if (match = line.match(line_regexp))
28
+ yield Response.new(
29
+ status: match[1].to_i,
30
+ size: match[2].to_i,
31
+ url: match[3],
32
+ )
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,34 @@
1
+ require 'gobuster/s3_bucket'
2
+
3
+ module Gobuster
4
+ module Parsers
5
+ module S3
6
+ #
7
+ # Parses `gobuster s3` output.
8
+ #
9
+ # @param [IO] io
10
+ # The IO stream to parse.
11
+ #
12
+ # @yield [s3bucket]
13
+ # The given block will be passed each parsed s3bucket.
14
+ #
15
+ # @yieldparam [S3Bucket] s3bucket
16
+ # The parsed s3bucket.
17
+ #
18
+ # @return [Enumerator]
19
+ # If no block is given, an Enumerator will be returned.
20
+ #
21
+ def self.parse(io)
22
+ return enum_for(__method__,io) unless block_given?
23
+
24
+ io.each_line do |line|
25
+ line.chomp!
26
+
27
+ if line.start_with?('http://') && line.end_with?('s3.amazonaws.com/')
28
+ yield S3Bucket.new(line)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end