Class: CMSScanner::Controller::Core

Inherits:
Base
  • Object
show all
Defined in:
app/controllers/core.rb,
app/controllers/core/cli_options.rb

Overview

CLI Options for the Core Controller

Instance Method Summary collapse

Methods inherited from Base

#==, #datastore, #formatter, #option_parser, option_parser=, #output, #render, reset, #target, #tmp_directory, #user_interaction?

Instance Method Details

#after_scanObject



69
70
71
72
73
74
75
76
77
78
79
# File 'app/controllers/core.rb', line 69

def after_scan
  @stop_time   = Time.now
  @elapsed     = @stop_time - @start_time
  @used_memory = GetProcessMem.new.bytes - @start_memory

  output('finished',
         cached_requests: NS.cached_requests,
         requests_done: NS.total_requests,
         data_sent: NS.total_data_sent,
         data_received: NS.total_data_received)
end

#before_scanObject



18
19
20
21
22
23
# File 'app/controllers/core.rb', line 18

def before_scan
  maybe_output_banner_help_and_version

  setup_cache
  check_target_availability
end

#check_target_availabilityVoid

Checks that the target is accessible, raises related errors otherwise

Returns:

  • (Void)

Raises:



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'app/controllers/core.rb', line 37

def check_target_availability
  res = NS::Browser.get(target.url)

  case res.code
  when 0
    raise Error::TargetDown, res
  when 401
    raise Error::HTTPAuthRequired
  when 403
    raise Error::AccessForbidden, NS::ParsedCli.random_user_agent unless NS::ParsedCli.force
  when 407
    raise Error::ProxyAuthRequired
  end

  # Checks for redirects
  # An out of scope redirect will raise an Error::HTTPRedirect
  effective_url = target.homepage_res.effective_url

  return if target.in_scope?(effective_url)

  raise Error::HTTPRedirect, effective_url unless NS::ParsedCli.ignore_main_redirect

  target.homepage_res = res
end

#cli_browser_cache_optionsArray<OptParseValidator::OptBase>

Returns:

  • (Array<OptParseValidator::OptBase>)


102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'app/controllers/core/cli_options.rb', line 102

def cli_browser_cache_options
  [
    OptInteger.new(['--cache-ttl TIME_TO_LIVE', 'The cache time to live in seconds'],
                   default: 600, advanced: true),
    OptBoolean.new(['--clear-cache', 'Clear the cache before the scan'], advanced: true),
    OptDirectoryPath.new(['--cache-dir PATH'],
                         readable: true,
                         writable: true,
                         create: true,
                         default: File.join(tmp_directory, 'cache'),
                         advanced: true)
  ]
end

#cli_browser_cookies_optionsArray<OptParseValidator::OptBase>

Returns:

  • (Array<OptParseValidator::OptBase>)


88
89
90
91
92
93
94
95
96
97
98
99
# File 'app/controllers/core/cli_options.rb', line 88

def cli_browser_cookies_options
  [
    OptString.new(['--cookie-string COOKIE',
                   'Cookie string to use in requests, ' \
                   'format: cookie1=value1[; cookie2=value2]']),
    OptFilePath.new(['--cookie-jar FILE-PATH', 'File to read and write cookies'],
                    writable: true,
                    readable: true,
                    create: true,
                    default: File.join(tmp_directory, 'cookie_jar.txt'))
  ]
end

#cli_browser_headers_optionsArray<OptParseValidator::OptBase>

Returns:

  • (Array<OptParseValidator::OptBase>)


70
71
72
73
74
75
76
# File 'app/controllers/core/cli_options.rb', line 70

def cli_browser_headers_options
  [
    OptString.new(['--user-agent VALUE', '--ua']),
    OptHeaders.new(['--headers HEADERS', 'Additional headers to append in requests'], advanced: true),
    OptString.new(['--vhost VALUE', 'The virtual host (Host header) to use in requests'], advanced: true)
  ]
end

#cli_browser_optionsArray<OptParseValidator::OptBase>

Returns:

  • (Array<OptParseValidator::OptBase>)


45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'app/controllers/core/cli_options.rb', line 45

