Class: Arachni::Platform::Manager

Inherits:
Object
  • Object
show all
Extended by:
UI::Output, Utilities
Includes:
UI::Output, Utilities, Enumerable
Defined in:
lib/arachni/platform/manager.rb

Overview

Represents a collection of platform lists.

It also holds a DB of all fingerprints per URI as a class variable and provides helper method for accessing and manipulating it.

Author:

Constant Summary collapse

TYPES =
{
    os:         'Operating systems',
    db:         'Databases',
    servers:    'Web servers',
    languages:  'Programming languages',
    frameworks: 'Frameworks'
}
OS =
{
    # Generic *nix, flavor couldn't be identified.
    unix:    {
        linux:   {},

        # Generic BSD, flavor couldn't be identified.
        bsd:     {},
        aix:     {},
        solaris: {}
    },
    windows: {}
}
DB =
{
    sql: {
        mysql:      {},
        pgsql:      {},
        mssql:      {},
        oracle:     {},
        sqlite:     {},
        ingres:     {},
        emc:        {},
        db2:        {},
        interbase:  {},
        informix:   {},
        firebird:   {},
        maxdb:      {},
        sybase:     {},
        frontbase:  {},
        hsqldb:     {},
        access:     {},
    },
    nosql: {
        mongodb:    {}
    }
}
SERVERS =
[
    :apache,
    :nginx,
    :tomcat,
    :iis,
    :jetty
]
LANGUAGES =
[
    :php,
    :jsp,
    :python,
    :ruby,
    :asp,
    :aspx,
    :perl
]
FRAMEWORKS =

WebApp frameworks.

[
    :rack
]
PLATFORM_NAMES =
{
    # Operating systems
    unix:       'Generic Unix family',
    linux:      'Linux',
    bsd:        'Generic BSD family',
    aix:        'IBM AIX',
    solaris:    'Solaris',
    windows:    'MS Windows',

    # Databases
    sql:        'Generic SQL family',
    mysql:      'MySQL',
    pgsql:      'Postgresql',
    mssql:      'MSSQL',
    oracle:     'Oracle',
    sqlite:     'SQLite',
    emc:        'EMC',
    db2:        'DB2',
    interbase:  'InterBase',
    informix:   'Informix',
    firebird:   'Firebird',
    maxdb:      'SaP Max DB',
    sybase:     'Sybase',
    frontbase:  'Frontbase',
    ingres:     'IngresDB',
    hsqldb:     'HSQLDB',
    access:     'MS Access',
    nosql:      'Generic NoSQL family',
    mongodb:    'MongoDB',

    # Web servers
    apache:     'Apache',
    nginx:      'Nginx',
    tomcat:     'TomCat',
    iis:        'IIS',
    jetty:      'Jetty',

    # Programming languages
    php:    'PHP',
    jsp:    'JSP',
    python: 'Python',
    ruby:   'Ruby',
    asp:    'ASP',
    aspx:   'ASP.NET',
    perl:   'Perl',

    # Web frameworks
    rack:   'Rack'
}
PLATFORM_CACHE_SIZE =

Amount of

1000

Class Method Summary collapse

Instance Method Summary collapse

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?, regexp_array_match, 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(platforms = []) ⇒ Manager

Returns a new instance of Manager.

Parameters:

  • platforms (Array<String, Symbol>) (defaults to: [])

    Platforms with which to initialize the lists.



331
332
333
334
335
336
337
338
339
# File 'lib/arachni/platform/manager.rb', line 331

def initialize( platforms = [] )
    @platforms = {}
    TYPES.keys.each do |type|
        @platforms[type] =
            List.new( self.class.const_get( type.to_s.upcase.to_sym ) )
    end

    update [platforms | Options.platforms].flatten.compact
end

Class Method Details

.[](uri) ⇒ Manager

Returns Platform for the given ‘uri`.

Parameters:

Returns:

  • (Manager)

    Platform for the given ‘uri`



300
301
302
303
304
305
306
307
308
309
310
# File 'lib/arachni/platform/manager.rb', line 300

