Class: Msf::Auxiliary::Web::HTTP
- Inherits:
-
Object
- Object
- Msf::Auxiliary::Web::HTTP
- Defined in:
- lib/msf/core/auxiliary/web/http.rb
Defined Under Namespace
Instance Attribute Summary collapse
-
#domain ⇒ Object
Returns the value of attribute domain.
-
#framework ⇒ Object
readonly
Returns the value of attribute framework.
-
#headers ⇒ Object
readonly
Returns the value of attribute headers.
-
#opts ⇒ Object
readonly
Returns the value of attribute opts.
-
#parent ⇒ Object
readonly
Returns the value of attribute parent.
-
#password ⇒ Object
Returns the value of attribute password.
-
#redirect_limit ⇒ Object
Returns the value of attribute redirect_limit.
-
#username ⇒ Object
Returns the value of attribute username.
Instance Method Summary collapse
-
#after_run { ... } ⇒ Array<Proc>
Registers a callback to be executed after #run drains the request queue.
-
#connect ⇒ Rex::Proto::Http::Client
Creates a Rex HTTP client using the configured target and authentication defaults.
-
#custom_404?(path, body) {|is_custom_404| ... } ⇒ nil
Determines whether a response body matches the application’s custom 404 behavior.
-
#get(url, opts = {}) ⇒ Response?
Sends a synchronous GET request.
-
#get_async(url, opts = {}) {|response| ... } ⇒ Queue
Enqueues a GET request.
-
#if_not_custom_404(path, body) { ... } ⇒ void
Yields only when the supplied response body does not appear to be a custom 404 page.
-
#initialize(opts = {}) ⇒ HTTP
constructor
A new instance of HTTP.
-
#post(url, opts = {}) ⇒ Response?
Sends a synchronous POST request.
-
#post_async(url, opts = {}) {|response| ... } ⇒ Queue
Enqueues a POST request.
-
#request(url, opts = {}) ⇒ Response?
Sends an HTTP request and optionally follows redirect responses.
-
#request_async(url, opts = {}) {|response| ... } ⇒ Queue
Enqueues a request to be sent later by #run.
-
#run ⇒ void
Executes all queued asynchronous requests using the configured thread pool size.
Constructor Details
#initialize(opts = {}) ⇒ HTTP
Returns a new instance of HTTP.
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 106 def initialize( opts = {} ) @opts = opts.dup @framework = opts[:framework] @parent = opts[:parent] @headers = { 'Accept' => '*/*', 'Cookie' => opts[:cookie_string] }.merge( opts[:headers] || {} ) @headers.delete( 'Cookie' ) if !@headers['Cookie'] @request_opts = {} if opts[:auth].is_a? Hash @username = opts[:auth][:user].to_s @password = opts[:auth][:password].to_s @domain = opts[:auth][:domain].to_s end self.redirect_limit = opts[:redirect_limit] || 20 @queue = Queue.new @after_run_blocks = [] end |
Instance Attribute Details
#domain ⇒ Object
Returns the value of attribute domain.
97 98 99 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 97 def domain @domain end |
#framework ⇒ Object (readonly)
Returns the value of attribute framework.
93 94 95 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 93 def framework @framework end |
#headers ⇒ Object (readonly)
Returns the value of attribute headers.
92 93 94 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 92 def headers @headers end |
#opts ⇒ Object (readonly)
Returns the value of attribute opts.
91 92 93 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 91 def opts @opts end |
#parent ⇒ Object (readonly)
Returns the value of attribute parent.
94 95 96 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 94 def parent @parent end |
#password ⇒ Object
Returns the value of attribute password.
97 98 99 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 97 def password @password end |
#redirect_limit ⇒ Object
Returns the value of attribute redirect_limit.
96 97 98 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 96 def redirect_limit @redirect_limit end |
#username ⇒ Object
Returns the value of attribute username.
97 98 99 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 97 def username @username end |
Instance Method Details
#after_run { ... } ⇒ Array<Proc>
Registers a callback to be executed after #run drains the request queue.
137 138 139 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 137 def after_run( &block ) @after_run_blocks << block end |
#connect ⇒ Rex::Proto::Http::Client
Creates a Rex HTTP client using the configured target and authentication defaults.
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 144 def connect c = Rex::Proto::Http::Client.new( opts[:target].host, opts[:target].port, {}, opts[:target].ssl, 'Auto', nil, username, password, subscriber: opts[:http_subscriber] ) c.set_config({ 'vhost' => opts[:target].vhost, 'ssl_server_name_indication' => opts[:target].ssl_server_name_indication || opts[:target].vhost, 'agent' => opts[:user_agent] || Rex::UserAgent.session_agent, 'domain' => domain }) c end |
#custom_404?(path, body) {|is_custom_404| ... } ⇒ nil
Determines whether a response body matches the application’s custom 404 behavior.
The helper probes several random paths, refines their dynamic content, and compares the result to the supplied response body.
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 283 def custom_404?( path, body, &callback ) return if !path || !body precision = 2 trv_back = File.dirname( path ) trv_back << '/' if trv_back[-1,1] != '/' # 404 probes generators = [ # get a random path with an extension proc{ path + Rex::Text.rand_text_alpha( 10 ) + '.' + Rex::Text.rand_text_alpha( 10 )[0..precision] }, # get a random path without an extension proc{ path + Rex::Text.rand_text_alpha( 10 ) }, # move up a dir and get a random file proc{ trv_back + Rex::Text.rand_text_alpha( 10 ) }, # move up a dir and get a random file with an extension proc{ trv_back + Rex::Text.rand_text_alpha( 10 ) + '.' + Rex::Text.rand_text_alpha( 10 )[0..precision] }, # get a random directory proc{ path + Rex::Text.rand_text_alpha( 10 ) + '/' } ] synchronize do @@_404 ||= {} @@_404[path] ||= [] @@_404_gathered ||= Set.new gathered = 0 if !@@_404_gathered.include?( path.hash ) generators.each.with_index do |generator, i| @@_404[path][i] ||= {} precision.times { get_async( generator.call, :follow_redirect => true ) do |res| gathered += 1 if gathered == generators.size * precision @@_404_gathered << path.hash callback.call is_404?( path, body ) else @@_404[path][i]['rdiff_now'] ||= false if !@@_404[path][i]['body'] @@_404[path][i]['body'] = res.body else @@_404[path][i]['rdiff_now'] = true end if @@_404[path][i]['rdiff_now'] && !@@_404[path][i]['rdiff'] @@_404[path][i]['rdiff'] = Rex::Text.refine( @@_404[path][i]['body'], res.body ) end end end } end else callback.call is_404?( path, body ) end end nil end |
#get(url, opts = {}) ⇒ Response?
Sends a synchronous GET request.
251 252 253 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 251 def get( url, opts = {} ) request( url, opts.merge( :method => :get ) ) end |
#get_async(url, opts = {}) {|response| ... } ⇒ Queue
Enqueues a GET request.
232 233 234 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 232 def get_async( url, opts = {}, &callback ) request_async( url, opts.merge( :method => :get ), &callback ) end |
#if_not_custom_404(path, body) { ... } ⇒ void
This method returns an undefined value.
Yields only when the supplied response body does not appear to be a custom 404 page.
270 271 272 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 270 def if_not_custom_404( path, body, &callback ) custom_404?( path, body ) { |b| callback.call if !b } end |
#post(url, opts = {}) ⇒ Response?
Sends a synchronous POST request.
260 261 262 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 260 def post( url, opts = {} ) request( url, opts.merge( :method => :post ) ) end |
#post_async(url, opts = {}) {|response| ... } ⇒ Queue
Enqueues a POST request.
242 243 244 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 242 def post_async( url, opts = {}, &callback ) request_async( url, opts.merge( :method => :post ), &callback ) end |
#request(url, opts = {}) ⇒ Response?
Sends an HTTP request and optionally follows redirect responses.
204 205 206 207 208 209 210 211 212 213 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 204 def request( url, opts = {} ) rlimit = self.redirect_limit while rlimit >= 0 rlimit -= 1 res = _request( url, opts ) return res if !opts[:follow_redirect] || !url = res.headers['location'] end nil end |
#request_async(url, opts = {}) {|response| ... } ⇒ Queue
Enqueues a request to be sent later by #run.
222 223 224 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 222 def request_async( url, opts = {}, &callback ) queue Request.new( url, opts, &callback ) end |
#run ⇒ void
This method returns an undefined value.
Executes all queued asynchronous requests using the configured thread pool size.
Callback exceptions are reported through the parent module and isolated from the rest of the queue processing.
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/msf/core/auxiliary/web/http.rb', line 172 def run return if @queue.empty? tl = [] loop do while tl.size <= (opts[:max_threads] || 5) && !@queue.empty? && (req = @queue.pop) tl << framework.threads.spawn( "#{self.class.name} - #{req})", false, req ) do |request| # Keep callback failures isolated. begin request.handle_response request( request.url, request.opts ) rescue => e print_error e.to_s e.backtrace.each { |l| print_error l } end end end break if tl.empty? tl.reject! { |t| !t.alive? } select( nil, nil, nil, 0.05 ) end call_after_run_blocks end |