def cli_browser_options
  cli_browser_headers_options + [
    OptBoolean.new(['--random-user-agent', '--rua',
                    'Use a random user-agent for each scan']),
    OptFilePath.new(['--user-agents-list FILE-PATH',
                     'List of agents to use with --random-user-agent'],
                    exists: true,
                    advanced: true,
                    default: APP_DIR.join('user_agents.txt')),
    OptCredentials.new(['--http-auth login:password']),
    OptPositiveInteger.new(['-t', '--max-threads VALUE', 'The max threads to use'],
                           default: 5),
    OptPositiveInteger.new(['--throttle MilliSeconds', 'Milliseconds to wait before doing another web request. ' \
                            'If used, the max threads will be set to 1.']),
    OptPositiveInteger.new(['--request-timeout SECONDS', 'The request timeout in seconds'],
                           default: 60),
    OptPositiveInteger.new(['--connect-timeout SECONDS', 'The connection timeout in seconds'],
                           default: 30),
    OptBoolean.new(['--disable-tls-checks',
                    'Disables SSL/TLS certificate verification, and downgrade to TLS1.0+ ' \
                    '(requires cURL 7.66 for the latter)'])
  ] + cli_browser_proxy_options + cli_browser_cookies_options + cli_browser_cache_options
end

#cli_browser_proxy_optionsArray<OptParseValidator::OptBase>

Returns:

  • (Array<OptParseValidator::OptBase>)


79
80
81
82
83
84
85
# File 'app/controllers/core/cli_options.rb', line 79

def cli_browser_proxy_options
  [
    OptProxy.new(['--proxy protocol://IP:port',
                  'Supported protocols depend on the cURL installed']),
    OptCredentials.new(['--proxy-auth login:password'])
  ]
end

#cli_optionsObject



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'app/controllers/core/cli_options.rb', line 7

def cli_options
  formats = NS::Formatter.availables

  [
    OptURL.new(['-u', '--url URL', 'The URL to scan'],
               required_unless: %i[help hh version],
               default_protocol: 'http'),
    OptBoolean.new(['--force', 'Do not check if target returns a 403'])
  ] + mixed_cli_options + [
    OptFilePath.new(['-o', '--output FILE', 'Output to FILE'], writable: true, exists: false),
    OptChoice.new(['-f', '--format FORMAT',
                   'Output results in the format supplied'], choices: formats),
    OptChoice.new(['--detection-mode MODE'],
                  choices: %w[mixed passive aggressive],
                  normalize: :to_sym,
                  default: :mixed),
    OptArray.new(['--scope DOMAINS',
                  'Comma separated (sub-)domains to consider in scope. ',
                  'Wildcard(s) allowed in the trd of valid domains, e.g: *.target.tld'], advanced: true)
  ] + cli_browser_options
end

#maybe_output_banner_help_and_versionObject



25
26
27
28
29
30
31
32
# File 'app/controllers/core.rb', line 25

def maybe_output_banner_help_and_version
  output('banner') if NS::ParsedCli.banner
  output('help', help: option_parser.simple_help, simple: true) if NS::ParsedCli.help
  output('help', help: option_parser.full_help, simple: false) if NS::ParsedCli.hh
  output('version') if NS::ParsedCli.version

  exit(NS::ExitCode::OK) if NS::ParsedCli.help || NS::ParsedCli.hh || NS::ParsedCli.version
end

#mixed_cli_optionsObject



29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'app/controllers/core/cli_options.rb', line 29

def mixed_cli_options
  [
    OptBoolean.new(['-h', '--help', 'Display the simple help and exit']),
    OptBoolean.new(['--hh', 'Display the full help and exit']),
    OptBoolean.new(['--version', 'Display the version and exit']),
    OptBoolean.new(['--ignore-main-redirect', 'Ignore the main redirect (if any) and scan the target url'],
                   advanced: true),
    OptBoolean.new(['-v', '--verbose', 'Verbose mode']),
    OptBoolean.new(['--[no-]banner', 'Whether or not to display the banner'], default: true),
    OptPositiveInteger.new(['--max-scan-duration SECONDS',
                            'Abort the scan if it exceeds the time provided in seconds'],
                           advanced: true)
  ]
end

#runObject



62
63
64
65
66
67
# File 'app/controllers/core.rb', line 62

def run
  @start_time = Time.now
  @start_memory = NS.start_memory

  output('started', url: target.url, ip: target.ip, effective_url: target.homepage_url)
end

#setup_cacheObject



9
10
11
12
13
14
15
16
# File 'app/controllers/core.rb', line 9

def setup_cache
  return unless NS::ParsedCli.cache_dir

  storage_path = File.join(NS::ParsedCli.cache_dir, Digest::MD5.hexdigest(target.url))

  Typhoeus::Config.cache = Cache::Typhoeus.new(storage_path)
  Typhoeus::Config.cache.clean if NS::ParsedCli.clear_cache
end