Class: Arachni::Framework

Inherits:
Object show all
Includes:
Support::Mixins::Observable, UI::Output, Utilities
Defined in:
lib/arachni/framework.rb

Overview

The Framework class ties together all the systems.

It’s the brains of the operation, it bosses the rest of the subsystems around. It runs the audit, loads checks and reports and runs them according to user options.

Author:

Direct Known Subclasses

RPC::Server::Framework

Defined Under Namespace

Classes: Error

Constant Summary collapse

AUDIT_PAGE_MAX_TRIES =

How many times to request a page upon failure.

5

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Support::Mixins::Observable

included

Methods included from Utilities

#available_port, #caller_name, #caller_path, #cookie_decode, #cookie_encode, #cookies_from_document, #cookies_from_file, #cookies_from_response, #exception_jail, #exclude_path?, #follow_protocol?, #form_decode, #form_encode, #forms_from_document, #forms_from_response, #generate_token, #get_path, #hms_to_seconds, #html_decode, #html_encode, #include_path?, #links_from_document, #links_from_response, #normalize_url, #page_from_response, #page_from_url, #parse_set_cookie, #path_in_domain?, #path_too_deep?, #port_available?, #rand_port, #random_seed, #redundant_path?, #remove_constants, #request_parse_body, #seconds_to_hms, #skip_page?, #skip_path?, #skip_resource?, #skip_response?, #to_absolute, #uri_decode, #uri_encode, #uri_parse, #uri_parse_query, #uri_parser, #uri_rewrite

Methods included from UI::Output

#debug?, #debug_off, #debug_on, #disable_only_positives, #included, #mute, #muted?, #only_positives, #only_positives?, #print_bad, #print_debug, #print_debug_backtrace, #print_debug_level_1, #print_debug_level_2, #print_debug_level_3, #print_error, #print_error_backtrace, #print_exception, #print_info, #print_line, #print_ok, #print_status, #print_verbose, #reroute_to_file, #reroute_to_file?, reset_output_options, #unmute, #verbose?, #verbose_on

Constructor Details

#initialize(options = Arachni::Options.instance, &block) ⇒ Framework

Returns a new instance of Framework.

Parameters:



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/arachni/framework.rb', line 129

def initialize( options = Arachni::Options.instance, &block )
    super()

    Encoding.default_external = 'BINARY'
    Encoding.default_internal = 'BINARY'

    @options = options

    @checks    = Check::Manager.new( self )
    @reporters = Reporter::Manager.new
    @plugins   = Plugin::Manager.new( self )

    reset_session
    @http = HTTP::Client.instance

    reset_trainer

    # Deep clone the redundancy rules to preserve their original counters
    # for the reports.
    @orig_redundant = options.scope.redundant_path_patterns.deep_clone

    state.status = :ready

    @current_url = ''

    # Holds page URLs which returned no response.
    @failures = []
    @retries  = {}

    @after_page_audit_blocks = []

    # Little helper to run a piece of code and reset the framework to be
    # ready to be reused.
    if block_given?
        begin
            block.call self
        ensure
            clean_up
            reset
        end
    end
end

Instance Attribute Details

#checksArachni::Check::Manager (readonly)



85
86
87
# File 'lib/arachni/framework.rb', line 85

def checks
  @checks
end

#failuresArray<String> (readonly)

Returns Page URLs which elicited no response from the server and were not audited. Not determined by HTTP status codes, we’re talking network failures here.

Returns:

  • (Array<String>)

    Page URLs which elicited no response from the server and were not audited. Not determined by HTTP status codes, we’re talking network failures here.



103
104
105
# File 'lib/arachni/framework.rb', line 103

def failures
  @failures
end

#httpArachni::HTTP (readonly)

Returns:



95
96
97
# File 'lib/arachni/framework.rb', line 95

def http
  @http
end

#optionsOptions (readonly)

Returns System options.

Returns:



79
80
81
# File 'lib/arachni/framework.rb', line 79

def options
  @options
end

#pluginsArachni::Plugin::Manager (readonly)



88
89
90
# File 'lib/arachni/framework.rb', line 88

def plugins
  @plugins
end

#reportersArachni::Reporter::Manager (readonly)



82
83
84
# File 'lib/arachni/framework.rb', line 82

