Class: Ronin::Recon::Web::DirEnum

Inherits:
Ronin::Recon::WebWorker show all
Defined in:
lib/ronin/recon/builtin/web/dir_enum.rb

Overview

A recon worker that discovers HTTP directories.

Constant Summary collapse

DEFAULT_WORDLIST =
File.join(WORDLISTS_DIR, 'raft-small-directories.txt.gz')

Constants included from Mixins::HTTP

Mixins::HTTP::VALID_STATUS_CODES

Instance Method Summary collapse

Methods inherited from Ronin::Recon::Worker

accepts, concurrency, #initialize, intensity, outputs, register, run

Constructor Details

This class inherits a constructor from Ronin::Recon::Worker

Instance Method Details

#process(website) {|url| ... } ⇒ Object

Discovers HTTP directories for a given website.

Parameters:

Yields:

  • (url)

    Every discovered directory will be passed to the block as a URL.

Yield Parameters:

  • url (Values::URL)

    A URL representing an exposed directory.



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/ronin/recon/builtin/web/dir_enum.rb', line 69

def process(website)
  wordlist = Wordlist.open(params[:wordlist] || DEFAULT_WORDLIST)
  queue    = Async::LimitedQueue.new(params[:concurrency])
  endpoint = Async::HTTP::Endpoint.for(
    website.scheme, website.host, port: website.port
  )
  base_url = website.to_s

  Async do |task|
    task.async do
      # feed the queue with the wordlist
      wordlist.each { |name| queue << name }

      # send stop messages for each sub-task
      params[:concurrency].times { queue << nil }
    end

    # spawn the sub-tasks
    params[:concurrency].times do
      task.async do
        http = Async::HTTP::Client.new(endpoint)

        while (dir = queue.dequeue)
          path    = "/#{URI.encode_uri_component(dir)}"
          retries = 0

          begin
            response = http.head(path)
            status   = response.status

            if VALID_STATUS_CODES.include?(status)
              headers = response.headers.to_h

              yield URL.new(
                "#{base_url}#{path}", status:  status,
                                      headers: headers
              )
            end
          rescue Errno::ECONNREFUSED,
                 SocketError
            task.stop
          rescue StandardError
            if retries > 3
              next
            else
              retries += 1
              sleep 1
              retry
            end
          end
        end
      end
    end
  end
end