ronin-recon 0.1.0.rc1 → 0.1.0.rc2

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/data/completions/ronin-recon +17 -17
  4. data/data/wordlists/raft-small-directories.txt.gz +0 -0
  5. data/data/wordlists/subdomains-1000.txt.gz +0 -0
  6. data/lib/ronin/recon/builtin/{ssl/cert_sh.rb → api/crt_sh.rb} +33 -10
  7. data/lib/ronin/recon/builtin/dns/subdomain_enum.rb +1 -0
  8. data/lib/ronin/recon/builtin/net/service_id.rb +1 -1
  9. data/lib/ronin/recon/builtin/ssl/cert_grab.rb +12 -4
  10. data/lib/ronin/recon/builtin/web/dir_enum.rb +13 -6
  11. data/lib/ronin/recon/builtin/web/email_addresses.rb +10 -5
  12. data/lib/ronin/recon/cli/commands/run.rb +7 -7
  13. data/lib/ronin/recon/cli/commands/test.rb +4 -1
  14. data/lib/ronin/recon/cli/printing.rb +19 -18
  15. data/lib/ronin/recon/config.rb +2 -2
  16. data/lib/ronin/recon/engine.rb +15 -15
  17. data/lib/ronin/recon/graph.rb +4 -4
  18. data/lib/ronin/recon/importer.rb +3 -3
  19. data/lib/ronin/recon/message/job_completed.rb +2 -2
  20. data/lib/ronin/recon/message/job_failed.rb +2 -2
  21. data/lib/ronin/recon/message/job_started.rb +2 -2
  22. data/lib/ronin/recon/mixins/http.rb +0 -1
  23. data/lib/ronin/recon/output_formats/dir.rb +2 -2
  24. data/lib/ronin/recon/output_formats/dot.rb +5 -5
  25. data/lib/ronin/recon/output_formats/graph_format.rb +2 -2
  26. data/lib/ronin/recon/output_formats/graphviz_format.rb +3 -3
  27. data/lib/ronin/recon/scope.rb +7 -3
  28. data/lib/ronin/recon/value_status.rb +3 -3
  29. data/lib/ronin/recon/values/domain.rb +4 -0
  30. data/lib/ronin/recon/values/email_address.rb +1 -1
  31. data/lib/ronin/recon/values/host.rb +4 -1
  32. data/lib/ronin/recon/values/ip.rb +1 -1
  33. data/lib/ronin/recon/values/ip_range.rb +1 -1
  34. data/lib/ronin/recon/values/open_port.rb +1 -1
  35. data/lib/ronin/recon/values/url.rb +2 -2
  36. data/lib/ronin/recon/values/website.rb +38 -10
  37. data/lib/ronin/recon/values/wildcard.rb +1 -1
  38. data/lib/ronin/recon/version.rb +1 -1
  39. data/lib/ronin/recon/worker.rb +3 -3
  40. data/man/ronin-recon-run.1 +1 -1
  41. data/man/ronin-recon-run.1.md +1 -1
  42. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a9c5f1341f2119335b680ceb29bed06bafa19a74664bacf71d4385ec2b517cb
4
- data.tar.gz: b0ba0ddde38138cb220ba5dc8b6a31005811622086b37ed51a1de5a3f80cc717
3
+ metadata.gz: d9353cb03516130e8ab2c0c672c9b989076eede3a91027e8442356550a9698fc
4
+ data.tar.gz: 85fd1b4795c9f776be9ac8c378279b4575e7d80ecc0407a092fec925c70614e9
5
5
  SHA512:
6
- metadata.gz: 9d6dac836e0943da2c2dc1478ce4bc557328811c4a9c4edb035462aaae0cfe3827f8b40acb7863a0ea61060c7f110a934e3f58ed5658decc776595064be664ba
7
- data.tar.gz: 13e2d6e10d7c38e70af52a616cc64f07b794d29535d80195d25e33c2e7f04430ef35964c557bcbfc65ac29177fde916141dc9f25fab261535ea590fc38498cd3
6
+ metadata.gz: b55e6f1ce78547f5bc1f5f7571033016ea35835975d87e83ced3ac9a1ce91606194512e42a67eafc40cb67d5179000880c89dd22b3b5f518be908771f50e9ed3
7
+ data.tar.gz: 8f3d6ebcb3b2a4547a21af4805d382349f597654d095a7df3b0d2d18ddf262f332221dc3f88a81b1d3f2a7d669e514bb2c44167e8655d11739e099192c0a15b6
data/README.md CHANGED
@@ -86,6 +86,7 @@ List all available recon workers:
86
86
 