def reporters
  @reporters
end

#sessionSession (readonly)

Returns Web application session manager.

Returns:

  • (Session)

    Web application session manager.



92
93
94
# File 'lib/arachni/framework.rb', line 92

def session
  @session
end

#trainerTrainer (readonly)

Returns:



98
99
100
# File 'lib/arachni/framework.rb', line 98

def trainer
  @trainer
end

Class Method Details

.resetObject

Note:

You should first reset Options.

Resets everything and allows the framework environment to be re-used.



835
836
837
838
839
840
841
842
843
844
845
846
847
848
# File 'lib/arachni/framework.rb', line 835

def self.reset
    State.clear
    Data.clear

    Platform::Manager.reset
    Check::Auditor.reset
    ElementFilter.reset
    Element::Capabilities::Auditable.reset
    Element::Capabilities::Analyzable.reset
    Check::Manager.reset
    Plugin::Manager.reset
    Reporter::Manager.reset
    HTTP::Client.reset
end

.restore(afs, &block) ⇒ Framework

Returns Restored instance.

Parameters:

  • afs (String)

    Path to an ‘.afs.` (Arachni Framework Snapshot) file created by #suspend.

Returns:



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/arachni/framework.rb', line 110

def self.restore( afs, &block )
    framework = new
    framework.restore( afs )

    if block_given?
        begin
            block.call framework
        ensure
            framework.clean_up
            framework.reset
        end
    end

    framework
end

Instance Method Details

#abort(wait = true) ⇒ Object

Aborts the framework #run on a best effort basis.

Parameters:

  • wait (Bool) (defaults to: true)

    Wait until the system has been aborted.



678
679
680
# File 'lib/arachni/framework.rb', line 678

def abort( wait = true )
    state.abort wait
end

#abort?Bool

Returns ‘true` if the framework has been instructed to abort (i.e. is in the process of being aborted or has been aborted), `false` otherwise.

Returns:

  • (Bool)

    ‘true` if the framework has been instructed to abort (i.e. is in the process of being aborted or has been aborted), `false` otherwise.



664
665
666
# File 'lib/arachni/framework.rb', line 664

def abort?
    state.abort?
end

#aborted?Bool

Returns ‘true` if the framework #run has been aborted, `false` otherwise.

Returns:

  • (Bool)

    ‘true` if the framework #run has been aborted, `false` otherwise.



657
658
659
# File 'lib/arachni/framework.rb', line 657

def aborted?
    state.aborted?
end

#aborting?Bool

Returns ‘true` if the framework is in the process of aborting, `false` otherwise.

Returns:

  • (Bool)

    ‘true` if the framework is in the process of aborting, `false` otherwise.



670
671
672
# File 'lib/arachni/framework.rb', line 670

def aborting?
    state.aborting?
end

#accepts_more_pages?Bool

Returns ‘true` if the framework can process more pages, `false` is scope limits have been reached.

Returns:

  • (Bool)

    ‘true` if the framework can process more pages, `false` is scope limits have been reached.



358
359
360
# File 'lib/arachni/framework.rb', line 358

def accepts_more_pages?
    crawl? && !page_limit_reached?
end

#after_page_audit(&block) ⇒ Object



61
# File 'lib/arachni/framework.rb', line 61

advertise :after_page_audit

#audit_page(page) ⇒ Object

Note:
Note:

It will audit just the given ‘page` and not any subsequent pages discovered by the Trainer – i.e. ignore any new elements that might appear as a result.

Note:

It will pass the ‘page` to the BrowserCluster for analysis if the DOM depth limit has not been reached and push resulting pages to #push_to_page_queue but will not audit those pages either.

Parameters:

  • page (Page)

    Runs loaded checks against ‘page`



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
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
# File 'lib/arachni/framework.rb', line 258

