ruby-gobuster 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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