Class: Arachni::Platform::Manager
- 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.
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, :gunicorn ]
- LANGUAGES =
 [ :php, :java, :python, :ruby, :asp, :aspx, :perl ]
- FRAMEWORKS =
          
WebApp frameworks.
 [ :rack, :rails, :cakephp, :symfony, :nette, :django, :aspx_mvc, :jsf, :cherrypy ]
- 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', gunicorn: 'Gunicorn', # Programming languages php: 'PHP', java: 'Java', python: 'Python', ruby: 'Ruby', asp: 'ASP', aspx: 'ASP.NET', perl: 'Perl', # Web frameworks rack: 'Rack', django: 'Django', cakephp: 'CakePHP', nette: 'Nette', symfony: 'Symfony', rails: 'Ruby on Rails', aspx_mvc: 'ASP.NET MVC', jsf: 'JavaServer Faces', cherrypy: 'CherryPy' }
- PLATFORM_CACHE_SIZE =
 500
Class Method Summary collapse
- 
  
    
      .[](uri)  ⇒ Manager 
    
    
  
  
  
  
  
  
  
  
  
    
Platform for the given `uri`.
 - 
  
    
      .[]=(uri, platforms)  ⇒ Manager 
    
    
  
  
  
  
  
  
  
  
  
    
Sets platform manager for the given `uri`.
 - 
  
    
      .any?  ⇒ Boolean 
    
    
  
  
  
  
  
  
  
  
  
    
`true` if there are platforms fingerprints, `false` otherwise.
 - 
  
    
      .clear  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Clears global platforms DB.
 - 
  
    
      .empty?  ⇒ Boolean 
    
    
  
  
  
  
  
  
  
  
  
    
`true` if there are no platforms fingerprints, `false` otherwise.
 - .find_type(platform) ⇒ Object
 - 
  
    
      .fingerprint(page)  ⇒ Manager 
    
    
  
  
  
  
  
  
  
  
  
    
Runs all fingerprinters against the given `page`.
 - 
  
    
      .fingerprint?(resource)  ⇒ Bool 
    
    
  
  
  
  
  
  
  
  
  
    
`true` if the resource should be fingerprinted, `false` otherwise.
 - .fingerprinters ⇒ Object
 - .include?(uri) ⇒ Boolean
 - .make_key(uri) ⇒ Object
 - .new_from_options(platforms = []) ⇒ Object
 - 
  
    
      .reset  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Empties the global platform fingerprints.
 - 
  
    
      .set(platforms)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Sets global platforms fingerprints.
 - .size ⇒ Object
 - .synchronize(&block) ⇒ Object
 - 
  
    
      .update(uri, platforms)  ⇒ Manager 
    
    
  
  
  
  
  
  
  
  
  
    
Updates the `platforms` for the given `uri`.
 - .valid ⇒ Object
 - .valid?(platforms) ⇒ Boolean
 
Instance Method Summary collapse
- 
  
    
      #<<(platform)  ⇒ Manager 
    
    
  
  
  
  
  
  
  
  
  
    
`self`.
 - 
  
    
      #any?  ⇒ Boolean 
    
    
  
  
  
  
  
  
  
  
  
    
`true` if there are applicable platforms, `false` otherwise.
 - #clear ⇒ Object
 - 
  
    
      #db  ⇒ List 
    
    
  
  
  
  
  
  
  
  
  
    
Platform list for databases.
 - 
  
    
      #each(&block)  ⇒ Enumerator, Manager 
    
    
  
  
  
  
  
  
  
  
  
    
`Enumerator` if no `block` is given, `self` otherwise.
 - 
  
    
      #empty?  ⇒ Boolean 
    
    
  
  
  
  
  
  
  
  
  
    
`true` if there are no applicable platforms, `false` otherwise.
 - 
  
    
      #find_list(platform)  ⇒ List 
    
    
  
  
  
  
  
  
  
  
  
    
Platform list.
 - 
  
    
      #find_type(platform)  ⇒ Symbol 
    
    
  
  
  
  
  
  
  
  
  
    