87
87
  ```shell
88
88
  $ ronin-recon workers
89
+ api/crt_sh
89
90
  dns/lookup
90
91
  dns/mailservers
91
92
  dns/nameservers
@@ -95,7 +96,6 @@ $ ronin-recon workers
95
96
  dns/suffix_enum
96
97
  net/cert_enum
97
98
  net/cert_grab
98
- net/cert_sh
99
99
  net/ip_range_enum
100
100
  net/port_scan
101
101
  net/service_id
@@ -11,7 +11,7 @@ _ronin-recon_completions_filter() {
11
11
 
12
12
  if [[ "${cur:0:1}" == "-" ]]; then
13
13
  echo "$words"
14
-
14
+
15
15
  else
16
16
  for word in $words; do
17
17
  [[ "${word:0:1}" != "-" ]] && result+=("$word")
@@ -29,67 +29,67 @@ _ronin-recon_completions() {
29
29
 
30
30
  case "$compline" in
31
31
  'run'*'--config-file')
32
- while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -A file -- "$cur" )
32
+ while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")
33
33
  ;;
34
34
 
35
35
  'run'*'--worker-file')
36
- while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -A file -- "$cur" )
36
+ while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")
37
37
  ;;
38
38
 
39
39
  'worker'*'--file')
40
- while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -A file -- "$cur" )
40
+ while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")
41
41
  ;;
42
42
 
43
43
  'run'*'--output')
44
- while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -A file -- "$cur" )
44
+ while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")
45
45
  ;;
46
46
 
47
47
  'test'*'--file')
48
- while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -A file -- "$cur" )
48
+ while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")
49
49
  ;;
50
50
 
51
51
  'completion'*)
52
- while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_ronin-recon_completions_filter "--print --install --uninstall")" -- "$cur" )
52
+ while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_ronin-recon_completions_filter "--print --install --uninstall")" -- "$cur")
53
53
  ;;
54
54
 
55
55
  'worker'*'-f')
56
- while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -A file -- "$cur" )
56
+ while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")
57
57
  ;;
58
58
 
59
59
  'test'*'-f')
60
- while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -A file -- "$cur" )
60
+ while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")
61
61
  ;;
62
62
 
63
63
  'run'*'-C')
64
- while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -A file -- "$cur" )
64
+ while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")
65
65
  ;;
66
66
 
67
67
  'run'*'-o')
68
- while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -A file -- "$cur" )
68
+ while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -A file -- "$cur")
69
69
  ;;
70
70
 
71
71
  'worker'*)
72
- while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_ronin-recon_completions_filter "--file -f --verbose -v")" -- "$cur" )
72
+ while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_ronin-recon_completions_filter "--file -f --verbose -v")" -- "$cur")
73
73
  ;;
74
74
 
75
75
  'test'*)
76
- while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_ronin-recon_completions_filter "--file -f --debug -D --param -p")" -- "$cur" )
76
+ while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_ronin-recon_completions_filter "--file -f --debug -D --param -p")" -- "$cur")
77
77
  ;;
78
78
 
79
79
  'new'*)
80
- while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_ronin-recon_completions_filter "--type -t --author -a --author-email -e --summary -S --description -D --reference -R --accepts -A --outputs -O --intensity -I")" -- "$cur" )
80
+ while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_ronin-recon_completions_filter "--type -t --author -a --author-email -e --summary -S --description -D --reference -R --accepts -A --outputs -O --intensity -I")" -- "$cur")
81
81
  ;;
82
82
 
83
83
  'run'*)
84
- while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_ronin-recon_completions_filter "--debug -D --db --db-uri --db-file --config-file -C --worker -w --enable -e --disable -d --worker-file --param -p --concurrency -c --intensity --max-depth --output -o --output-format -F --import --ignore -I")" -- "$cur" )
84
+ while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_ronin-recon_completions_filter "--debug -D --db --db-uri --db-file --config-file -C --worker -w --enable -e --disable -d --worker-file --param -p --concurrency -c --intensity --max-depth --output -o --output-format -F --import --ignore -I")" -- "$cur")
85
85
  ;;
86
86
 
87
87
  *)
88
- while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(_ronin-recon_completions_filter "--version -V help completion irb new run test worker workers")" -- "$cur" )
88
+ while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen -W "$(_ronin-recon_completions_filter "--version -V help completion irb new run test worker workers")" -- "$cur")
89
89
  ;;
90
90
 
91
91
  esac
92
92
  } &&
93
- complete -F _ronin-recon_completions ronin-recon
93
+ complete -F _ronin-recon_completions ronin-recon
94
94
 
95
95
  # ex: filetype=sh
Binary file
@@ -24,23 +24,48 @@ require 'async/http/internet/instance'
24
24
 
25
25
  module Ronin
26
26
  module Recon
27
- module SSL
27
+ module API
28
28
  #
29
- # A recon worker that returns host from each domains certificate
29
+ # A recon worker that queries https://crt.sh and returns host from each
30
+ # domains certificate
30
31
  #
31
- class CertSh < Worker
32
+ class CrtSh < Worker
32
33
 
33
- register 'ssl/cert_sh'
34
+ register 'api/crt_sh'
34
35
 
35
- summary 'Queries cert.sh and returns host from each domains certificate.'
36
+ summary 'Queries https://crt.sh and returns host from each domains certificate.'
36
37
 
37
38
  description <<~DESC
38
- Queries cert.sh and returns host from each domains certificate.
39
+ Queries https://crt.sh and returns host from each domains certificate.
39
40
  DESC
40
41
 
41
42
  accepts Domain
42
43
  outputs Host
43
44
  intensity :passive
45
+ concurrency 1
46
+
47
+ # The HTTP client for `https://crt.sh`.
48
+ #
49
+ # @return [Async::HTTP::Client]
50
+ #
51
+ # @api private
52
+ attr_reader :client
53
+
54
+ #
55
+ # Initializes the `api/crt_sh` worker.
56
+ #
57
+ # @param [Hash{Symbol => Object}] kwargs
58
+ # Additional keyword arguments.
59
+ #
60
+ # @api private
61
+ #
62
+ def initialize(**kwargs)
63
+ super(**kwargs)
64
+
65
+ @client = Async::HTTP::Client.new(
66
+ Async::HTTP::Endpoint.for('https','crt.sh')
67
+ )
68
+ end
44
69
 
45
70
  #
46
71
  # Returns host from each domains certificate.
@@ -57,10 +82,8 @@ module Ronin
57
82
  #
58
83
  def process(domain)
59
84
  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)
85
+ path = "/?dNSName=#{domain}&exclude=expired&output=json"
86
+ response = @client.get(path)
64
87
  certs = JSON.parse(response.read, symbolize_names: true)
65
88
 
66
89
  certs.each do |cert|
@@ -33,6 +33,7 @@ module Ronin
33
33
  #
34
34
  class SubdomainEnum < DNSWorker
35
35
 
36
+ # The path to the default common subdomains wordlist.
36
37
  DEFAULT_WORDLIST = File.join(WORDLISTS_DIR, 'subdomains-1000.txt.gz')
37
38
 
38
39
  register 'dns/subdomain_enum'
@@ -64,7 +64,7 @@ module Ronin
64
64
  else
65
65
  yield Website.http(open_port.host,open_port.number)
66
66
  end