def self.[]( uri )
    # If fingerprinting is disabled there's no point in filling the cache
    # with the same object over and over, create an identical one for all
    # URLs and return that always.
    if !Options.fingerprint?
        return @default ||= new( Options.platforms )
    end

    return new if !(key = make_key( uri ))
    synchronize { @platforms[key] ||= new }
end

.[]=(uri, platforms) ⇒ Manager

Sets platform manager for the given ‘uri`.

Parameters:

Returns:

Raises:



262
263
264
265
266
267
268
269
# File 'lib/arachni/platform/manager.rb', line 262

def self.[]=( uri, platforms )
    return new( platforms ) if !(key = make_key( uri ))

    synchronize do
        @platforms[key] =
            platforms.is_a?( self ) ? platforms : new( platforms )
    end
end

.any?Boolean

Returns ‘true` if there are platforms fingerprints, `false` otherwise.

Returns:

  • (Boolean)

    ‘true` if there are platforms fingerprints, `false` otherwise.



320
321
322
# File 'lib/arachni/platform/manager.rb', line 320

def self.any?
    !empty?
end

.clearObject

Clears global platforms DB.



203
204
205
# File 'lib/arachni/platform/manager.rb', line 203

def self.clear
    @platforms.clear
end

.empty?Boolean

Returns ‘true` if there are no platforms fingerprints, `false` otherwise.

Returns:

  • (Boolean)

    ‘true` if there are no platforms fingerprints, `false` otherwise.



314
315
316
# File 'lib/arachni/platform/manager.rb', line 314

def self.empty?
    @platforms.empty?
end

.find_type(platform) ⇒ Object



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/arachni/platform/manager.rb', line 167

def self.find_type( platform )
    @find_type ||= {}

    if @find_type.empty?
        TYPES.keys.each do |type|

            platforms = const_get( type.to_s.upcase.to_sym )
            platforms = platforms.find_symbol_keys_recursively if platforms.is_a?( Hash )

            platforms.each do |p|
                @find_type[p] = type
            end
        end
    end

    @find_type[platform]
end

.fingerprint(page) ⇒ Manager

Runs all fingerprinters against the given ‘page`.

Parameters:

  • page (Page)

    Page to fingerprint.

Returns:



242
243
244
245
246
247
248
249
250
251
# File 'lib/arachni/platform/manager.rb', line 242

def self.fingerprint( page )
    return page if !fingerprint? page

    fingerprinters.available.each do |name|
        exception_jail( false ) do
            fingerprinters[name].new( page ).run
        end
    end
    page
end

.fingerprint?(resource) ⇒ Bool

Returns ‘true` if the resource should be fingerprinted, `false` otherwise.

Parameters:

Returns:

  • (Bool)

    ‘true` if the resource should be fingerprinted, `false` otherwise.



230
231
232
233
# File 'lib/arachni/platform/manager.rb', line 230

def self.fingerprint?( resource )
    !(!Options.fingerprint? || !resource.text? ||
    include?( resource.url ) || resource.scope.out?)
end

.fingerprintersObject



219
220
221
222
223
# File 'lib/arachni/platform/manager.rb', line 219

def self.fingerprinters
    @manager ||=
        Component::Manager.new( Options.paths.fingerprinters,
                                Platform::Fingerprinters )
end

.include?(uri) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


276
277
278
# File 'lib/arachni/platform/manager.rb', line 276

def self.include?( uri )
    @platforms.include?( make_key( uri ) )
end

.make_key(uri) ⇒ Object



324
325
326
327
# File 'lib/arachni/platform/manager.rb', line 324

def self.make_key( uri )
    return if !(parsed = Arachni::URI( uri ))
    parsed.without_query
end

.resetObject

Empties the global platform fingerprints.



208
209
210
211
212
213
214
215
216
# File 'lib/arachni/platform/manager.rb', line 208

def self.reset
    set Hash.new
    @manager.clear if @manager
    @manager = nil

    @mutex  = Monitor.new

    self
end

.set(platforms) ⇒ Object

