ruby-feroxbuster 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.
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+ require 'feroxbuster/parsers/json'
3
+
4
+ describe Feroxbuster::Parsers::JSON do
5
+ describe ".parse" do
6
+ let(:line) { json }
7
+ let(:io) { StringIO.new(line + $/) }
8
+
9
+ let(:parsed_json) { JSON.parse(json) }
10
+
11
+ context "when the JSON \"type\" attribute is \"response\"" do
12
+ let(:json) do
13
+ "{\"type\":\"response\",\"url\":\"https://github.com/test\",\"original_url\":\"https://github.com\",\"path\":\"/test\",\"wildcard\":false,\"status\":200,\"method\":\"GET\",\"content_length\":0,\"line_count\":2010,\"word_count\":11253,\"headers\":{\"permissions-policy\":\"interest-cohort=()\",\"accept-ranges\":\"bytes\",\"referrer-policy\":\"origin-when-cross-origin, strict-origin-when-cross-origin\",\"x-content-type-options\":\"nosniff\",\"cache-control\":\"max-age=0, private, must-revalidate\",\"expect-ct\":\"max-age=2592000, report-uri=\\\"https://api.github.com/_private/browser/errors\\\"\",\"server\":\"GitHub.com\",\"x-github-request-id\":\"85A8:0E10:20B03E:27719A:6260B1D5\",\"transfer-encoding\":\"chunked\",\"date\":\"Thu, 21 Apr 2022 01:22:16 GMT\",\"strict-transport-security\":\"max-age=31536000; includeSubdomains; preload\",\"etag\":\"W/\\\"7c98cb0440eb94eddcfd360497fae419\\\"\",\"x-frame-options\":\"deny\",\"content-security-policy\":\"default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com objects-origin.githubusercontent.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com cdn.optimizely.com logx.optimizely.com/v1/events translator.github.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com online.visualstudio.com/api/v1/locations github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src render.githubusercontent.com viewscreen.githubusercontent.com notebooks.githubusercontent.com; img-src 'self' data: github.githubassets.com identicons.github.com github-cloud.s3.amazonaws.com secured-user-images.githubusercontent.com/ *.githubusercontent.com; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; worker-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/\",\"x-xss-protection\":\"0\",\"set-cookie\":\"logged_in=no; Path=/; Domain=github.com; Expires=Fri, 21 Apr 2023 01:22:29 GMT; HttpOnly; Secure; SameSite=Lax\",\"vary\":\"X-Requested-With, X-PJAX-Container, Accept-Encoding, Accept, X-Requested-With\",\"content-type\":\"text/html; charset=utf-8\"},\"extension\":\"\"}"
14
+ end
15
+
16
+ it "must parse each line and yield Feroxbuster::Response objects" do
17
+ yielded_objects = []
18
+
19
+ subject.parse(io) do |response|
20
+ yielded_objects << response
21
+ end
22
+
23
+ expect(yielded_objects.length).to eq(1)
24
+ expect(yielded_objects.first).to be_kind_of(Feroxbuster::Response)
25
+
26
+ yielded_response = yielded_objects.first
27
+ expect(yielded_response.url).to eq(parsed_json['url'])
28
+ expect(yielded_response.original_url).to eq(parsed_json['original_url'])
29
+ expect(yielded_response.path).to eq(parsed_json['path'])
30
+ expect(yielded_response.wildcard).to eq(parsed_json['wildcard'])
31
+ expect(yielded_response.status).to eq(parsed_json['status'])
32
+ expect(yielded_response.method).to eq(parsed_json['method'])
33
+ expect(yielded_response.content_length).to eq(parsed_json['content_length'])
34
+ expect(yielded_response.line_count).to eq(parsed_json['line_count'])
35
+ expect(yielded_response.word_count).to eq(parsed_json['word_count'])
36
+ expect(yielded_response.headers).to eq(parsed_json['headers'])
37
+ expect(yielded_response.extension).to eq(parsed_json['extension'])
38
+ end
39
+ end
40
+
41
+ context "when the JSON \"type\" attribute is \"statistics\"" do
42
+ let(:json) do
43
+ "{\"type\":\"statistics\",\"timeouts\":0,\"requests\":18,\"expected_per_scan\":6,\"total_expected\":12,\"errors\":0,\"successes\":12,\"redirects\":0,\"client_errors\":6,\"server_errors\":0,\"total_scans\":2,\"initial_targets\":0,\"links_extracted\":0,\"extensions_collected\":0,\"status_200s\":12,\"status_301s\":0,\"status_302s\":0,\"status_401s\":0,\"status_403s\":0,\"status_429s\":0,\"status_500s\":0,\"status_503s\":0,\"status_504s\":0,\"status_508s\":0,\"wildcards_filtered\":0,\"responses_filtered\":0,\"resources_discovered\":4,\"url_format_errors\":0,\"redirection_errors\":0,\"connection_errors\":0,\"request_errors\":0,\"directory_scan_times\":[0.434531853,0.434228035],\"total_runtime\":[1.6527268240000001]}"
44
+ end
45
+
46
+ it "must parse each line and yield Feroxbuster::Statistics objects" do
47
+ yielded_objects = []
48
+
49
+ subject.parse(io) do |statistics|
50
+ yielded_objects << statistics
51
+ end
52
+
53
+ expect(yielded_objects.length).to eq(1)
54
+ expect(yielded_objects.first).to be_kind_of(Feroxbuster::Statistics)
55
+
56
+ yielded_statistics = yielded_objects.first
57
+ expect(yielded_statistics.timeouts).to eq(parsed_json['timeouts'])
58
+ expect(yielded_statistics.requests).to eq(parsed_json['requests'])
59
+ expect(yielded_statistics.expected_per_scan).to eq(parsed_json['expected_per_scan'])
60
+ expect(yielded_statistics.total_expected).to eq(parsed_json['total_expected'])
61
+ expect(yielded_statistics.errors).to eq(parsed_json['errors'])
62
+ expect(yielded_statistics.successes).to eq(parsed_json['successes'])
63
+ expect(yielded_statistics.redirects).to eq(parsed_json['redirects'])
64
+ expect(yielded_statistics.client_errors).to eq(parsed_json['client_errors'])
65
+ expect(yielded_statistics.server_errors).to eq(parsed_json['server_errors'])
66
+ expect(yielded_statistics.total_scans).to eq(parsed_json['total_scans'])
67
+ expect(yielded_statistics.initial_targets).to eq(parsed_json['initial_targets'])
68
+ expect(yielded_statistics.links_extracted).to eq(parsed_json['links_extracted'])
69
+ expect(yielded_statistics.extensions_collected).to eq(parsed_json['extensions_collected'])
70
+ expect(yielded_statistics.status_200s).to eq(parsed_json['status_200s'])
71
+ expect(yielded_statistics.status_301s).to eq(parsed_json['status_301s'])
72
+ expect(yielded_statistics.status_302s).to eq(parsed_json['status_302s'])
73
+ expect(yielded_statistics.status_401s).to eq(parsed_json['status_401s'])
74
+ expect(yielded_statistics.status_403s).to eq(parsed_json['status_403s'])
75
+ expect(yielded_statistics.status_429s).to eq(parsed_json['status_429s'])
76
+ expect(yielded_statistics.status_500s).to eq(parsed_json['status_500s'])
77
+ expect(yielded_statistics.status_503s).to eq(parsed_json['status_503s'])
78
+ expect(yielded_statistics.status_504s).to eq(parsed_json['status_504s'])
79
+ expect(yielded_statistics.status_508s).to eq(parsed_json['status_508s'])
80
+ expect(yielded_statistics.wildcards_filtered).to eq(parsed_json['wildcards_filtered'])
81
+ expect(yielded_statistics.responses_filtered).to eq(parsed_json['responses_filtered'])
82
+ expect(yielded_statistics.resources_discovered).to eq(parsed_json['resources_discovered'])
83
+ expect(yielded_statistics.url_format_errors).to eq(parsed_json['url_format_errors'])
84
+ expect(yielded_statistics.redirection_errors).to eq(parsed_json['redirection_errors'])
85
+ expect(yielded_statistics.connection_errors).to eq(parsed_json['connection_errors'])
86
+ expect(yielded_statistics.request_errors).to eq(parsed_json['request_errors'])
87
+ expect(yielded_statistics.directory_scan_times).to eq(parsed_json['directory_scan_times'])
88
+ expect(yielded_statistics.total_runtime).to eq(parsed_json['total_runtime'])
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+ require 'feroxbuster/parsers/txt'
3
+
4
+ describe Feroxbuster::Parsers::TXT do
5
+ describe ".parse" do
6
+ let(:status) { 200 }
7
+ let(:method) { "GET" }
8
+ let(:url) { "https://github.com/test" }
9
+
10
+ let(:line_count) { 2010 }
11
+ let(:word_count) { 11253 }
12
+ let(:content_length) { 0 }
13
+
14
+ let(:line) do
15
+ "#{status} #{method} #{line_count}l #{word_count}w #{content_length}c #{url}"
16
+ end
17
+ let(:io) { StringIO.new(line + $/) }
18
+
19
+ it "must parse each line and yield Feroxbuster::Response objects" do
20
+ yielded_responses = []
21
+
22
+ subject.parse(io) do |response|
23
+ yielded_responses << response
24
+ end
25
+
26
+ expect(yielded_responses.length).to eq(1)
27
+ expect(yielded_responses.first).to be_kind_of(Feroxbuster::Response)
28
+
29
+ yielded_response = yielded_responses.first
30
+ expect(yielded_response.status).to eq(status)
31
+ expect(yielded_response.method).to eq(method)
32
+ expect(yielded_response.url).to eq(url)
33
+ expect(yielded_response.line_count).to eq(line_count)
34
+ expect(yielded_response.word_count).to eq(word_count)
35
+ expect(yielded_response.content_length).to eq(content_length)
36
+ end
37
+
38
+ context "when there is other output mixed in" do
39
+ let(:lines) do
40
+ [
41
+ "",
42
+ " ___ ___ __ __ __ __ __ ___",
43
+ "|__ |__ |__) |__) | / ` / \ \_/ | | \ |__",
44
+ "| |___ | \ | \ | \__, \__/ / \ | |__/ |___",
45
+ "by Ben \"epi\" Risher πŸ€“ ver: 2.7.0",
46
+ "───────────────────────────┬──────────────────────",
47
+ " 🎯 Target Url β”‚ https://github.com",
48
+ " πŸš€ Threads β”‚ 50",
49
+ " πŸ“– Wordlist β”‚ ./feroxbuster/wordlist.txt",
50
+ " πŸ‘Œ Status Codes β”‚ [200, 204, 301, 302, 307, 308, 401, 403, 405, 500]",
51
+ " πŸ’₯ Timeout (secs) β”‚ 7",
52
+ " 🦑 User-Agent β”‚ feroxbuster/2.7.0",
53
+ " πŸ’‰ Config File β”‚ /home/postmodern/.config/feroxbuster/ferox-config.toml",
54
+ " 🏁 HTTP methods β”‚ [GET]",
55
+ " πŸ”ƒ Recursion Depth β”‚ 4",
56
+ "───────────────────────────┴──────────────────────",
57
+ " 🏁 Press [ENTER] to use the Scan Management Menuβ„’",
58
+ "──────────────────────────────────────────────────",
59
+ line,
60
+ "[####################] - 1s 12/12 0s found:3 errors:0 ",
61
+ "[####################] - 0s 6/6 4/s https://github.com ",
62
+ "[####################] - 0s 6/6 9/s https://github.com/ ",
63
+ ''
64
+ ]
65
+ end
66
+ let(:io) { StringIO.new(lines.join($/)) }
67
+
68
+ it "must ignore the other output lines" do
69
+ yielded_responses = []
70
+
71
+ subject.parse(io) do |response|
72
+ yielded_responses << response
73
+ end
74
+
75
+ expect(yielded_responses.length).to eq(1)
76
+ expect(yielded_responses.first).to be_kind_of(Feroxbuster::Response)
77
+
78
+ yielded_response = yielded_responses.first
79
+ expect(yielded_response.status).to eq(status)
80
+ expect(yielded_response.method).to eq(method)
81
+ expect(yielded_response.url).to eq(url)
82
+ expect(yielded_response.line_count).to eq(line_count)
83
+ expect(yielded_response.word_count).to eq(word_count)
84
+ expect(yielded_response.content_length).to eq(content_length)
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,3 @@
1
+ require 'rspec'
2
+ require 'simplecov'
3
+ SimpleCov.start
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-feroxbuster
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Postmodern
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-04-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: command_mapper
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.2'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.2.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.2'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.2.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.0'
47
+ description: A Ruby interface to feroxbuster, a simple, fast, recursive content discovery
48
+ tool written in Rust.
49
+ email: postmodern.mod3@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files:
53
+ - ChangeLog.md
54
+ - LICENSE.txt
55
+ - README.md
56
+ files:
57
+ - ".document"
58
+ - ".github/workflows/ruby.yml"
59
+ - ".gitignore"
60
+ - ".rspec"
61
+ - ".yardopts"
62
+ - ChangeLog.md
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - gemspec.yml
68
+ - lib/feroxbuster/command.rb
69
+ - lib/feroxbuster/output_file.rb
70
+ - lib/feroxbuster/parsers/json.rb
71
+ - lib/feroxbuster/parsers/txt.rb
72
+ - lib/feroxbuster/response.rb
73
+ - lib/feroxbuster/statistics.rb
74
+ - lib/feroxbuster/version.rb
75
+ - ruby-feroxbuster.gemspec
76
+ - spec/command_spec.rb
77
+ - spec/fixtures/output.json
78
+ - spec/fixtures/output.txt
79
+ - spec/output_file_spec.rb
80
+ - spec/parsers/json_spec.rb
81
+ - spec/parsers/txt_spec.rb
82
+ - spec/spec_helper.rb
83
+ homepage: https://github.com/postmodern/ruby-feroxbuster#readme
84
+ licenses:
85
+ - MIT
86
+ metadata:
87
+ documentation_uri: https://rubydoc.info/gems/ruby-feroxbuster
88
+ source_code_uri: https://github.com/postmodern/ruby-feroxbuster
89
+ bug_tracker_uri: https://github.com/postmodern/ruby-feroxbuster/issues
90
+ changelog_uri: https://github.com/postmodern/ruby-feroxbuster/blob/master/ChangeLog.md
91
+ rubygems_mfa_required: 'true'
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: 2.0.0
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements:
107
+ - feroxbuster >= 2.7.0
108
+ rubygems_version: 3.2.22
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: A Ruby interface to feroxbuster.
112
+ test_files: []