67
- when 'https'
67
+ when 'https', 'https-alt'
68
68
  yield Website.https(open_port.host,open_port.number)
69
69
  end
70
70
  end
@@ -58,14 +58,22 @@ module Ronin
58
58
  #
59
59
  def process(open_port)
60
60
  if open_port.ssl?
61
+ context = OpenSSL::SSL::SSLContext.new
62
+
63
+ context.verify_mode = OpenSSL::SSL::VERIFY_NONE
64
+
61
65
  address = open_port.address
62
66
  port = open_port.number
63
- endpoint = Async::IO::Endpoint.ssl(address,port)
67
+ endpoint = Async::IO::Endpoint.ssl(address,port, ssl_context: context)
64
68
 
65
- endpoint.connect do |socket|
66
- peer_cert = socket.peer_cert
69
+ begin
70
+ endpoint.connect do |socket|
71
+ peer_cert = socket.peer_cert
67
72
 
68
- yield Cert.new(peer_cert)
73
+ yield Cert.new(peer_cert)
74
+ end
75
+ rescue OpenSSL::SSL::SSLError
76
+ # abort if we cannot successfully establish a SSL/TLS connection
69
77
  end
70
78
  end
71
79
  end
@@ -69,6 +69,9 @@ module Ronin
69
69
  def process(website)
70
70
  wordlist = Wordlist.open(params[:wordlist] || DEFAULT_WORDLIST)
71
71
  queue = Async::LimitedQueue.new(params[:concurrency])
72
+ endpoint = Async::HTTP::Endpoint.for(
73
+ website.scheme, website.host, port: website.port
74
+ )
72
75
  base_url = website.to_s
73
76
 
74
77
  Async do |task|
@@ -83,19 +86,23 @@ module Ronin
83
86
  # spawn the sub-tasks
84
87
  params[:concurrency].times do
85
88
  task.async do
86
- http = Async::HTTP::Internet.instance
89
+ http = Async::HTTP::Client.new(endpoint)
87
90
 
88
91
  while (dir = queue.dequeue)
89
92
  path = "/#{URI.encode_uri_component(dir)}"
90
- url = "#{base_url}#{path}"
91
93
  retries = 0
92
94
 
93
95
  begin
94
- response = http.head(url)
96
+ response = http.head(path)
97
+ status = response.status
95
98
 
96
- if VALID_STATUS_CODES.include?(response.status)
97
- yield URL.new(url, status: response.status,
98
- headers: response.headers)
99
+ if VALID_STATUS_CODES.include?(status)
100
+ headers = response.headers.to_h
101
+
102
+ yield URL.new(
103
+ "#{base_url}#{path}", status: status,
104
+ headers: headers
105
+ )
99
106
  end
100
107
  rescue Errno::ECONNREFUSED,
101
108
  SocketError
@@ -55,12 +55,17 @@ module Ronin
55
55
  # Email address found on the page.
56
56
  #
57
57
  def process(url)
58
- return nil unless url.body
58
+ if (body = url.body)
59
+ if body.encoding == Encoding::ASCII_8BIT
60
+ # forcibly convert and scrub binary data into UTF-8 data
61
+ body = body.dup
62
+ body.force_encoding(Encoding::UTF_8)
63
+ body.scrub!
64
+ end
59
65
 
60
- email_pattern = Ronin::Support::Text::Patterns::EMAIL_ADDRESS
61
-
62
- url.body.force_encoding(Encoding::UTF_8).scan(email_pattern) do |email|
63
- yield EmailAddress.new(email)
66
+ body.scan(Support::Text::Patterns::EMAIL_ADDRESS) do |email|
67
+ yield EmailAddress.new(email)
68
+ end
64
69
  end
65
70
  end
66
71
 
@@ -50,7 +50,7 @@ module Ronin
50
50
  # --worker-file FILE Loads a worker from a file
51
51
  # -p, --param WORKER.NAME=VALUE Sets a param for a worker
52
52
  # -c, --concurrency WORKER=NUM Sets the concurrency of a worker
53
- # --max-depth NUM The maximum recon depth (Default: 3)
53
+ # --max-depth NUM The maximum recon depth (Default: 10)
54
54
  # -o, --output FILE The output file to write results to
55
55
  # -I, --ignore VALUE The values to ignore in result
56
56
  # -F txt|list|csv|json|ndjson|dot|svg|png|pdf,
@@ -144,7 +144,7 @@ module Ronin
144
144
  option :max_depth, value: {
145
145
  type: Integer,
146
146
  usage: 'NUM',
147
- default: 3
147
+ default: 10
148
148
  },
149
149
  desc: 'The maximum recon depth'
150
150
 
@@ -226,7 +226,7 @@ module Ronin
226
226
 
227
227
  # The values that are out of scope.
228
228
  #
229
- # @return [Array<Values::Value>]
229
+ # @return [Array<Value>]
230
230
  attr_reader :ignore
231
231
 
232
232
  #
@@ -318,7 +318,7 @@ module Ronin
318
318
  # @param [String] value
319
319
  # The value to parse.
320
320
  #
321
- # @return [Values::Value]
321
+ # @return [Value]
322
322
  # The parsed value.
323
323
  #
324
324
  def parse_value(value)
@@ -393,7 +393,7 @@ module Ronin
393
393
  #
394
394
  # Imports a discovered value into ronin-db.
395
395
  #
396
- # @param [Values::Value] value
396
+ # @param [Value] value
397
397
  # A discovered recon value to import.
398
398
  #
399
399
  def import_value(value)
@@ -403,10 +403,10 @@ module Ronin
403
403
  #
404
404
  # Imports a connection between two values into ronin-db.
405
405
  #
406
- # @param [Values::Value] value
406
+ # @param [Value] value
407
407
  # A discovered recon value to import.
408
408
  #
409
- # @param [Values::Value] parent
409
+ # @param [Value] parent
410
410
  # The parent value of the discovered recon value.
411
411
  #
412
412
  def import_connection(value,parent)