Sets global platforms fingerprints



196
197
198
199
200
# File 'lib/arachni/platform/manager.rb', line 196

def self.set( platforms )
    @platforms = Support::Cache::RandomReplacement.new( PLATFORM_CACHE_SIZE )
    platforms.each { |k, v| @platforms[k] = v }
    @platforms
end

.sizeObject



271
272
273
# File 'lib/arachni/platform/manager.rb', line 271

def self.size
    @platforms.size
end

.synchronize(&block) ⇒ Object



163
164
165
# File 'lib/arachni/platform/manager.rb', line 163

def self.synchronize( &block )
    @mutex.synchronize( &block )
end

.update(uri, platforms) ⇒ Manager

Updates the ‘platforms` for the given `uri`.

Parameters:

Returns:

Raises:



290
291
292
293
294
# File 'lib/arachni/platform/manager.rb', line 290

def self.update( uri, platforms )
    synchronize do
        self[uri].update platforms
    end
end

.validObject



185
186
187
# File 'lib/arachni/platform/manager.rb', line 185

def self.valid
    @valid ||= Set.new( PLATFORM_NAMES.keys )
end

.valid?(platforms) ⇒ Boolean

Returns:

  • (Boolean)


189
190
191
192
# File 'lib/arachni/platform/manager.rb', line 189

def self.valid?( platforms )
    platforms = [platforms].flatten.compact
    (valid & platforms).to_a == platforms
end

Instance Method Details

#<<(platform) ⇒ Manager

Returns ‘self`.

Parameters:

  • platform (Symbol, String)

    Platform to add to the appropriate list.

Returns:

Raises:



514
515
516
517
# File 'lib/arachni/platform/manager.rb', line 514

def <<( platform )
    find_list( platform ) << platform
    self
end

#any?Boolean

Returns ‘true` if there are applicable platforms, `false` otherwise.

Returns:

  • (Boolean)

    ‘true` if there are applicable platforms, `false` otherwise.



485
486
487
# File 'lib/arachni/platform/manager.rb', line 485

def any?
    !empty?
end

#clearObject



489
490
491
# File 'lib/arachni/platform/manager.rb', line 489

def clear
    @platforms.clear
end

#dbList

Returns Platform list for databases.

Returns:

  • (List)

    Platform list for databases.

See Also:



# File 'lib/arachni/platform/manager.rb', line 347

#each(&block) ⇒ Enumerator, Manager

Returns ‘Enumerator` if no `block` is given, `self` otherwise.

Parameters:

  • block (Block)

    Block to be passed each platform.

Returns:

  • (Enumerator, Manager)

    ‘Enumerator` if no `block` is given, `self` otherwise.



459
460
461
462
463
# File 'lib/arachni/platform/manager.rb', line 459

def each( &block )
    return enum_for( __method__ ) if !block_given?
    @platforms.map { |_, p| p.to_a }.flatten.each( &block )
    self
end

#empty?Boolean

Returns ‘true` if there are no applicable platforms, `false` otherwise.

Returns:

  • (Boolean)

    ‘true` if there are no applicable platforms, `false` otherwise.



479
480
481
# File 'lib/arachni/platform/manager.rb', line 479

def empty?
    !@platforms.map { |_, p| p.empty? }.include?( false )
end

#find_list(platform) ⇒ List

Returns Platform list.

Parameters:

  • platform (String, Symbol)

    Platform whose list to find.

Returns:

  • (List)

    Platform list.



532
533
534
# File 'lib/arachni/platform/manager.rb', line 532

def find_list( platform )
    @platforms[find_type( normalize( platform ) )]
end

#find_type(platform) ⇒ Symbol

Returns Platform type.

Parameters:

  • platform (String, Symbol)

    Platform whose type to find

Returns:

  • (Symbol)

    Platform type.



523
524
525
# File 'lib/arachni/platform/manager.rb', line 523

def find_type( platform )
    self.class.find_type( platform )
end

#frameworksList

Returns Platform list for frameworks.

Returns:

  • (List)

    Platform list for frameworks.