def audit_page( page )
    return if !page

    if page.scope.out?
        print_info "Ignoring page due to exclusion criteria: #{page.dom.url}"
        return false
    end

    # Initialize the BrowserCluster.
    browser_cluster

    state.audited_page_count += 1
    add_to_sitemap( page )
    sitemap.merge!( browser_sitemap )

    print_line
    print_status "[HTTP: #{page.code}] #{page.dom.url}"
    # print_object_space
    # print_with_statistics

    if page.platforms.any?
        print_info "Identified as: #{page.platforms.to_a.join( ', ' )}"
    end

    if crawl?
        pushed = push_paths_from_page( page )
        print_info "Analysis resulted in #{pushed.size} usable paths."
    end

    if host_has_browser?
        print_info "DOM depth: #{page.dom.depth} (Limit: #{options.scope.dom_depth_limit})"

        if page.dom.transitions.any?
            print_info '  Transitions:'
            page.dom.print_transitions( method(:print_info), '    ' )
        end
    end

    notify_on_page_audit( page )

    @current_url = page.dom.url.to_s

    http.update_cookies( page.cookie_jar )
    perform_browser_analysis( page )

    # Run checks which **don't** benefit from fingerprinting first, so that
    # we can use the responses of their HTTP requests to fingerprint the
    # webapp platforms, so that the checks which **do** benefit from knowing
    # the remote platforms can run more efficiently.
    ran = false
    @checks.without_platforms.values.each do |check|
        ran = true
        check_page( check, page )
    end
    harvest_http_responses if ran
    run_http = ran

    ran = false
    @checks.with_platforms.values.each do |check|
        ran = true
        check_page( check, page )
    end
    harvest_http_responses if ran
    run_http ||= ran

    if Check::Auditor.has_timeout_candidates?
        print_line
        print_status "Verifying timeout-analysis candidates for: #{page.dom.url}"
        print_info '---------------------------------------'
        Check::Auditor.timeout_audit_run
        run_http = true
    end

    # Makes it easier on the GC.
    page.clear_cache

    notify_after_page_audit( page )
    run_http
end

#browser_clusterBrowserCluster?

Returns A lazy-loaded browser cluster or ‘nil` if OptionGroups::BrowserCluster#pool_size or OptionGroups::Scope#dom_depth_limit are 0 or not #host_has_browser?.

Returns:



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/arachni/framework.rb', line 195

def browser_cluster
    return if options.browser_cluster.pool_size == 0 ||
        Options.scope.dom_depth_limit == 0 || !host_has_browser?

    # Initialization may take a while so since we lazy load this make sure
    # that only one thread gets to this code at a time.
    synchronize do
        if !@browser_cluster
            state.set_status_message :browser_cluster_startup
        end

        @browser_cluster ||= BrowserCluster.new
        state.clear_status_messages
        @browser_cluster
    end
end

#browser_job_skip_statesObject



798
799
800
801
# File 'lib/arachni/framework.rb', line 798

def browser_job_skip_states
    return if !@browser_cluster
    browser_cluster.skip_states( browser_job.id )
end

#clean_up(shutdown_browsers = true) ⇒ Object

Cleans up the framework; should be called after running the audit or after canceling a running scan.

It stops the clock and waits for the plugins to finish up.



763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
# File 'lib/arachni/framework.rb', line 763

def clean_up( shutdown_browsers = true )
    return if @cleaned_up
    @cleaned_up = true

    state.status = :cleanup

    sitemap.merge!( browser_sitemap )

    if shutdown_browsers
        state.set_status_message :browser_cluster_shutdown
        shutdown_browser_cluster
    end

    state.set_status_message :clearing_queues
    page_queue.clear
    url_queue.clear

    @finish_datetime  = Time.now
    @start_datetime ||= Time.now

    # Make sure this is disabled or it'll break reporter output.
    disable_only_positives

    state.running = false

    state.set_status_message :waiting_for_plugins
    @plugins.block

    # Plugins may need the session right till the very end so save it for last.
    @session.clean_up
    @session = nil

    true
end

#crawl?Boolean

Returns:

  • (Boolean)


351
352
353
# File 'lib/arachni/framework.rb', line 351

def crawl?
    options.scope.crawl? && options.scope.restrict_paths.empty?
end

#dataData::Framework

Returns:



243
244
245
# File 'lib/arachni/framework.rb', line 243

def data
    Data.framework
end

#host_has_browser?Bool

Returns ‘true` if the environment has a browser, `false` otherwise.