Platform type.
 - 
  
    
      #frameworks  ⇒ List 
    
    
  
  
  
  
  
  
  
  
  
    
Platform list for frameworks.
 - 
  
    
      #fullname(platform)  ⇒ String 
    
    
  
  
  
  
  
  
  
  
  
    
Converts a platform shortname to a full name.
 - 
  
    
      #include?(platform)  ⇒ Boolean 
    
    
  
  
  
  
  
  
  
  
  
    
`true` if one of the lists contains the `platform`, `false` otherwise.
 - 
  
    
      #initialize(platforms = [])  ⇒ Manager 
    
    
  
  
  
    constructor
  
  
  
  
  
  
  
    
A new instance of Manager.
 - 
  
    
      #invalid?(platform)  ⇒ Boolean 
    
    
  
  
  
  
  
  
  
  
  
    
`true` if platform is invalid (i.e. not in #valid), `false` otherwise.
 - 
  
    
      #languages  ⇒ List 
    
    
  
  
  
  
  
  
  
  
  
    
Platform list for languages.
 - 
  
    
      #os  ⇒ List 
    
    
  
  
  
  
  
  
  
  
  
    
Platform list for operating systems.
 - 
  
    
      #pick(data_per_platform)  ⇒ Hash 
    
    
  
  
  
  
  
  
  
  
  
    
Selects appropriate data, depending on the applicable platforms, from `data_per_platform`.
 - 
  
    
      #servers  ⇒ List 
    
    
  
  
  
  
  
  
  
  
  
    
Platform list for web servers.
 - 
  
    
      #update(enum)  ⇒ Manager 
    
    
  
  
  
  
  
  
  
  
  
    
Updated `self`.
 - 
  
    
      #valid  ⇒ Set<Symbol> 
    
    
  
  
  
  
  
  
  
  
  
    
List of valid platforms.
 - 
  
    
      #valid?(platform)  ⇒ Boolean 
    
    
  
  
  
  
  
  
  
  
  
    
`true` if platform is valid (i.e. in #valid), `false` otherwise.
 
Methods included from Utilities
available_port, available_port_mutex, bytes_to_kilobytes, bytes_to_megabytes, caller_name, caller_path, cookie_decode, cookie_encode, cookies_from_file, cookies_from_parser, cookies_from_response, exception_jail, exclude_path?, follow_protocol?, form_decode, form_encode, forms_from_parser, forms_from_response, full_and_absolute_url?, generate_token, get_path, hms_to_seconds, html_decode, html_encode, include_path?, links_from_parser, 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_level_1?, debug_level_2?, debug_level_3?, debug_level_4?, 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_debug_level_4, 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.
      367 368 369 370 371 372 373 374 375  | 
    
      # File 'lib/arachni/platform/manager.rb', line 367 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 end  | 
  
Class Method Details
.[](uri) ⇒ Manager
Returns Platform for the given `uri`.
      284 285 286 287 288 289 290 291 292 293 294  | 
    
      # File 'lib/arachni/platform/manager.rb', line 284 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 ||= end return if !(key = make_key( uri )) synchronize { @platforms.fetch(key) { } } end  | 
  
.[]=(uri, platforms) ⇒ Manager
Sets platform manager for the given `uri`.
      305 306 307 308 309 310 311 312 313 314 315 316 317  | 
    
      # File 'lib/arachni/platform/manager.rb', line 305 def self.[]=( uri, platforms ) # For some reason we failed to make a key, try to salvage the situation. if !(key = make_key( uri )) return ( platforms ) end synchronize do @platforms[key] = platforms.is_a?( self ) ? platforms : ( platforms ) end end  | 
  
.any? ⇒ Boolean
Returns `true` if there are platforms fingerprints, `false` otherwise.
      352 353 354  | 
    
      # File 'lib/arachni/platform/manager.rb', line 352 def self.any? !empty? end  | 
  
.clear ⇒ Object
Clears global platforms DB.
      220 221 222  | 
    
      # File 'lib/arachni/platform/manager.rb', line 220 def self.clear @platforms.clear end  | 
  
.empty? ⇒ Boolean
Returns `true` if there are no platforms fingerprints, `false` otherwise.
      346 347 348  | 
    
      # File 'lib/arachni/platform/manager.rb', line 346 def self.empty? @platforms.empty? end  | 
  
.find_type(platform) ⇒ Object
      184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200  | 
    
      # File 'lib/arachni/platform/manager.rb', line 184 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`.
      259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278  | 
    
      # File 'lib/arachni/platform/manager.rb', line 259 def self.fingerprint( page ) synchronize do return page if !fingerprint? page fingerprinters.available.each do |name| exception_jail( false ) do fingerprinters[name].new( page ).run end end # We do this to flag the resource as checked even if no platforms # were identified. We don't want to keep checking a resource that # yields nothing over and over. update( page.url, [] ) end # Fingerprinting will have resulted in element parsing, clear the element # caches to keep RAM consumption down. page.clear_cache end  | 
  
.fingerprint?(resource) ⇒ Bool
Returns `true` if the resource should be fingerprinted, `false` otherwise.
      247 248 249 250  | 
    
      # File 'lib/arachni/platform/manager.rb', line 247 def self.fingerprint?( resource ) !(!Options.fingerprint? || resource.code != 200 || !resource.text? || include?( resource.url ) || resource.scope.out?) end  | 
  
.fingerprinters ⇒ Object
      236 237 238 239 240  | 
    
      # File 'lib/arachni/platform/manager.rb', line 236 def self.fingerprinters @manager ||= Component::Manager.new( Options.paths.fingerprinters, Platform::Fingerprinters ) end  | 
  
.include?(uri) ⇒ Boolean
      324 325 326  | 
    
      # File 'lib/arachni/platform/manager.rb', line 324 def self.include?( uri ) @platforms.include?( make_key( uri ) ) end  | 
  
.make_key(uri) ⇒ Object
      356 357 358 359  | 
    
      # File 'lib/arachni/platform/manager.rb', line 356 def self.make_key( uri ) return if !(parsed = Arachni::URI( uri )) parsed.without_query end  | 
  
.new_from_options(platforms = []) ⇒ Object
      361 362 363  | 
    
      # File 'lib/arachni/platform/manager.rb', line 361 def self.( platforms = [] ) new( platforms | Options.platforms ) end  | 
  
.reset ⇒ Object
Empties the global platform fingerprints.
      225 226 227 228 229 230 231 232 233  | 
    
      # File 'lib/arachni/platform/manager.rb', line 225 def self.reset set Hash.new @manager.clear if @manager @manager = nil @mutex = Monitor.new self end  | 
  
.set(platforms) ⇒ Object
Sets global platforms fingerprints
      213 214 215 216 217  | 
    
      # File 'lib/arachni/platform/manager.rb', line 213 def self.set( platforms ) @platforms = Support::Cache::LeastRecentlyPushed.new( PLATFORM_CACHE_SIZE ) platforms.each { |k, v| @platforms[k] = v } @platforms end  | 
  
.size ⇒ Object
      319 320 321  | 
    
      # File 'lib/arachni/platform/manager.rb', line 319 def self.size @platforms.size end  | 
  
.synchronize(&block) ⇒ Object
      180 181 182  | 
    
      # File 'lib/arachni/platform/manager.rb', line 180 def self.synchronize( &block ) @mutex.synchronize( &block ) end  | 
  
.update(uri, platforms) ⇒ Manager
Updates the `platforms` for the given `uri`.
      338 339 340 341 342  | 
    
      # File 'lib/arachni/platform/manager.rb', line 338 def self.update( uri, platforms ) synchronize do self[uri].update platforms end end  | 
  
.valid ⇒ Object
      202 203 204  | 
    
      # File 'lib/arachni/platform/manager.rb', line 202 def self.valid @valid ||= Set.new( PLATFORM_NAMES.keys ) end  | 
  
.valid?(platforms) ⇒ Boolean
      206 207 208 209  | 
    
      # File 'lib/arachni/platform/manager.rb', line 206 def self.valid?( platforms ) platforms = [platforms].flatten.compact (valid & platforms).to_a == platforms end  | 
  
Instance Method Details
#<<(platform) ⇒ Manager
Returns `self`.
      550 551 552 553  | 
    
      # File 'lib/arachni/platform/manager.rb', line 550 def <<( platform ) find_list( platform ) << platform self end  | 
  
#any? ⇒ Boolean
Returns `true` if there are applicable platforms, `false` otherwise.
      521 522 523  | 
    
      # File 'lib/arachni/platform/manager.rb', line 521 def any? !empty? end  | 
  
#clear ⇒ Object
      525 526 527  | 
    
      # File 'lib/arachni/platform/manager.rb', line 525 def clear @platforms.clear end  | 
  
#each(&block) ⇒ Enumerator, Manager
Returns `Enumerator` if no `block` is given, `self` otherwise.
      495 496 497 498 499  | 
    
      # File 'lib/arachni/platform/manager.rb', line 495 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.
      515 516 517  | 
    
      # File 'lib/arachni/platform/manager.rb', line 515 def empty? !@platforms.map { |_, p| p.empty? }.include?( false ) end  | 
  
#find_list(platform) ⇒ List
Returns Platform list.
      568 569 570  | 
    
      # File 'lib/arachni/platform/manager.rb', line 568 def find_list( platform ) @platforms[find_type( normalize( platform ) )] end  | 
  
#find_type(platform) ⇒ Symbol
Returns Platform type.
      559 560 561  | 
    
      # File 'lib/arachni/platform/manager.rb', line 559 def find_type( platform ) self.class.find_type( platform ) end  | 
  
#frameworks ⇒ List
Returns Platform list for frameworks.
      407 408 409 410 411  | 
    
      # File 'lib/arachni/platform/manager.rb', line 407 [: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.
      423 424 425  | 
    
      # File 'lib/arachni/platform/manager.rb', line 423 def fullname( platform ) PLATFORM_NAMES[normalize( platform )] end  | 
  
#include?(platform) ⇒ Boolean
Returns `true` if one of the lists contains the `platform`, `false` otherwise.
      509 510 511  | 
    
      # File 'lib/arachni/platform/manager.rb', line 509 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.
      486 487 488  | 
    
      # File 'lib/arachni/platform/manager.rb', line 486 def invalid?( platform ) !valid?( platform ) end  | 
  
#languages ⇒ List
Returns Platform list for languages.
| 
       | 
    
      # File 'lib/arachni/platform/manager.rb', line 395
     | 
  
#os ⇒ List
Returns Platform list for operating systems.
| 
       | 
    
      # File 'lib/arachni/platform/manager.rb', line 377
     | 
  
#pick(data_per_platform) ⇒ Hash
Selects appropriate data, depending on the applicable platforms, from `data_per_platform`.
      439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460  | 
    
      # File 'lib/arachni/platform/manager.rb', line 439 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  | 
  
#servers ⇒ List
Returns Platform list for web servers.
| 
       | 
    
      # File 'lib/arachni/platform/manager.rb', line 389
     | 
  
#update(enum) ⇒ Manager
Returns Updated `self`.
      537 538 539 540  | 
    
      # File 'lib/arachni/platform/manager.rb', line 537 def update( enum ) enum.each { |p| self << p } self end  | 
  
#valid ⇒ Set<Symbol>
Returns List of valid platforms.
      464 465 466  | 
    
      # File 'lib/arachni/platform/manager.rb', line 464 def valid self.class.valid end  | 
  
#valid?(platform) ⇒ Boolean
Returns `true` if platform is valid (i.e. in #valid), `false` otherwise.
      475 476 477  | 
    
      # File 'lib/arachni/platform/manager.rb', line 475 def valid?( platform ) valid.include? platform end  |