@@ -54,7 +54,7 @@ module Ronin
54
54
  include Core::CLI::Logging
55
55
  include Core::CLI::Options::Param
56
56
 
57
- usage '[options] {IP | IP-range | DOMAIN | HOST | WILDCARD | WEBSITE}'
57
+ usage '[options] {--file FILE | NAME} {IP | IP-range | DOMAIN | HOST | WILDCARD | WEBSITE}'
58
58
 
59
59
  argument :value, required: true,
60
60
  usage: 'IP|IP-range|DOMAIN|HOST|WILDCARD|WEBSITE',
@@ -70,6 +70,9 @@ module Ronin
70
70
  # @param [String, nil] name
71
71
  # The optional worker name to load and print metadata for.
72
72
  #
73
+ # @param [String] value
74
+ # The input value for the worker.
75
+ #
73
76
  def run(name=nil,value)
74
77
  super(name)
75
78
 
@@ -33,17 +33,17 @@ module Ronin
33
33
  # Mapping of {Value} classes to printable names.
34
34
  VALUE_CLASS_NAMES = {
35
35
  Values::Domain => 'domain',
36
+ Values::Mailserver => 'mailserver',
37
+ Values::Nameserver => 'nameserver',
38
+ Values::Wildcard => 'wildcard host name',
36
39
  Values::Host => 'host',
37
40
  Values::IP => 'IP address',
38
41
  Values::IPRange => 'IP range',
39
- Values::Mailserver => 'mailserver',
40
- Values::Nameserver => 'nameserver',
41
42
  Values::OpenPort => 'open port',
42
43
  Values::Cert => 'SSL/TLS certificate',
43
- Values::EmailAddress => 'email addresse',
44
- Values::URL => 'URL',
45
44
  Values::Website => 'website',
46
- Values::Wildcard => 'wildcard host name'
45
+ Values::URL => 'URL',
46
+ Values::EmailAddress => 'email addresse'
47
47
  }
48
48
 
49
49
  #
@@ -66,7 +66,7 @@ module Ronin
66
66
  #
67
67
  # Formats a value object into a human readable string.
68
68
  #
69
- # @param [Values::Value] value
69
+ # @param [Value] value
70
70
  # The value object to format.
71
71
  #
72
72
  # @return [String]
@@ -77,17 +77,18 @@ module Ronin
77
77
  #
78
78
  def format_value(value)
79
79
  case value
80
- when Values::Domain then "domain #{value}"
81
- when Values::Mailserver then "mailserver #{value}"
82
- when Values::Nameserver then "nameserver #{value}"
83
- when Values::Host then "host #{value}"
84
- when Values::IP then "IP address #{value}"
85
- when Values::IPRange then "IP range #{value}"
86
- when Values::OpenPort then "open #{value.protocol.upcase} port #{value}"
87
- when Values::Cert then "SSL/TLS certificate #{value.subject}"
88
- when Values::URL then "URL #{value}"
89
- when Values::Website then "website #{value}"
90
- when Values::Wildcard then "wildcard host name #{value}"
80
+ when Values::Domain then "domain #{value}"
81
+ when Values::Mailserver then "mailserver #{value}"
82
+ when Values::Nameserver then "nameserver #{value}"
83
+ when Values::Wildcard then "wildcard host name #{value}"
84
+ when Values::Host then "host #{value}"
85
+ when Values::IP then "IP address #{value}"
86
+ when Values::IPRange then "IP range #{value}"
87
+ when Values::OpenPort then "open #{value.protocol.upcase} port #{value}"
88
+ when Values::Cert then "SSL/TLS certificate #{value.subject}"
89
+ when Values::Website then "website #{value}"
90
+ when Values::URL then "URL #{value}"
91
+ when Values::EmailAddress then "email address #{value}"
91
92
  else
92
93
  raise(NotImplementedError,"value class #{value.class} not supported")
93
94
  end
@@ -96,7 +97,7 @@ module Ronin
96
97
  #
97
98
  # Prints a newly discovered value.
98
99
  #
99
- # @param [Values::Value] value
100
+ # @param [Value] value
100
101
  # The value to print.
101
102
  #
102
103
  # @param [Value, nil] parent
@@ -72,6 +72,8 @@ module Ronin
72
72
 
73
73
  # The default workers configuration.