Returns:

  • (Bool)

    ‘true` if the environment has a browser, `false` otherwise.



340
341
342
# File 'lib/arachni/framework.rb', line 340

def host_has_browser?
    Browser.has_executable?
end

#list_checks(patterns = nil) ⇒ Array<Hash>

Returns Information about all available Checks.

Returns:



500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
# File 'lib/arachni/framework.rb', line 500

def list_checks( patterns = nil )
    loaded = @checks.loaded

    begin
        @checks.clear
        @checks.available.map do |name|
            path = @checks.name_to_path( name )
            next if !list_check?( path, patterns )

            @checks[name].info.merge(
                shortname: name,
                author:    [@checks[name].info[:author]].
                               flatten.map { |a| a.strip },
                path:      path.strip,
                platforms: @checks[name].platforms,
                elements:  @checks[name].elements
            )
        end.compact
    ensure
        @checks.clear
        @checks.load loaded
    end
end

#list_platformsArray<Hash>

Returns Information about all available platforms.

Returns:

  • (Array<Hash>)

    Information about all available platforms.



576
577
578
579
580
581
582
583
584
# File 'lib/arachni/framework.rb', line 576

def list_platforms
    platforms = Platform::Manager.new
    platforms.valid.inject({}) do |h, platform|
        type = Platform::Manager::TYPES[platforms.find_type( platform )]
        h[type] ||= {}
        h[type][platform] = platforms.fullname( platform )
        h
    end
end

#list_plugins(patterns = nil) ⇒ Array<Hash>

Returns Information about all available Plugins.

Returns:



551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
# File 'lib/arachni/framework.rb', line 551

def list_plugins( patterns = nil )
    loaded = @plugins.loaded

    begin
        @plugins.clear
        @plugins.available.map do |plugin|
            path = @plugins.name_to_path( plugin )
            next if !list_plugin?( path, patterns )

            @plugins[plugin].info.merge(
                options:   @plugins[plugin].info[:options] || [],
                shortname: plugin,
                path:      path,
                author:    [@plugins[plugin].info[:author]].
                               flatten.map { |a| a.strip }
            )
        end.compact
    ensure
        @plugins.clear
        @plugins.load loaded
    end
end

#list_reporters(patterns = nil) ⇒ Array<Hash>

Returns Information about all available Reporters.

Returns:



526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
# File 'lib/arachni/framework.rb', line 526

def list_reporters( patterns = nil )
    loaded = @reporters.loaded

    begin
        @reporters.clear
        @reporters.available.map do |report|
            path = @reporters.name_to_path( report )
            next if !list_reporter?( path, patterns )

            @reporters[report].info.merge(
                options:   @reporters[report].info[:options] || [],
                shortname: report,
                path:      path,
                author:    [@reporters[report].info[:author]].
                               flatten.map { |a| a.strip }
            )
        end.compact
    ensure
        @reporters.clear
        @reporters.load loaded
    end
end

#on_page_audit(&block) ⇒ Object



58
# File 'lib/arachni/framework.rb', line 58

advertise :on_page_audit

#page_limit_reached?Bool

Returns ‘true` if the OptionGroups::Scope#page_limit has been reached, `false` otherwise.

Returns:



347
348
349
# File 'lib/arachni/framework.rb', line 347

def page_limit_reached?
    options.scope.page_limit_reached?( sitemap.size )
end

#page_queue_total_sizeInteger

Returns Total number of pages added to the page audit queue.

Returns:



174
175
176
# File 'lib/arachni/framework.rb', line 174

def page_queue_total_size
    data.page_queue_total_size
end

#pause(wait = true) ⇒ Integer

Note:

Each call from a unique caller is counted as a pause request and in order for the system to resume all pause callers need to #resume it.

Pauses the framework on a best effort basis.

Parameters:

  • wait (Bool) (defaults to: true)

    Wait until the system has been paused.

Returns:

  • (Integer)

    ID identifying this pause request.



649
650
651
652
653
# File 'lib/arachni/framework.rb', line 649

def pause( wait = true )
    id = generate_token.hash
    state.pause id, wait
    id
end

#pause?Bool

Returns ‘true` if the framework has been instructed to pause (i.e. is in the process of being paused or has been paused), `false` otherwise.

Returns:

  • (Bool)

    ‘true` if the framework has been instructed to pause (i.e. is in the process of being paused or has been paused), `false` otherwise.



628
629
630
# File 'lib/arachni/framework.rb', line 628

def pause?
    state.pause?
