ronin-recon 0.1.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +4 -0
- data/.github/workflows/ruby.yml +46 -0
- data/.gitignore +20 -0
- data/.rspec +1 -0
- data/.rubocop.yml +44 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/COPYING.txt +165 -0
- data/ChangeLog.md +36 -0
- data/Gemfile +62 -0
- data/README.md +391 -0
- data/Rakefile +74 -0
- data/bin/ronin-recon +16 -0
- data/data/completions/ronin-recon +95 -0
- data/data/templates/worker.rb.erb +67 -0
- data/data/wordlists/raft-small-directories.txt.gz +0 -0
- data/data/wordlists/subdomains-1000.txt.gz +0 -0
- data/examples/recon.rb +24 -0
- data/gemspec.yml +57 -0
- data/lib/ronin/recon/builtin/dns/lookup.rb +65 -0
- data/lib/ronin/recon/builtin/dns/mailservers.rb +64 -0
- data/lib/ronin/recon/builtin/dns/nameservers.rb +61 -0
- data/lib/ronin/recon/builtin/dns/reverse_lookup.rb +63 -0
- data/lib/ronin/recon/builtin/dns/srv_enum.rb +178 -0
- data/lib/ronin/recon/builtin/dns/subdomain_enum.rb +105 -0
- data/lib/ronin/recon/builtin/dns/suffix_enum.rb +168 -0
- data/lib/ronin/recon/builtin/net/ip_range_enum.rb +65 -0
- data/lib/ronin/recon/builtin/net/port_scan.rb +84 -0
- data/lib/ronin/recon/builtin/net/service_id.rb +75 -0
- data/lib/ronin/recon/builtin/ssl/cert_enum.rb +109 -0
- data/lib/ronin/recon/builtin/ssl/cert_grab.rb +76 -0
- data/lib/ronin/recon/builtin/ssl/cert_sh.rb +77 -0
- data/lib/ronin/recon/builtin/web/dir_enum.rb +121 -0
- data/lib/ronin/recon/builtin/web/email_addresses.rb +70 -0
- data/lib/ronin/recon/builtin/web/spider.rb +93 -0
- data/lib/ronin/recon/builtin.rb +34 -0
- data/lib/ronin/recon/cli/command.rb +40 -0
- data/lib/ronin/recon/cli/commands/completion.rb +61 -0
- data/lib/ronin/recon/cli/commands/irb.rb +57 -0
- data/lib/ronin/recon/cli/commands/new.rb +203 -0
- data/lib/ronin/recon/cli/commands/run.rb +420 -0
- data/lib/ronin/recon/cli/commands/test.rb +99 -0
- data/lib/ronin/recon/cli/commands/worker.rb +114 -0
- data/lib/ronin/recon/cli/commands/workers.rb +80 -0
- data/lib/ronin/recon/cli/debug_option.rb +45 -0
- data/lib/ronin/recon/cli/printing.rb +122 -0
- data/lib/ronin/recon/cli/ruby_shell.rb +51 -0
- data/lib/ronin/recon/cli/worker_command.rb +105 -0
- data/lib/ronin/recon/cli.rb +50 -0
- data/lib/ronin/recon/config.rb +371 -0
- data/lib/ronin/recon/dns_worker.rb +41 -0
- data/lib/ronin/recon/engine.rb +639 -0
- data/lib/ronin/recon/exceptions.rb +45 -0
- data/lib/ronin/recon/graph.rb +127 -0
- data/lib/ronin/recon/importer.rb +224 -0
- data/lib/ronin/recon/input_file.rb +81 -0
- data/lib/ronin/recon/message/job_completed.rb +60 -0
- data/lib/ronin/recon/message/job_failed.rb +69 -0
- data/lib/ronin/recon/message/job_started.rb +60 -0
- data/lib/ronin/recon/message/shutdown.rb +38 -0
- data/lib/ronin/recon/message/value.rb +76 -0
- data/lib/ronin/recon/message/worker_started.rb +51 -0
- data/lib/ronin/recon/message/worker_stopped.rb +51 -0
- data/lib/ronin/recon/mixins/dns.rb +639 -0
- data/lib/ronin/recon/mixins/http.rb +58 -0
- data/lib/ronin/recon/mixins.rb +21 -0
- data/lib/ronin/recon/output_formats/dir.rb +94 -0
- data/lib/ronin/recon/output_formats/dot.rb +155 -0
- data/lib/ronin/recon/output_formats/graph_format.rb +48 -0
- data/lib/ronin/recon/output_formats/graphviz_format.rb +115 -0
- data/lib/ronin/recon/output_formats/pdf.rb +43 -0
- data/lib/ronin/recon/output_formats/png.rb +43 -0
- data/lib/ronin/recon/output_formats/svg.rb +43 -0
- data/lib/ronin/recon/output_formats.rb +48 -0
- data/lib/ronin/recon/registry.rb +35 -0
- data/lib/ronin/recon/root.rb +33 -0
- data/lib/ronin/recon/scope.rb +112 -0
- data/lib/ronin/recon/value/parser.rb +113 -0
- data/lib/ronin/recon/value.rb +110 -0
- data/lib/ronin/recon/value_status.rb +87 -0
- data/lib/ronin/recon/values/cert.rb +168 -0
- data/lib/ronin/recon/values/domain.rb +88 -0
- data/lib/ronin/recon/values/email_address.rb +114 -0
- data/lib/ronin/recon/values/host.rb +137 -0
- data/lib/ronin/recon/values/ip.rb +123 -0
- data/lib/ronin/recon/values/ip_range.rb +155 -0
- data/lib/ronin/recon/values/mailserver.rb +61 -0
- data/lib/ronin/recon/values/nameserver.rb +61 -0
- data/lib/ronin/recon/values/open_port.rb +190 -0
- data/lib/ronin/recon/values/url.rb +218 -0
- data/lib/ronin/recon/values/website.rb +200 -0
- data/lib/ronin/recon/values/wildcard.rb +140 -0
- data/lib/ronin/recon/values.rb +32 -0
- data/lib/ronin/recon/version.rb +26 -0
- data/lib/ronin/recon/web_worker.rb +35 -0
- data/lib/ronin/recon/worker.rb +433 -0
- data/lib/ronin/recon/worker_pool.rb +203 -0
- data/lib/ronin/recon/workers.rb +260 -0
- data/lib/ronin/recon.rb +22 -0
- data/man/ronin-recon-completion.1 +76 -0
- data/man/ronin-recon-completion.1.md +78 -0
- data/man/ronin-recon-irb.1 +27 -0
- data/man/ronin-recon-irb.1.md +26 -0
- data/man/ronin-recon-new.1 +58 -0
- data/man/ronin-recon-new.1.md +59 -0
- data/man/ronin-recon-run.1 +137 -0
- data/man/ronin-recon-run.1.md +115 -0
- data/man/ronin-recon-test.1 +53 -0
- data/man/ronin-recon-test.1.md +55 -0
- data/man/ronin-recon-worker.1 +32 -0
- data/man/ronin-recon-worker.1.md +34 -0
- data/man/ronin-recon-workers.1 +29 -0
- data/man/ronin-recon-workers.1.md +31 -0
- data/man/ronin-recon.1 +57 -0
- data/man/ronin-recon.1.md +57 -0
- data/ronin-recon.gemspec +62 -0
- data/scripts/setup +58 -0
- metadata +364 -0
@@ -0,0 +1,168 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-recon - A micro-framework and tool for performing reconnaissance.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-recon is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-recon is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-recon. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/recon/dns_worker'
|
22
|
+
require 'ronin/support/network/public_suffix'
|
23
|
+
|
24
|
+
require 'async/queue'
|
25
|
+
|
26
|
+
module Ronin
|
27
|
+
module Recon
|
28
|
+
module DNS
|
29
|
+
#
|
30
|
+
# Finds other domains with different suffixes for a given domain
|
31
|
+
# using the [public suffix list].
|
32
|
+
#
|
33
|
+
# [public suffix list]: https://publicsuffix.org/
|
34
|
+
#
|
35
|
+
class SuffixEnum < DNSWorker
|
36
|
+
|
37
|
+
register 'dns/suffix_enum'
|
38
|
+
|
39
|
+
summary 'Enumerates suffixes of a domain'
|
40
|
+
description <<~DESC
|
41
|
+
Attempts to find other domains with different suffixes for the given
|
42
|
+
domain using the public suffix list.
|
43
|
+
DESC
|
44
|
+
|
45
|
+
references [
|
46
|
+
'https://publicsuffix.org/'
|
47
|
+
]
|
48
|
+
|
49
|
+
accepts Domain
|
50
|
+
outputs Domain
|
51
|
+
|
52
|
+
param :concurrency, Integer, default: 10,
|
53
|
+
desc: 'Sets the number of async tasks'
|
54
|
+
|
55
|
+
# Known bad suffixes that act like wildcard domains.
|
56
|
+
BAD_SUFFIXES = Set[
|
57
|
+
'aquila.it',
|
58
|
+
'arab',
|
59
|
+
'belau.pw',
|
60
|
+
'biz.ni',
|
61
|
+
'com.ph',
|
62
|
+
'com.ws',
|
63
|
+
'co.pw',
|
64
|
+
'df.gov.br',
|
65
|
+
'ed.pw',
|
66
|
+
'edu.ee',
|
67
|
+
'edu.ps',
|
68
|
+
'edu.ws',
|
69
|
+
'gob.ni',
|
70
|
+
'go.pw',
|
71
|
+
'int.la',
|
72
|
+
'int.ni',
|
73
|
+
'lib.ee',
|
74
|
+
'mil.ph',
|
75
|
+
'mobi.tt',
|
76
|
+
'music',
|
77
|
+
'net.ph',
|
78
|
+
'net.ws',
|
79
|
+
'ngo.ph',
|
80
|
+
'nom.za',
|
81
|
+
'org.ee',
|
82
|
+
'org.ph',
|
83
|
+
'org.ws',
|
84
|
+
'or.pw',
|
85
|
+
'plo.ps',
|
86
|
+
'ph',
|
87
|
+
'vg',
|
88
|
+
'ws',
|
89
|
+
'გე',
|
90
|
+
'عرب',
|
91
|
+
'中国',
|
92
|
+
'中國',
|
93
|
+
'公司.cn',
|
94
|
+
'政府',
|
95
|
+
'網絡.cn',
|
96
|
+
'网络.cn'
|
97
|
+
]
|
98
|
+
|
99
|
+
# The public suffix list.
|
100
|
+
#
|
101
|
+
# @return [Ronin::Support::Network::PublicSuffixList]
|
102
|
+
attr_reader :public_suffix_list
|
103
|
+
|
104
|
+
#
|
105
|
+
# Initializes the DNS suffix enum worker.
|
106
|
+
#
|
107
|
+
# @param [Hash{Symbol => Object}] kwargs
|
108
|
+
# Additional keyword arguments.
|
109
|
+
#
|
110
|
+
def initialize(**kwargs)
|
111
|
+
super(**kwargs)
|
112
|
+
|
113
|
+
@public_suffix_list = Support::Network::PublicSuffix.list
|
114
|
+
end
|
115
|
+
|
116
|
+
#
|
117
|
+
# Bruteforce resolves the other domains with different suffixes for the
|
118
|
+
# given domain.
|
119
|
+
#
|
120
|
+
# @param [Values::Domain] domain
|
121
|
+
# The domain name to bruteforce.
|
122
|
+
#
|
123
|
+
# @yield [new_domain]
|
124
|
+
# Each new domain with a different public suffix.
|
125
|
+
#
|
126
|
+
# @yieldparam [Values::Domain] new_domain
|
127
|
+
# A valid domain with a different suffix.
|
128
|
+
#
|
129
|
+
def process(domain)
|
130
|
+
queue = Async::LimitedQueue.new(params[:concurrency])
|
131
|
+
|
132
|
+
domain_name, orig_suffix = @public_suffix_list.split(domain.name)
|
133
|
+
|
134
|
+
Async do |task|
|
135
|
+
task.async do
|
136
|
+
public_suffixes = @public_suffix_list.non_wildcards.icann.reject do |suffix|
|
137
|
+
BAD_SUFFIXES.include?(suffix.name)
|
138
|
+
end
|
139
|
+
|
140
|
+
public_suffixes.each do |suffix|
|
141
|
+
unless suffix.name == orig_suffix
|
142
|
+
queue << "#{domain_name}.#{suffix.name}"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# send stop messages for each sub-task
|
147
|
+
params[:concurrency].times do
|
148
|
+
queue << nil
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# spawn the sub-tasks
|
153
|
+
params[:concurrency].times do
|
154
|
+
task.async do
|
155
|
+
while (new_domain = queue.dequeue)
|
156
|
+
if dns_get_address(new_domain)
|
157
|
+
yield Domain.new(new_domain)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-recon - A micro-framework and tool for performing reconnaissance.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-recon is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-recon is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-recon. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/recon/worker'
|
22
|
+
require 'ronin/support/network/ip_range'
|
23
|
+
|
24
|
+
module Ronin
|
25
|
+
module Recon
|
26
|
+
module Net
|
27
|
+
#
|
28
|
+
# A recon worker that enumerates every IP address within an IP range.
|
29
|
+
#
|
30
|
+
class IPRangeEnum < Worker
|
31
|
+
|
32
|
+
register 'net/ip_range_enum'
|
33
|
+
|
34
|
+
summary 'Enumerates the IP addresses in an IP range'
|
35
|
+
|
36
|
+
description <<~DESC
|
37
|
+
Enumerates over every IP address in a CIDR IP range.
|
38
|
+
DESC
|
39
|
+
|
40
|
+
accepts IPRange
|
41
|
+
outputs IP
|
42
|
+
intensity :passive
|
43
|
+
|
44
|
+
#
|
45
|
+
# Enumerates an IP range.
|
46
|
+
#
|
47
|
+
# @param [Values::IPRange] ip_range
|
48
|
+
# The IP range value.
|
49
|
+
#
|
50
|
+
# @yield [ip]
|
51
|
+
# Each IP value within the IP range will be yielded.
|
52
|
+
#
|
53
|
+
# @yieldparam [Values::IP] ip
|
54
|
+
# An IP value.
|
55
|
+
#
|
56
|
+
def process(ip_range)
|
57
|
+
ip_range.range.each do |address|
|
58
|
+
yield IP.new(address)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-recon - A micro-framework and tool for performing reconnaissance.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-recon is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-recon is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-recon. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/recon/worker'
|
22
|
+
|
23
|
+
require 'ronin/nmap'
|
24
|
+
|
25
|
+
module Ronin
|
26
|
+
module Recon
|
27
|
+
module Net
|
28
|
+
#
|
29
|
+
# A recon worker that performs a nmap port scan.
|
30
|
+
#
|
31
|
+
class PortScan < Worker
|
32
|
+
|
33
|
+
register 'net/port_scan'
|
34
|
+
|
35
|
+
summary 'Scans an IP for open ports'
|
36
|
+
|
37
|
+
description <<~DESC
|
38
|
+
Performs a nmap port scan of the given IP and retruns the open
|
39
|
+
ports and their services.
|
40
|
+
DESC
|
41
|
+
|
42
|
+
accepts IP
|
43
|
+
outputs OpenPort
|
44
|
+
|
45
|
+
param :ports, String, desc: 'Optional port list to scan'
|
46
|
+
|
47
|
+
#
|
48
|
+
# Performs an nmap port scan on the given IP value.
|
49
|
+
#
|
50
|
+
# @param [Values::IP] ip
|
51
|
+
# The given IP to scan.
|
52
|
+
#
|
53
|
+
# @yield [new_value]
|
54
|
+
# The discovered open ports will be yielded.
|
55
|
+
#
|
56
|
+
# @yieldparam [Values::OpenPort] new_value
|
57
|
+
# A discovered open port.
|
58
|
+
#
|
59
|
+
def process(ip)
|
60
|
+
xml = Nmap.scan(ip.address, verbose: true,
|
61
|
+
service_scan: true,
|
62
|
+
ports: params[:ports])
|
63
|
+
|
64
|
+
address = ip.address
|
65
|
+
host = ip.host || xml.host.to_s
|
66
|
+
|
67
|
+
xml.host.open_ports.each do |open_port|
|
68
|
+
number = open_port.number
|
69
|
+
protocol = open_port.protocol
|
70
|
+
service = open_port.service
|
71
|
+
|
72
|
+
yield OpenPort.new(
|
73
|
+
address,number, host: host,
|
74
|
+
protocol: protocol,
|
75
|
+
service: service && service.name,
|
76
|
+
ssl: service && service.ssl?
|
77
|
+
)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-recon - A micro-framework and tool for performing reconnaissance.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-recon is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-recon is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-recon. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/recon/worker'
|
22
|
+
|
23
|
+
module Ronin
|
24
|
+
module Recon
|
25
|
+
module Net
|
26
|
+
#
|
27
|
+
# A recon worker that identifies services on open ports.
|
28
|
+
#
|
29
|
+
class ServiceID < Worker
|
30
|
+
|
31
|
+
register 'net/service_id'
|
32
|
+
|
33
|
+
summary 'Identifies services running on open ports'
|
34
|
+
|
35
|
+
description <<~DESC
|
36
|
+
Identifies various services that are running on open ports.
|
37
|
+
DESC
|
38
|
+
|
39
|
+
accepts OpenPort
|
40
|
+
outputs Nameserver, Mailserver, Website
|
41
|
+
intensity :passive
|
42
|
+
|
43
|
+
#
|
44
|
+
# Identifies the service running on an open port.
|
45
|
+
#
|
46
|
+
# @param [Values::OpenPort] open_port
|
47
|
+
# The given open port.
|
48
|
+
#
|
49
|
+
# @yield [new_value]
|
50
|
+
# The identified service will be yielded.
|
51
|
+
#
|
52
|
+
# @yieldparam [Values::Nameserver, Values::Mailserver, Values::Website] new_value
|
53
|
+
# A discovered nameserver, mailserver, or website.
|
54
|
+
#
|
55
|
+
def process(open_port)
|
56
|
+
case open_port.service
|
57
|
+
when 'domain'
|
58
|
+
yield Nameserver.new(open_port.host)
|
59
|
+
when 'smtp'
|
60
|
+
yield Mailserver.new(open_port.host)
|
61
|
+
when 'http'
|
62
|
+
if open_port.ssl?
|
63
|
+
yield Website.https(open_port.host,open_port.number)
|
64
|
+
else
|
65
|
+
yield Website.http(open_port.host,open_port.number)
|
66
|
+
end
|
67
|
+
when 'https'
|
68
|
+
yield Website.https(open_port.host,open_port.number)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-recon - A micro-framework and tool for performing reconnaissance.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-recon is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-recon is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-recon. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/recon/worker'
|
22
|
+
require 'ronin/recon/value/parser'
|
23
|
+
|
24
|
+
require 'async/io'
|
25
|
+
|
26
|
+
module Ronin
|
27
|
+
module Recon
|
28
|
+
module SSL
|
29
|
+
#
|
30
|
+
# A recon worker that enumerates over the host names within the SSL/TLS
|
31
|
+
# certificate.
|
32
|
+
#
|
33
|
+
class CertEnum < Worker
|
34
|
+
|
35
|
+
register 'ssl/cert_enum'
|
36
|
+
|
37
|
+
summary 'Enumerates over the host names within a SSL/TLS certificate'
|
38
|
+
|
39
|
+
description <<~DESC
|
40
|
+
Enumerates over the subject CommonName and subjectAltNames of a
|
41
|
+
SSL/TLS certificate.
|
42
|
+
DESC
|
43
|
+
|
44
|
+
accepts Cert
|
45
|
+
outputs Domain, Host, Wildcard, EmailAddress
|
46
|
+
|
47
|
+
#
|
48
|
+
# Grabs the TLS certificate from the open port, if it supports SSL/TLS.
|
49
|
+
#
|
50
|
+
# @param [Values::Cert] cert
|
51
|
+
# The SSL/TLS certificate.
|
52
|
+
#
|
53
|
+
# @yield [name]
|
54
|
+
# All host names, wildcard host names, IP addresses, or email
|
55
|
+
# addresses, from the SSL/TLS certificate will be yielded.
|
56
|
+
#
|
57
|
+
# @yieldparam [Values::Host, Values::Wildcard, Values::IP, Values::EmailAddress] name
|
58
|
+
# A host name, wildcard host name, IP address, or email address from
|
59
|
+
# the certificate.
|
60
|
+
#
|
61
|
+
def process(cert)
|
62
|
+
subject_entries = cert.subject.to_a
|
63
|
+
subject_entries.each do |entry|
|
64
|
+
case entry[0]
|
65
|
+
when 'CN' # Common Name
|
66
|
+
case entry[1]
|
67
|
+
when Value::Parser::DOMAIN_REGEX
|
68
|
+
yield Domain.new(entry[1])
|
69
|
+
when Value::Parser::HOSTNAME_REGEX
|
70
|
+
yield Host.new(entry[1])
|
71
|
+
end
|
72
|
+
when 'emailAddress'
|
73
|
+
yield EmailAddress.new(entry[1])
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
subject_alt_names = cert.extensions.find do |ext|
|
78
|
+
ext.oid == 'subjectAltName'
|
79
|
+
end
|
80
|
+
|
81
|
+
if subject_alt_names
|
82
|
+
values = subject_alt_names.value.split(', ')
|
83
|
+
|
84
|
+
values.each do |string|
|
85
|
+
name, value = string.split(':',2)
|
86
|
+
|
87
|
+
case name
|
88
|
+
when 'DNS'
|
89
|
+
case value
|
90
|
+
when Value::Parser::DOMAIN_REGEX
|
91
|
+
yield Domain.new(value)
|
92
|
+
when Value::Parser::HOSTNAME_REGEX
|
93
|
+
yield Host.new(value)
|
94
|
+
when Value::Parser::WILDCARD_REGEX
|
95
|
+
yield Wildcard.new(value)
|
96
|
+
end
|
97
|
+
when 'IP'
|
98
|
+
yield IP.new(value)
|
99
|
+
when 'email'
|
100
|
+
yield EmailAddress.new(value)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-recon - A micro-framework and tool for performing reconnaissance.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-recon is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-recon is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-recon. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/recon/worker'
|
22
|
+
|
23
|
+
require 'async/io'
|
24
|
+
|
25
|
+
module Ronin
|
26
|
+
module Recon
|
27
|
+
module SSL
|
28
|
+
#
|
29
|
+
# A recon worker that grabs the SSL/TLS certificate from open ports that
|
30
|
+
# use SSL/TLS.
|
31
|
+
#
|
32
|
+
class CertGrab < Worker
|
33
|
+
|
34
|
+
register 'ssl/cert_grab'
|
35
|
+
|
36
|
+
summary 'Fetches the SSL/TLS certificate from an open port'
|
37
|
+
|
38
|
+
description <<~DESC
|
39
|
+
Grabs and decodes the X509 SSL/TLS peer certificate from an open port
|
40
|
+
which supports SSL/TLS.
|
41
|
+
DESC
|
42
|
+
|
43
|
+
accepts OpenPort
|
44
|
+
outputs Cert
|
45
|
+
|
46
|
+
#
|
47
|
+
# Grabs the TLS certificate from the open port, if it supports SSL/TLS.
|
48
|
+
#
|
49
|
+
# @param [Values::OpenPort] open_port
|
50
|
+
# The open port value to check.
|
51
|
+
#
|
52
|
+
# @yield [cert]
|
53
|
+
# If the open port supports SSL/TLS, then a certificate value will be
|
54
|
+
# yielded.
|
55
|
+
#
|
56
|
+
# @yieldparam [Values::Cert] cert
|
57
|
+
# The grabbed certificate value.
|
58
|
+
#
|
59
|
+
def process(open_port)
|
60
|
+
if open_port.ssl?
|
61
|
+
address = open_port.address
|
62
|
+
port = open_port.number
|
63
|
+
endpoint = Async::IO::Endpoint.ssl(address,port)
|
64
|
+
|
65
|
+
endpoint.connect do |socket|
|
66
|
+
peer_cert = socket.peer_cert
|
67
|
+
|
68
|
+
yield Cert.new(peer_cert)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-recon - A micro-framework and tool for performing reconnaissance.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-recon is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-recon is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-recon. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/recon/worker'
|
22
|
+
|
23
|
+
require 'async/http/internet/instance'
|
24
|
+
|
25
|
+
module Ronin
|
26
|
+
module Recon
|
27
|
+
module SSL
|
28
|
+
#
|
29
|
+
# A recon worker that returns host from each domains certificate
|
30
|
+
#
|
31
|
+
class CertSh < Worker
|
32
|
+
|
33
|
+
register 'ssl/cert_sh'
|
34
|
+
|
35
|
+
summary 'Queries cert.sh and returns host from each domains certificate.'
|
36
|
+
|
37
|
+
description <<~DESC
|
38
|
+
Queries cert.sh and returns host from each domains certificate.
|
39
|
+
DESC
|
40
|
+
|
41
|
+
accepts Domain
|
42
|
+
outputs Host
|
43
|
+
intensity :passive
|
44
|
+
|
45
|
+
#
|
46
|
+
# Returns host from each domains certificate.
|
47
|
+
#
|
48
|
+
# @param [Values::Domain] domain
|
49
|
+
# The domain value to check.
|
50
|
+
#
|
51
|
+
# @yield [host]
|
52
|
+
# If the domain has certificates, then a host value will be
|
53
|
+
# yielded.
|
54
|
+
#
|
55
|
+
# @yieldparam [Values::Host] host
|
56
|
+
# The host from certificate.
|
57
|
+
#
|
58
|
+
def process(domain)
|
59
|
+
Async do
|
60
|
+
internet = Async::HTTP::Internet.instance
|
61
|
+
path = "https://crt.sh/?dNSName=#{domain}&exclude=expired&output=json"
|
62
|
+
|
63
|
+
response = internet.get(path)
|
64
|
+
certs = JSON.parse(response.read, symbolize_names: true)
|
65
|
+
|
66
|
+
certs.each do |cert|
|
67
|
+
if (common_name = cert[:common_name])
|
68
|
+
yield Host.new(common_name)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|