See Also:



371
372
373
374
375
# File 'lib/arachni/platform/manager.rb', line 371

[:os, :db, :servers, :languages, :frameworks].each do |type|
    define_method type do
        @platforms[type]
    end
end

#fullname(platform) ⇒ String

Converts a platform shortname to a full name.

Parameters:

  • platform (String, Symbol)

    Platform shortname.

Returns:

Raises:



387
388
389
# File 'lib/arachni/platform/manager.rb', line 387

def fullname( platform )
    PLATFORM_NAMES[normalize( platform )]
end

#include?(platform) ⇒ Boolean

Returns ‘true` if one of the lists contains the `platform`, `false` otherwise.

Parameters:

  • platform (Symbol, String)

    Platform to check.

Returns:

  • (Boolean)

    ‘true` if one of the lists contains the `platform`, `false` otherwise.

Raises:



473
474
475
# File 'lib/arachni/platform/manager.rb', line 473

def include?( platform )
    find_list( platform ).include?( platform )
end

#invalid?(platform) ⇒ Boolean

Returns ‘true` if platform is invalid (i.e. not in #valid), `false` otherwise.

Parameters:

  • platform (Symbol, String)

    Platform to check.

Returns:

  • (Boolean)

    ‘true` if platform is invalid (i.e. not in #valid), `false` otherwise.

See Also:



450
451
452
# File 'lib/arachni/platform/manager.rb', line 450

def invalid?( platform )
    !valid?( platform )
end

#languagesList

Returns Platform list for languages.

Returns:

  • (List)

    Platform list for languages.

See Also:



# File 'lib/arachni/platform/manager.rb', line 359

#osList

Returns Platform list for operating systems.

Returns:

  • (List)

    Platform list for operating systems.

See Also:



# File 'lib/arachni/platform/manager.rb', line 341

#pick(data_per_platform) ⇒ Hash

Selects appropriate data, depending on the applicable platforms, from ‘data_per_platform`.

Parameters:

  • data_per_platform (Hash{<Symbol, String> => Object})

    Hash with platform names as keys and arbitrary data as values.

Returns:

  • (Hash)

    ‘data_per_platform` with non-applicable entries (for non-empty platform lists) removed. Data for platforms whose list is empty will not be removed.

Raises:



403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
# File 'lib/arachni/platform/manager.rb', line 403

def pick( data_per_platform )
    data_per_list = {}
    data_per_platform.each do |platform, value|
        list = find_list( platform )
        data_per_list[list]           ||= {}
        data_per_list[list][platform]   = value
    end

    picked = {}
    data_per_list.each do |list, data|
        # If a platform list is empty pass the given data without picking...
        if list.empty?
            picked.merge! data
            next
        end

        # ...otherwise enforce its platform restrictions.
        picked.merge! list.pick( data )
    end

    picked
end

#serversList

Returns Platform list for web servers.

Returns:

  • (List)

    Platform list for web servers.

See Also:



# File 'lib/arachni/platform/manager.rb', line 353

#update(enum) ⇒ Manager

Returns Updated ‘self`.

Parameters:

  • enum (Enumerable)

    Enumerable object containing platforms.

Returns:

Raises:



501
502
503
504
# File 'lib/arachni/platform/manager.rb', line 501

def update( enum )
    enum.each { |p| self << p }
    self
end

#validSet<Symbol>

Returns List of valid platforms.

Returns:

  • (Set<Symbol>)

    List of valid platforms.



428
429
430
# File 'lib/arachni/platform/manager.rb', line 428

def valid
    self.class.valid
end

#valid?(platform) ⇒ Boolean

Returns ‘true` if platform is valid (i.e. in #valid), `false` otherwise.

Parameters:

  • platform (Symbol, String)

    Platform to check.

Returns:

  • (Boolean)

    ‘true` if platform is valid (i.e. in #valid), `false` otherwise.

See Also:



439
440
441
# File 'lib/arachni/platform/manager.rb', line 439

def valid?( platform )
    valid.include? platform
end