end

#paused?Bool

Returns ‘true` if the framework is paused, `false` otherwise.

Returns:

  • (Bool)

    ‘true` if the framework is paused, `false` otherwise.



621
622
623
# File 'lib/arachni/framework.rb', line 621

def paused?
    state.paused?
end

#pausing?Bool

Returns ‘true` if the framework is in the process of pausing, `false` otherwise.

Returns:

  • (Bool)

    ‘true` if the framework is in the process of pausing, `false` otherwise.



634
635
636
# File 'lib/arachni/framework.rb', line 634

def pausing?
    state.pausing?
end

#push_to_page_queue(page, force = false) ⇒ Bool

Returns ‘true` if push was successful, `false` if the `page` matched any exclusion criteria or has already been seen.

Parameters:

Returns:

  • (Bool)

    ‘true` if push was successful, `false` if the `page` matched any exclusion criteria or has already been seen.



396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
# File 'lib/arachni/framework.rb', line 396

def push_to_page_queue( page, force = false )
    return false if !force && (!accepts_more_pages? || state.page_seen?( page ) ||
        page.scope.out? || page.scope.redundant?)

    # We want to update from the already loaded page cache (if there is one)
    # as we have to store the page anyways (needs to go through Browser analysis)
    # and it's not worth the resources to parse its elements.
    #
    # We're basically doing this to give the Browser and Trainer a better
    # view of what elements have been seen, so that they won't feed us pages
    # with elements that they think are new, but have been provided to us by
    # some other component; however, it wouldn't be the end of the world if
    # that were to happen.
    ElementFilter.update_from_page_cache page

    data.push_to_page_queue page
    state.page_seen page

    true
end

#push_to_url_queue(url, force = false) ⇒ Bool

Returns ‘true` if push was successful, `false` if the `url` matched any exclusion criteria or has already been seen.

Parameters:

Returns:

  • (Bool)

    ‘true` if push was successful, `false` if the `url` matched any exclusion criteria or has already been seen.



423
424
425
426
427
428
429
430
431
432
433
434
435
# File 'lib/arachni/framework.rb', line 423

def push_to_url_queue( url, force = false )
    return if !force && !accepts_more_pages?

    url = to_absolute( url ) || url
    if state.url_seen?( url ) || skip_path?( url ) || redundant_path?( url )
        return false
    end

    data.push_to_url_queue url
    state.url_seen url

    true
end

#reportReport

Returns Scan results.

Returns:



439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
# File 'lib/arachni/framework.rb', line 439

def report
    opts = options.to_hash.deep_clone

    # restore the original redundancy rules and their counters
    opts[:scope][:redundant_path_patterns] = @orig_redundant

    Report.new(
        options:         options,
        sitemap:         sitemap,
        issues:          Data.issues.sort,
        plugins:         @plugins.results,
        start_datetime:  @start_datetime,
        finish_datetime: @finish_datetime
    )
end

#report_as(name, external_report = report) ⇒ String

Runs a reporter component and returns the contents of the generated report.

Only accepts reporters which support an ‘outfile` option.

Parameters:

  • name (String)

    Name of the reporter component to run, as presented by #list_reporters‘s `:shortname` key.

  • external_report (Report) (defaults to: report)

    Report to use – defaults to the local one.

Returns:

Raises:



473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
# File 'lib/arachni/framework.rb', line 473

def report_as( name, external_report = report )
    if !@reporters.available.include?( name.to_s )
        fail Component::Error::NotFound, "Reporter '#{name}' could not be found."
    end

    loaded = @reporters.loaded
    begin
        @reporters.clear

        if !@reporters[name].has_outfile?
            fail Component::Options::Error::Invalid,
                 "Reporter '#{name}' cannot format the audit results as a String."
        end

        outfile = "#{Dir.tmpdir}/#{generate_token}"
        @reporters.run( name, external_report, outfile: outfile )

        IO.binread( outfile )
    ensure
        File.delete( outfile ) if outfile
        @reporters.clear
        @reporters.load loaded
    end
end

#resetObject

Note:

Prefer this from reset if you already have an instance.

Note:

You should first reset Options.

Resets everything and allows the framework to be re-used.



813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
# File 'lib/arachni/framework.rb', line 813

def reset
    @cleaned_up  = false
    @browser_job = nil

    @failures.clear
    @retries.clear

    # This needs to happen before resetting the other components so they
    # will be able to put in their hooks.
    self.class.reset

    clear_observers
    reset_trainer
    reset_session
    @checks.clear
    @reporters.clear
    @plugins.clear
end

#reset_trainerObject



851
852
853
# File 'lib/arachni/framework.rb', line 851

def reset_trainer
    @trainer = Trainer.new( self )
end

#restore(afs) ⇒ Framework

Returns Restored instance.

Parameters:

  • afs (String)

    Path to an ‘.afs.` (Arachni Framework Snapshot) file created by #suspend.