74
74
  DEFAULT = Set[
75
+ # NOTE: disabled due to rate limiting issues
76
+ # 'api/crt_sh',
75
77
  'dns/lookup',
76
78
  'dns/mailservers',
77
79
  'dns/nameservers',
@@ -84,8 +86,6 @@ module Ronin
84
86
  'net/service_id',
85
87
  'ssl/cert_grab',
86
88
  'ssl/cert_enum',
87
- # NOTE: disabled due to rate limiting issues
88
- # 'ssl/cert_sh',
89
89
  'web/dir_enum',
90
90
  'web/email_addresses',
91
91
  'web/spider'
@@ -88,10 +88,10 @@ module Ronin
88
88
  #
89
89
  # Initializes the recon engine.
90
90
  #
91
- # @param [Array<Values::Value>] values
91
+ # @param [Array<Value>] values
92
92
  # The values to start performing recon on.
93
93
  #
94
- # @param [Array<Values::Value>] ignore
94
+ # @param [Array<Value>] ignore
95
95
  # The values to ignore while performing recon.
96
96
  #
97
97
  # @param [Integer, nil] max_depth
@@ -118,7 +118,7 @@ module Ronin
118
118
  # @yieldparam [Engine] self
119
119
  # The newly initialized engine.
120
120
  #
121
- # @yieldparam [Values::Value] parent
121
+ # @yieldparam [Value] parent
122
122
  # The parent value which is associated to the discovered value.
123
123
  #
124
124
  # @api public
@@ -186,10 +186,10 @@ module Ronin
186
186
  # If the block accepts two arguments the value and it's parent value
187
187
  # will be passed to the block.
188
188
  #
189
- # @yieldparam [Values::Value] value
189
+ # @yieldparam [Value] value
190
190
  # A value discovered by one of the recon workers.
191
191
  #
192
- # @yieldparam [Values::Value] parent
192
+ # @yieldparam [Value] parent
193
193
  # The parent value which is associated to the discovered value.
194
194
  #
195
195
  # @return [Engine]
@@ -293,10 +293,10 @@ module Ronin
293
293
  # If `:job_failed` is given, then any exception raised by a worker will
294
294
  # be passed to the given block.
295
295
  #
296
- # @yieldparam [Values::Value] value
296
+ # @yieldparam [Value] value
297
297
  # A discovered value value.
298
298
  #
299
- # @yieldparam [Values::Value] parent
299
+ # @yieldparam [Value] parent
300
300
  # The parent value of the value.
301
301
  #
302
302
  # @yieldparam [Class<Worker>] worker_class
@@ -327,7 +327,7 @@ module Ronin
327
327
  # @param [Worker] worker
328
328
  # The worker that is processing the value.
329
329
  #
330
- # @param [Values::Value] value
330
+ # @param [Value] value
331
331
  # The value that is being processed.
332
332
  #
333
333
  # @api private
@@ -344,7 +344,7 @@ module Ronin
344
344
  # @param [Worker] worker
345
345
  # The worker that processed the value.
346
346
  #
347
- # @param [Values::Value] value
347
+ # @param [Value] value
348
348
  # The value that was processed.
349
349
  #
350
350
  # @api private
@@ -361,7 +361,7 @@ module Ronin
361
361
  # @param [Worker] worker
362
362
  # The worker that raised the exception.
363
363
  #
364
- # @param [Values::Value] value
364
+ # @param [Value] value
365
365
  # The value that was being processed.
366
366
  #
367
367
  # @param [RuntimeError] exception
@@ -381,10 +381,10 @@ module Ronin
381
381
  # @param [Worker] worker
382
382
  # The worker that discovered the value.
383
383
  #
384
- # @param [Values::Value] value
384
+ # @param [Value] value
385
385
  # The newly discovered value.
386
386
  #
387
- # @param [Values::Value] parent
387
+ # @param [Value] parent
388
388
  # The parent value associated with the new value.
389
389
  #
390
390
  # @api private
@@ -405,10 +405,10 @@ module Ronin
405
405
  # @param [Worker] worker
406
406
  # The worker that discovered the value.
407
407
  #
408
- # @param [Values::Value] value
408
+ # @param [Value] value
409
409
  # The discovered value.
410
410
  #
411
- # @param [Values::Value] parent
411
+ # @param [Value] parent
412
412
  # The parent value associated with the value.
413
413
  #
414
414
  # @api private
@@ -610,7 +610,7 @@ module Ronin
610
610
  #
611
611
  # Sends a new value into the recon engine for processing.
612
612
  #
613
- # @param [Values::Value] value
613
+ # @param [Value] value
614
614
  # The value object to enqueue.
615
615
  #
616
616
  # @api private
@@ -50,7 +50,7 @@ module Ronin
50
50
  #
51
51
  # Adds a value to the graph, if it already hasn't been added.
52
52
  #
53
- # @param [Values::Value] new_value
53
+ # @param [Value] new_value
54
54
  # The new value node to add.
55
55
  #
56
56
  # @return [Boolean]
@@ -66,7 +66,7 @@ module Ronin
66
66
  #
67
67
  # Adds a value to the graph, if it already hasn't been added.
68
68
  #
69
- # @param [Values::Value] new_value
69
+ # @param [Value] new_value
70
70
  # The new value node to add.
71
71
  #
72
72
  # @param [Value, nil] parent_value
@@ -89,7 +89,7 @@ module Ronin
89
89
  #
90
90
  # Determines if the value is in the graph.
91
91
  #
92
- # @param [Values::Value] value
92
+ # @param [Value] value
93
93
  # The value node.
94
94
  #
95
95
  # @return [Boolean]
@@ -102,7 +102,7 @@ module Ronin
102
102
  #
103
103
  # Fetches the parent value nodes for the value.
104
104
  #
105
- # @param [Values::Value] value
105
+ # @param [Value] value
106
106
  # The value node to lookup.
107
107
  #
108
108
  # @return [Set<Value>, nil]
@@ -49,10 +49,10 @@ module Ronin
49
49
  #
50
50
  # Imports the connection between two values.
51
51
  #
52
- # @param [Values::Value] value
52
+ # @param [Value] value
53
53
  # A discovered recon value to import.
54
54
  #
55
- # @param [Values::Value] parent
55
+ # @param [Value] parent
56
56
  # The parent value of the discovered recon value.
57
57
  #
58
58
  # @return [(Ronin::DB::Model, Ronin::DB::Model)]
@@ -78,7 +78,7 @@ module Ronin
78
78
  #
79
79
  # Imports a value into the database.
80
80
  #
81
- # @param [Values::Value] value
81
+ # @param [Value] value
82
82
  # A discovered recon value to import.
83
83
  #
84
84
  # @return [Ronin::DB::HostName,
@@ -35,7 +35,7 @@ module Ronin
35
35
 
36
36
  # The input value object.
37
37
  #
38
- # @return [Values::Value]
38
+ # @return [Value]
39
39
  attr_reader :value
40
40
 
41
41
  #
@@ -44,7 +44,7 @@ module Ronin
44
44
  # @param [Worker] worker
45
45
  # The worker object.
46
46
  #
47
- # @param [Values::Value] value
47
+ # @param [Value] value
48
48
  # The input value for the job.
49
49
  #
50
50
  def initialize(worker,value)
@@ -35,7 +35,7 @@ module Ronin
35
35
 
36
36
  # The input value object.
37
37
  #
38
- # @return [Values::Value]
38
+ # @return [Value]
39
39
  attr_reader :value
40
40
 
41
41
  # The exception.
@@ -49,7 +49,7 @@ module Ronin
49
49
  # @param [Worker] worker
50
50
  # The worker object.
51
51
  #
52
- # @param [Values::Value] value
52
+ # @param [Value] value
53
53
  # The input value object.
54
54
  #
55
55
  # @param [StandardError] exception
@@ -35,7 +35,7 @@ module Ronin
35
35
 
36
36
  # The input value object.
37
37
  #
38
- # @return [Values::Value]
38
+ # @return [Value]
39
39
  attr_reader :value
40
40
 
41
41
  #
@@ -44,7 +44,7 @@ module Ronin
44
44
  # @param [Worker] worker
45
45
  # The worker object.
46
46
  #
47
- # @param [Values::Value] value
47
+ # @param [Value] value
48
48
  # The input value object.
49
49
  #
50
50
  def initialize(worker,value)
@@ -43,7 +43,6 @@ module Ronin
43
43
  208, # Already Reported
44
44
  226, # IM Used
45
45
  405, # Method Not Allowed
46
- 406, # Not Acceptable
47
46
  409, # Conflict
48
47
  415, # Unsupported Media Type
49
48
  422, # Unprocessable Content
@@ -33,7 +33,7 @@ module Ronin
33
33
 
34
34
  # The opened filenames and files within the output directory.
35
35
  #
36
- # @return [Hash{Class<Values::Value> => File}]
36
+ # @return [Hash{Class<Value> => File}]
37
37
  attr_reader :files
38
38
 
39
39
  # Mapping of value classes to file names.
@@ -69,7 +69,7 @@ module Ronin
69
69
  #
70
70
  # Writes a new value to it's specific file.
71
71
  #
72
- # @param [Values::Value] value
72
+ # @param [Value] value
73
73
  # The value to write.
74
74
  #
75
75
  def <<(value)
@@ -60,7 +60,7 @@ module Ronin
60
60
  #
61
61
  # Returns the descriptive type name for the value object.
62
62
  #
63
- # @param [Values::Value] value
63
+ # @param [Value] value
64
64
  # The value object.
65
65
  #
66
66
  # @return [String]
@@ -91,7 +91,7 @@ module Ronin
91
91
  #
92
92
  # Returns the body text for the value object.
93
93
  #
94
- # @param [Values::Value] value
94
+ # @param [Value] value
95
95
  # The value object.
96
96
  #
97
97
  # @return [String]
@@ -112,7 +112,7 @@ module Ronin
112
112
  # Writes a value to the GraphViz DOT output stream as a node
113
113
  # declaration.
114
114
  #
115
- # @param [Values::Value] value
115
+ # @param [Value] value
116
116
  # The value object to write.
117
117
  #
118
118
  def <<(value)
@@ -127,10 +127,10 @@ module Ronin
127
127
  # Appends a value and it's parent value to the GraphViz DOT output
128
128
  # stream.
129
129
  #
130
- # @param [Values::Value] value
130
+ # @param [Value] value
131
131
  # The value to append.
132
132
  #
133
- # @param [Values::Value] parent
133
+ # @param [Value] parent
134
134
  # The parent value of the given value.
135
135
  #
136
136
  # @return [self]
@@ -29,10 +29,10 @@ module Ronin
29
29
  # Appends a value and it's parent value to the GraphViz DOT output
30
30
  # stream.
31
31
  #
32
- # @param [Values::Value] value
32
+ # @param [Value] value
33
33
  # The value to append.
34
34
  #
35
- # @param [Values::Value] parent
35
+ # @param [Value] parent
36
36
  # The parent value of the given value.
37
37
  #
38
38
  # @return [self]
@@ -72,7 +72,7 @@ module Ronin
72
72
  #
73
73
  # Writes a value to the GraphViz output stream as a node declaration.
74
74
  #
75
- # @param [Values::Value] value
75
+ # @param [Value] value
76
76
  # The value object to write.
77
77
  #
78
78
  def <<(value)
@@ -82,10 +82,10 @@ module Ronin
82
82
  #
83
83
  # Appends a value and it's parent value to the GraphViz output stream.
84
84
  #
85
- # @param [Values::Value] value
85
+ # @param [Value] value
86
86
  # The value to append.
87
87
  #
88
- # @param [Values::Value] parent
88
+ # @param [Value] parent
89
89
  # The parent value of the given value.
90
90
  #
91
91
  # @return [self]
@@ -23,6 +23,8 @@ require 'ronin/recon/values/domain'
23
23
  require 'ronin/recon/values/host'
24
24
  require 'ronin/recon/values/ip_range'
25
25
  require 'ronin/recon/values/ip'
26
+ require 'ronin/recon/values/url'
27
+ require 'ronin/recon/values/email_address'
26
28
 
27
29
  module Ronin
28
30
  module Recon
@@ -46,7 +48,7 @@ module Ronin
46
48
  #
47
49
  # Initializes the scope.
48
50
  #
49
- # @param [Array<Values::Wildcard, Values::Domain, Values::Host, Values::IPRange, Values::IP>] values
51
+ # @param [Array<Values::Wildcard, Values::Domain, Values::Host, Values::Website, Values::IPRange, Values::IP>] values
50
52
  # The list of "in scope" values.
51
53
  #
52
54
  # @param [Array<Value>] ignore
@@ -64,7 +66,7 @@ module Ronin
64
66
 
65
67
  values.each do |value|
66
68
  case value
67
- when Values::Wildcard, Values::Domain, Values::Host
69
+ when Values::Wildcard, Values::Domain, Values::Host, Values::Website
68
70
  @host_values << value
69
71
  when Values::IP, Values::IPRange
70
72
  @ip_values << value
@@ -91,7 +93,9 @@ module Ronin
91
93
  when Values::Wildcard,
92
94
  Values::Domain,
93
95
  Values::Host,
94
- Values::URL
96
+ Values::Website,
97
+ Values::URL,
98
+ Values::EmailAddress
95
99
  @host_values
96
100
  when Values::IP,
97
101
  Values::IPRange
@@ -34,7 +34,7 @@ module Ronin
34
34
  #
35
35
  # Records that a value was enqueued for the given worker class.
36
36
  #
37
- # @param [Values::Value] value
37
+ # @param [Value] value
38
38
  #
39
39
  # @param [Class<Worker>] worker_class
40
40
  #
@@ -45,7 +45,7 @@ module Ronin
45
45
  #
46
46
  # Records that a worker has dequeued the value and started processing it.
47
47
  #
48
- # @param [Values::Value] value
48
+ # @param [Value] value
49
49
  #
50
50
  # @param [Class<Worker>] worker_class
51
51
  #
@@ -56,7 +56,7 @@ module Ronin
56
56
  #
57
57
  # Records that a worker has completed processing the value.
58
58
  #
59
- # @param [Values::Value] value
59
+ # @param [Value] value
60
60
  #
61
61
  # @param [Class<Worker>] worker_class
62
62
  #
@@ -22,6 +22,7 @@ require 'ronin/recon/values/host'
22
22
  require 'ronin/recon/values/ip'
23
23
  require 'ronin/recon/values/website'
24
24
  require 'ronin/recon/values/url'
25
+ require 'ronin/recon/values/email_address'
25
26
 
26
27
  module Ronin
27
28
  module Recon
@@ -52,6 +53,9 @@ module Ronin
52
53
  if (other_host = other.host)
53
54
  other_host == @name || other_host.end_with?(".#{@name}")
54
55
  end
56
+ when EmailAddress
57
+ other.address.end_with?("@#{@name}") ||
58
+ other.address.end_with?(".#{@name}")
55
59
  else
56
60
  false
57
61
  end
@@ -48,7 +48,7 @@ module Ronin
48
48
  #
49
49
  # Compares the value to another value.
50
50
  #
51
- # @param [Values::Value] other
51
+ # @param [Value] other
52
52
  # The other value to compare.
53
53
  #
54
54
  # @return [Boolean]
@@ -22,6 +22,7 @@ require 'ronin/recon/value'
22
22
  require 'ronin/recon/values/ip'
23
23
  require 'ronin/recon/values/website'
24
24
  require 'ronin/recon/values/url'
25
+ require 'ronin/recon/values/email_address'
25
26
 
26
27
  module Ronin
27
28
  module Recon
@@ -51,7 +52,7 @@ module Ronin
51
52
  #
52
53
  # Compares the value to another value.
53
54
  #
54
- # @param [Values::Value] other
55
+ # @param [Value] other
55
56
  # The other value to compare.
56
57
  #
57
58
  # @return [Boolean]
@@ -79,6 +80,8 @@ module Ronin
79
80
  @name == other.name
80
81
  when IP, Website, URL
81
82
  @name == other.host
83
+ when EmailAddress
84
+ other.address.end_with?("@#{@name}")
82
85
  else
83
86
  false
84
87
  end
@@ -57,7 +57,7 @@ module Ronin
57
57
  #
58
58
  # Compares the value to another value.
59
59
  #
60
- # @param [Values::Value] other
60
+ # @param [Value] other
61
61
  # The other value to compare.
62
62
  #
63
63
  # @return [Boolean]
@@ -94,7 +94,7 @@ module Ronin
94
94
  #
95
95
  # Compares the value to another value.
96
96
  #
97
- # @param [Values::Value] other
97
+ # @param [Value] other
98
98
  #
99
99
  # @return [Boolean]
100
100
  #
@@ -105,7 +105,7 @@ module Ronin
105
105
  #
106
106
  # Compares the value to another value.
107
107
  #
108
- # @param [Values::Value] other
108
+ # @param [Value] other
109
109
  #
110
110
  # @return [Boolean]
111
111
  #
@@ -21,6 +21,7 @@
21
21
  require 'ronin/recon/value'
22
22
 
23
23
  require 'uri'
24
+ require 'base64'
24
25
 
25
26
  module Ronin
26
27
  module Recon
@@ -149,7 +150,7 @@ module Ronin
149
150
  #
150
151
  # Compares the value to another value.
151
152
  #
152
- # @param [Values::Value] other
153
+ # @param [Value] other
153
154
  #
154
155
  # @return [Boolean]
155
156
  #
@@ -192,7 +193,6 @@ module Ronin
192
193
 
193
194
  hash[:status] = @status if @status
194
195
  hash[:headers] = @headers if @headers
195
- hash[:body] = @body if @body
196
196
 
197
197
  return hash
198
198
  end
@@ -19,6 +19,8 @@
19
19
  #
20
20
 
21
21
  require 'ronin/recon/value'
22
+ require 'ronin/recon/values/url'
23
+ require 'ronin/recon/values/email_address'
22
24
 
23
25
  require 'uri'
24
26
 
@@ -34,7 +36,7 @@ module Ronin
34
36
 
35
37
  # Indicates whether the website uses `http://` or `https://`.
36
38
  #
37
- # @return [:http, :https]
39
+ # @return ['http', 'https']
38
40
  attr_reader :scheme
39
41
 
40
42
  # The website's host name.
@@ -50,7 +52,7 @@ module Ronin
50
52
  #
51
53
  # Initializes the website.
52
54
  #
53
- # @param [:http, :https] scheme
55
+ # @param ['http', 'https'] scheme
54
56
  # Indicates whether the website uses `http://` or `https://`.
55
57
  #
56
58
  # @param [String] host
@@ -78,7 +80,7 @@ module Ronin
78
80
  # The new website value.
79
81
  #
80
82
  def self.http(host,port=80)
81
- new(:http,host,port)
83
+ new('http',host,port)
82
84
  end
83
85
 
84
86
  #
@@ -94,7 +96,7 @@ module Ronin
94
96
  # The new website value.
95
97
  #
96
98
  def self.https(host,port=443)
97
- new(:https,host,port)
99
+ new('https',host,port)
98
100
  end
99
101
 
100
102
  #
@@ -109,13 +111,13 @@ module Ronin
109
111
  def self.parse(url)
110
112
  uri = URI.parse(url)
111
113
 
112
- Values::Website.new(uri.scheme.to_sym,uri.host,uri.port)
114
+ Values::Website.new(uri.scheme,uri.host,uri.port)
113
115
  end
114
116
 
115
117
  #
116
118
  # Compares the value to another value.
117
119
  #
118
- # @param [Values::Value] other
120
+ # @param [Value] other
119
121
  #
120
122
  # @return [Boolean]
121
123
  #
@@ -126,6 +128,32 @@ module Ronin
126
128
  @port == other.port
127
129
  end
128
130
 
131
+ #
132
+ # Case equality method used for fuzzy matching.
133
+ #
134
+ # @param [Value] other
135
+ # The other value to compare.
136
+ #
137
+ # @return [Boolean]
138
+ # Imdicates whether the other value is either the same {Website} or
139
+ # a {URL} with the same {#scheme}, {#host}, and {#port} as the
140
+ # website.
141
+ #
142
+ def ===(other)
143
+ case other
144
+ when Website
145
+ self == other
146
+ when URL
147
+ @scheme == other.scheme &&
148
+ @host == other.host &&
149
+ @port == other.port
150
+ when EmailAddress
151
+ other.address.end_with?("@#{@host}")
152
+ else
153
+ false
154
+ end
155
+ end
156
+
129
157
  #
130
158
  # The "hash" value of the wildcard host name.
131
159
  #
@@ -140,8 +168,8 @@ module Ronin
140
168
  #
141
169
  # @api private
142
170
  URI_CLASSES = {
143
- https: URI::HTTPS,
144
- http: URI::HTTP
171
+ 'https' => URI::HTTPS,
172
+ 'http' => URI::HTTP
145
173
  }
146
174
 
147
175
  #
@@ -161,8 +189,8 @@ module Ronin
161
189
  # The base URL value for the website.
162
190
  #
163
191
  def to_s
164
- if ((@scheme == :https) && (@port != 443)) ||
165
- ((@scheme == :http) && (@port != 80))
192
+ if ((@scheme == 'https') && (@port != 443)) ||
193
+ ((@scheme == 'http') && (@port != 80))
166
194
  "#{@scheme}://#{@host}:#{@port}"
167
195
  else
168
196
  "#{@scheme}://#{@host}"
@@ -52,7 +52,7 @@ module Ronin
52
52
  #
53
53
  # Compares the value to another value.
54
54
  #
55
- # @param [Values::Value] other
55
+ # @param [Value] other
56
56
  #
57
57
  # @return [Boolean]
58
58
  #
@@ -21,6 +21,6 @@
21
21
  module Ronin
22
22
  module Recon
23
23
  # ronin-recon version
24
- VERSION = '0.1.0.rc1'
24
+ VERSION = '0.1.0.rc2'
25
25
  end
26
26
  end
@@ -392,7 +392,7 @@ module Ronin
392
392
  #
393
393
  # Initializes the worker and runs it with the single value.
394
394
  #
395
- # @param [Values::Value] value
395
+ # @param [Value] value
396
396
  # The input value to process.
397
397
  #
398
398
  # @param [Hash{Symbol => Object}] kwargs
@@ -413,13 +413,13 @@ module Ronin
413
413
  #
414
414
  # Calls the recon worker with the given input value.
415
415
  #
416
- # @param [Values::Value] value
416
+ # @param [Value] value
417
417
  # The input value.
418
418
  #
419
419
  # @yield [new_value]
420
420
  # The `call` method can then `yield` one or more newly discovered values
421
421
  #
422
- # @yieldparam [Values::Value] new_value
422
+ # @yieldparam [Value] new_value
423
423
  # An newly discovered output value from the input value.
424
424
  #
425
425
  # @abstract
@@ -57,7 +57,7 @@ Sets a param value for the given worker\.
57
57
  Overrides the concurrency for the given worker\.
58
58
  .TP
59
59
  \fB\-\-max\-depth\fR \fINUM\fP
60
- The maximum recon depth\. Defaults to depth of \fB3\fR if the option is not
60
+ The maximum recon depth\. Defaults to depth of \fB10\fR if the option is not
61
61
  specified\.
62
62
  .TP
63
63
  \fB\-o\fR, \fB\-\-output\fR \fIFILE\fP
@@ -60,7 +60,7 @@ Runs the recon engine with one or more initial values.
60
60
  : Overrides the concurrency for the given worker.
61
61
 
62
62
  `--max-depth` *NUM*
63
- : The maximum recon depth. Defaults to depth of `3` if the option is not
63
+ : The maximum recon depth. Defaults to depth of `10` if the option is not
64
64
  specified.
65
65
 
66
66
  `-o`, `--output` *FILE*
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ronin-recon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.rc1
4
+ version: 0.1.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Postmodern
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-23 00:00:00.000000000 Z
11
+ date: 2024-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thread-local
@@ -237,6 +237,7 @@ files:
237
237
  - gemspec.yml
238
238
  - lib/ronin/recon.rb
239
239
  - lib/ronin/recon/builtin.rb
240
+ - lib/ronin/recon/builtin/api/crt_sh.rb
240
241
  - lib/ronin/recon/builtin/dns/lookup.rb
241
242
  - lib/ronin/recon/builtin/dns/mailservers.rb
242
243
  - lib/ronin/recon/builtin/dns/nameservers.rb
@@ -249,7 +250,6 @@ files:
249
250
  - lib/ronin/recon/builtin/net/service_id.rb
250
251
  - lib/ronin/recon/builtin/ssl/cert_enum.rb
251
252
  - lib/ronin/recon/builtin/ssl/cert_grab.rb
252
- - lib/ronin/recon/builtin/ssl/cert_sh.rb
253
253
  - lib/ronin/recon/builtin/web/dir_enum.rb
254
254
  - lib/ronin/recon/builtin/web/email_addresses.rb
255
255
  - lib/ronin/recon/builtin/web/spider.rb