Returns:



744
745
746
747
748
749
750
751
752
753
# File 'lib/arachni/framework.rb', line 744

def restore( afs )
    Snapshot.load afs

    browser_job_update_skip_states state.browser_skip_states

    checks.load  Options.checks
    plugins.load Options.plugins.keys

    nil
end

#resume(id) ⇒ Object

Note:

Each call from a unique caller is counted as a pause request and in order for the system to resume all pause callers need to #resume it.

Removes a #pause request for the current caller.

Parameters:

  • id (Integer)

    ID of the #pause request.



690
691
692
# File 'lib/arachni/framework.rb', line 690

def resume( id )
    state.resume id
end

#run(&block) ⇒ Object

Starts the scan.

Parameters:

  • block (Block)

    A block to call after the audit has finished but before running #reporters.



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/arachni/framework.rb', line 216

def run( &block )
    prepare
    handle_signals
    return if aborted?

    # Catch exceptions so that if something breaks down or the user opted to
    # exit the reporters will still run with whatever results Arachni managed
    # to gather.
    exception_jail( false ){ audit }
    # print_with_statistics

    return if aborted?
    return if suspended?

    clean_up
    exception_jail( false ){ block.call } if block_given?
    state.status = :done

    true
end

#running?Bool

Returns ‘true` if the framework is running, `false` otherwise. This is `true` even if the scan is #paused?.

Returns:

  • (Bool)

    ‘true` if the framework is running, `false` otherwise. This is `true` even if the scan is #paused?.



609
610
611
# File 'lib/arachni/framework.rb', line 609

def running?
    state.running?
end

#scanning?Bool

Returns ‘true` if the system is scanning, `false` otherwise.

Returns:

  • (Bool)

    ‘true` if the system is scanning, `false` otherwise.



615
616
617
# File 'lib/arachni/framework.rb', line 615

def scanning?
    state.scanning?
end

#sitemapHash<String, Integer>

Returns List of crawled URLs with their HTTP codes.

Returns:

  • (Hash<String, Integer>)

    List of crawled URLs with their HTTP codes.



186
187
188
# File 'lib/arachni/framework.rb', line 186

def sitemap
    data.sitemap
end

#snapshot_pathString

Returns Provisioned #suspend dump file for this instance.

Returns:



722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
# File 'lib/arachni/framework.rb', line 722

def snapshot_path
    return @state_archive if @state_archive

    default_filename =
        "#{URI(options.url).host} #{Time.now.to_s.gsub( ':', '_' )} #{generate_token}.afs"

    location = options.snapshot.save_path

    if !location
        location = default_filename
    elsif File.directory? location
        location += "/#{default_filename}"
    end

    @state_archive ||= File.expand_path( location )
end

#stateState::Framework

Returns:



238
239
240
# File 'lib/arachni/framework.rb', line 238

def state
    State.framework
end

#statisticsHash

Returns Framework statistics:

  • ‘:http` – HTTP::Client#statistics

  • ‘:runtime` – Scan runtime in seconds.

  • ‘:found_pages` – Number of discovered pages.

  • ‘:audited_pages` – Number of audited pages.

  • ‘:current_page` – URL of the currently audited page.

  • ‘:status` – #status

  • ‘:messages` – #status_messages.

Returns:

  • (Hash)

    Framework statistics:

    • ‘:http` – HTTP::Client#statistics

    • ‘:runtime` – Scan runtime in seconds.

    • ‘:found_pages` – Number of discovered pages.

    • ‘:audited_pages` – Number of audited pages.

    • ‘:current_page` – URL of the currently audited page.

    • ‘:status` – #status

    • ‘:messages` – #status_messages



373
374
375
376
377
378
379
380
381
# File 'lib/arachni/framework.rb', line 373

def statistics
    {
        http:          http.statistics,
        runtime:       @start_datetime ? Time.now - @start_datetime : 0,
        found_pages:   sitemap.size,
        audited_pages: state.audited_page_count,
        current_page:  @current_url
    }
end

#statusSymbol

Returns Status of the instance, possible values are (in order):

  • ‘:ready` – Initialised and waiting for instructions.

  • ‘:preparing` – Getting ready to start (i.e. initializing plugins etc.).

  • ‘:scanning` – The instance is currently auditing the webapp.

  • ‘:pausing` – The instance is being paused (if applicable).

  • ‘:paused` – The instance has been paused (if applicable).

  • ‘:suspending` – The instance is being suspended (if applicable).

  • ‘:suspended` – The instance has being suspended (if applicable).

  • ‘:cleanup` – The scan has completed and the instance is

    {Framework#clean_up cleaning up} after itself (i.e. waiting for
    plugins to finish etc.).
    
  • ‘:aborted` – The scan has been #abort, you can grab the

    report and shutdown.
    
  • ‘:done` – The scan has completed, you can grab the report and shutdown.

Returns:

  • (Symbol)

    Status of the instance, possible values are (in order):

    • ‘:ready` – Initialised and waiting for instructions.

    • ‘:preparing` – Getting ready to start (i.e. initializing plugins etc.).

    • ‘:scanning` – The instance is currently auditing the webapp.

    • ‘:pausing` – The instance is being paused (if applicable).

    • ‘:paused` – The instance has been paused (if applicable).

    • ‘:suspending` – The instance is being suspended (if applicable).

    • ‘:suspended` – The instance has being suspended (if applicable).

    • ‘:cleanup` – The scan has completed and the instance is

      {Framework#clean_up cleaning up} after itself (i.e. waiting for
      plugins to finish etc.).
      
    • ‘:aborted` – The scan has been #abort, you can grab the

      report and shutdown.
      
    • ‘:done` – The scan has completed, you can grab the report and shutdown.



602
603
604
# File 'lib/arachni/framework.rb', line 602

def status
    state.status
end

#status_messagesArray<String>

Returns Messages providing more information about the current #status of the framework.

Returns:

  • (Array<String>)

    Messages providing more information about the current #status of the framework.



386
387
388
# File 'lib/arachni/framework.rb', line 386

def status_messages
    state.status_messages
end

#suspend(wait = true) ⇒ String?

Writes a Snapshot.dump to disk and aborts the scan.

Parameters:

  • wait (Bool) (defaults to: true)

    Wait for the system to write it state to disk.

Returns:

  • (String, nil)

    Path to the state file ‘wait` is `true`, `nil` otherwise.



701
702
703
704
705
# File 'lib/arachni/framework.rb', line 701

def suspend( wait = true )
    state.suspend( wait )
    return snapshot_path if wait
    nil
end

#suspend?Bool

Returns ‘true` if the system is in the process of being suspended, `false` otherwise.

Returns:

  • (Bool)

    ‘true` if the system is in the process of being suspended, `false` otherwise.



710
711
712
# File 'lib/arachni/framework.rb', line 710

def suspend?
    state.suspend?
end

#suspended?Bool

Returns ‘true` if the system has been suspended, `false` otherwise.

Returns:

  • (Bool)

    ‘true` if the system has been suspended, `false` otherwise.



716
717
718
# File 'lib/arachni/framework.rb', line 716

def suspended?
    state.suspended?
end

#url_queue_total_sizeInteger

Returns Total number of URLs added to the URL audit queue.

Returns:



180
181
182
# File 'lib/arachni/framework.rb', line 180

def url_queue_total_size
    data.url_queue_total_size
end

#versionString

Returns the version of the framework.

Returns:

  • (String)

    Returns the version of the framework.



805
806
807
# File 'lib/arachni/framework.rb', line 805

def version
    Arachni::VERSION
end

#wait_for_browser?Boolean

Returns:

  • (Boolean)


755
756
757
# File 'lib/arachni/framework.rb', line 755

def wait_for_browser?
    @browser_cluster && !browser_cluster.done?
end