ronin-web 1.0.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +3 -2
- data/.gitignore +1 -0
- data/.rubocop.yml +5 -0
- data/.ruby-version +1 -1
- data/ChangeLog.md +46 -1
- data/Gemfile +25 -12
- data/README.md +257 -51
- data/Rakefile +9 -0
- data/data/completions/ronin-web +203 -0
- data/gemspec.yml +18 -5
- data/lib/ronin/web/cli/browser_options.rb +92 -0
- data/lib/ronin/web/cli/browser_shell.rb +448 -0
- data/lib/ronin/web/cli/command.rb +1 -1
- data/lib/ronin/web/cli/commands/browser.rb +373 -0
- data/lib/ronin/web/cli/commands/completion.rb +63 -0
- data/lib/ronin/web/cli/commands/diff.rb +60 -8
- data/lib/ronin/web/cli/commands/html.rb +21 -33
- data/lib/ronin/web/cli/commands/irb.rb +1 -1
- data/lib/ronin/web/cli/commands/new/{webapp.rb → app.rb} +8 -8
- data/lib/ronin/web/cli/commands/new/nokogiri.rb +4 -4
- data/lib/ronin/web/cli/commands/new/server.rb +1 -1
- data/lib/ronin/web/cli/commands/new/spider.rb +1 -1
- data/lib/ronin/web/cli/commands/new.rb +5 -3
- data/lib/ronin/web/cli/commands/reverse_proxy.rb +1 -1
- data/lib/ronin/web/cli/commands/screenshot.rb +186 -0
- data/lib/ronin/web/cli/commands/server.rb +1 -1
- data/lib/ronin/web/cli/commands/session_cookie.rb +265 -0
- data/lib/ronin/web/cli/commands/spider.rb +61 -467
- data/lib/ronin/web/cli/commands/user_agent.rb +177 -0
- data/lib/ronin/web/cli/commands/vulns.rb +463 -0
- data/lib/ronin/web/cli/commands/wordlist.rb +484 -0
- data/lib/ronin/web/cli/commands/xml.rb +149 -0
- data/lib/ronin/web/cli/js_shell.rb +69 -0
- data/lib/ronin/web/cli/ruby_shell.rb +1 -1
- data/lib/ronin/web/cli/spider_options.rb +919 -0
- data/lib/ronin/web/cli.rb +3 -1
- data/lib/ronin/web/html.rb +1 -1
- data/lib/ronin/web/root.rb +1 -1
- data/lib/ronin/web/version.rb +2 -2
- data/lib/ronin/web/xml.rb +1 -1
- data/lib/ronin/web.rb +4 -364
- data/man/ronin-web-browser.1 +92 -0
- data/man/ronin-web-browser.1.md +96 -0
- data/man/ronin-web-completion.1 +76 -0
- data/man/ronin-web-completion.1.md +78 -0
- data/man/ronin-web-diff.1 +14 -21
- data/man/ronin-web-diff.1.md +13 -6
- data/man/ronin-web-html.1 +30 -46
- data/man/ronin-web-html.1.md +27 -17
- data/man/ronin-web-irb.1 +9 -16
- data/man/ronin-web-irb.1.md +6 -2
- data/man/ronin-web-new-app.1.md +39 -0
- data/man/ronin-web-new-nokogiri.1 +9 -20
- data/man/ronin-web-new-nokogiri.1.md +5 -5
- data/man/ronin-web-new-server.1 +11 -23
- data/man/ronin-web-new-server.1.md +5 -5
- data/man/ronin-web-new-spider.1 +44 -88
- data/man/ronin-web-new-spider.1.md +37 -37
- data/man/ronin-web-new.1 +18 -30
- data/man/ronin-web-new.1.md +15 -11
- data/man/ronin-web-reverse-proxy.1 +33 -38
- data/man/ronin-web-reverse-proxy.1.md +20 -14
- data/man/ronin-web-screenshot.1 +56 -0
- data/man/ronin-web-screenshot.1.md +56 -0
- data/man/ronin-web-server.1 +15 -29
- data/man/ronin-web-server.1.md +13 -9
- data/man/ronin-web-session-cookie.1 +38 -0
- data/man/ronin-web-session-cookie.1.md +41 -0
- data/man/ronin-web-spider.1 +121 -130
- data/man/ronin-web-spider.1.md +115 -66
- data/man/ronin-web-user-agent.1 +44 -0
- data/man/ronin-web-user-agent.1.md +46 -0
- data/man/ronin-web-vulns.1 +175 -0
- data/man/ronin-web-vulns.1.md +177 -0
- data/man/ronin-web-wordlist.1 +258 -0
- data/man/ronin-web-wordlist.1.md +263 -0
- data/man/ronin-web-xml.1 +43 -0
- data/man/ronin-web-xml.1.md +46 -0
- data/man/ronin-web.1 +67 -18
- data/man/ronin-web.1.md +55 -4
- data/scripts/setup +58 -0
- metadata +121 -30
- data/lib/ronin/web/mechanize.rb +0 -84
- data/man/ronin-web-new-webapp.1.md +0 -39
- /data/data/new/{webapp → app}/.gitignore +0 -0
- /data/data/new/{webapp → app}/.ruby-version.erb +0 -0
- /data/data/new/{webapp → app}/Dockerfile.erb +0 -0
- /data/data/new/{webapp → app}/Gemfile +0 -0
- /data/data/new/{webapp → app}/app.rb.erb +0 -0
- /data/data/new/{webapp → app}/config.ru +0 -0
- /data/data/new/{webapp → app}/docker-compose.yml.erb +0 -0
@@ -0,0 +1,177 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-web - A collection of useful web helper methods and commands.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2006-2024 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-web is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-web is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with ronin-web. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/web/cli/command'
|
22
|
+
require 'ronin/web/user_agents'
|
23
|
+
|
24
|
+
module Ronin
|
25
|
+
module Web
|
26
|
+
class CLI
|
27
|
+
module Commands
|
28
|
+
#
|
29
|
+
# Generates a random HTTP `User-Agent` string.
|
30
|
+
#
|
31
|
+
# ## Usage
|
32
|
+
#
|
33
|
+
# ronin-web user_agent [options]
|
34
|
+
#
|
35
|
+
# ## Options
|
36
|
+
#
|
37
|
+
# -B, --browser chrome|firefox The desired browser
|
38
|
+
# --chrome-version VERSION The desired Chrome version
|
39
|
+
# --firefox-version VERSION The desired Firefox version
|
40
|
+
# -D ubuntu|fedora|arch|DISTRO, The desired Linux distro
|
41
|
+
# --linux-distro
|
42
|
+
# -A x86-64|x86|i686|aarch64|arm64|arm,
|
43
|
+
# --arch The desired architecture
|
44
|
+
# -O, --os android|linux|windows The desired OS
|
45
|
+
# --os-version VERSION The desired OS version
|
46
|
+
# -h, --help Print help information
|
47
|
+
#
|
48
|
+
# @since 2.0.0
|
49
|
+
#
|
50
|
+
class UserAgent < Command
|
51
|
+
|
52
|
+
usage '[options]'
|
53
|
+
|
54
|
+
option :browser, short: '-B',
|
55
|
+
value: {
|
56
|
+
type: [:chrome, :firefox]
|
57
|
+
},
|
58
|
+
desc: 'The desired browser'
|
59
|
+
|
60
|
+
option :chrome_version, value: {
|
61
|
+
type: String,
|
62
|
+
usage: 'VERSION'
|
63
|
+
},
|
64
|
+
desc: 'The desired Chrome version'
|
65
|
+
|
66
|
+
option :firefox_version, value: {
|
67
|
+
type: String,
|
68
|
+
usage: 'VERSION'
|
69
|
+
},
|
70
|
+
desc: 'The desired Firefox version'
|
71
|
+
|
72
|
+
option :linux_distro, short: '-D',
|
73
|
+
value: {
|
74
|
+
type: String,
|
75
|
+
usage: 'ubuntu|fedora|arch|DISTRO'
|
76
|
+
},
|
77
|
+
desc: 'The desired Linux distro' do |distro|
|
78
|
+
options[:linux_distro] = case distro
|
79
|
+
when 'ubuntu'
|
80
|
+
:ubuntu
|
81
|
+
when 'fedora'
|
82
|
+
:fedora
|
83
|
+
when 'arch'
|
84
|
+
:arch
|
85
|
+
else
|
86
|
+
distro
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
option :arch, short: '-A',
|
91
|
+
value: {
|
92
|
+
type: {
|
93
|
+
'x86-64' => :x86_64,
|
94
|
+
'x86' => :x86,
|
95
|
+
'i686' => :i686,
|
96
|
+
'aarch64' => :aarch64,
|
97
|
+
'arm64' => :arm64,
|
98
|
+
'arm' => :arm
|
99
|
+
}
|
100
|
+
},
|
101
|
+
desc: 'The desired architecture'
|
102
|
+
|
103
|
+
option :os, short: '-O',
|
104
|
+
value: {
|
105
|
+
type: [:android, :linux, :windows]
|
106
|
+
},
|
107
|
+
desc: 'The desired OS'
|
108
|
+
|
109
|
+
option :os_version, value: {
|
110
|
+
type: String,
|
111
|
+
usage: 'VERSION'
|
112
|
+
},
|
113
|
+
desc: 'The desired OS version'
|
114
|
+
|
115
|
+
description 'Generates a random User-Agent string'
|
116
|
+
|
117
|
+
man_page 'ronin-web-user-agent.1'
|
118
|
+
|
119
|
+
#
|
120
|
+
# Runs the `ronin-web user-agent` command.
|
121
|
+
#
|
122
|
+
def run
|
123
|
+
case options[:browser]
|
124
|
+
when :chrome
|
125
|
+
puts Web::UserAgents.chrome.random(**random_kwargs)
|
126
|
+
when :firefox
|
127
|
+
puts Web::UserAgents.firefox.random(**random_kwargs)
|
128
|
+
when nil
|
129
|
+
puts Web::UserAgents.random(**random_kwargs)
|
130
|
+
else
|
131
|
+
raise(NotImplementedError,"unsupported browser type: #{options[:browser].inspect}")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
#
|
136
|
+
# Generates keyword arguments for `Ronin::Web::UserAgents.random`,
|
137
|
+
# `Ronin::Web::UserAgents.chrome.random`, or
|
138
|
+
# `Ronin::Web::UserAgents.firefox.random`.
|
139
|
+
#
|
140
|
+
# @return [Hash{Symbol => Object}]
|
141
|
+
# The keyword arguments for the User-Agent module's `random` method.
|
142
|
+
#
|
143
|
+
def random_kwargs
|
144
|
+
kwargs = {}
|
145
|
+
|
146
|
+
if options[:chrome_version] && options[:browser] == :chrome
|
147
|
+
kwargs[:chrome_version] = options[:chrome_version]
|
148
|
+
end
|
149
|
+
|
150
|
+
if options[:firefox_version] && options[:browser] == :firefox
|
151
|
+
kwargs[:firefox_version] = options[:firefox_version]
|
152
|
+
end
|
153
|
+
|
154
|
+
if options[:os]
|
155
|
+
kwargs[:os] = options[:os]
|
156
|
+
end
|
157
|
+
|
158
|
+
if options[:os_version]
|
159
|
+
kwargs[:os_version] = options[:os_version]
|
160
|
+
end
|
161
|
+
|
162
|
+
if options[:linux_distro]
|
163
|
+
kwargs[:linux_distro] = options[:linux_distro]
|
164
|
+
end
|
165
|
+
|
166
|
+
if options[:arch]
|
167
|
+
kwargs[:arch] = options[:arch]
|
168
|
+
end
|
169
|
+
|
170
|
+
return kwargs
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
@@ -0,0 +1,463 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-web - A collection of useful web helper methods and commands.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2006-2024 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-web is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-web is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with ronin-web. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/web/cli/command'
|
22
|
+
require 'ronin/web/cli/spider_options'
|
23
|
+
require 'ronin/core/cli/logging'
|
24
|
+
require 'ronin/vulns/url_scanner'
|
25
|
+
require 'ronin/vulns/cli/printing'
|
26
|
+
require 'ronin/vulns/cli/importable'
|
27
|
+
|
28
|
+
module Ronin
|
29
|
+
module Web
|
30
|
+
class CLI
|
31
|
+
module Commands
|
32
|
+
#
|
33
|
+
# ## Usage
|
34
|
+
#
|
35
|
+
# ronin-web vulns [options] {--host HOST | --domain DOMAIN | --site URL}
|
36
|
+
#
|
37
|
+
# ## Options
|
38
|
+
#
|
39
|
+
# --host HOST Spiders the specific HOST
|
40
|
+
# --domain DOMAIN Spiders the whole domain
|
41
|
+
# --site URL Spiders the website, starting at the URL
|
42
|
+
# --open-timeout SECS Sets the connection open timeout
|
43
|
+
# --read-timeout SECS Sets the read timeout
|
44
|
+
# --ssl-timeout SECS Sets the SSL connection timeout
|
45
|
+
# --continue-timeout SECS Sets the continue timeout
|
46
|
+
# --keep-alive-timeout SECS Sets the connection keep alive timeout
|
47
|
+
# -P, --proxy PROXY Sets the proxy to use.
|
48
|
+
# -H, --header NAME: VALUE Sets a default header
|
49
|
+
# --host-header NAME=VALUE Sets a default header
|
50
|
+
# -u chrome-linux|chrome-macos|chrome-windows|chrome-iphone|chrome-ipad|chrome-android|firefox-linux|firefox-macos|firefox-windows|firefox-iphone|firefox-ipad|firefox-android|safari-macos|safari-iphone|safari-ipad|edge,
|
51
|
+
# --user-agent The User-Agent to use
|
52
|
+
# -U, --user-agent-string STRING The User-Agent string to use
|
53
|
+
# -R, --referer URL Sets the Referer URL
|
54
|
+
# --delay SECS Sets the delay in seconds between each request
|
55
|
+
# -l, --limit COUNT Only spiders up to COUNT pages
|
56
|
+
# -d, --max-depth DEPTH Only spiders up to max depth
|
57
|
+
# --enqueue URL Adds the URL to the queue
|
58
|
+
# --visited URL Marks the URL as previously visited
|
59
|
+
# --strip-fragments Enables/disables stripping the fragment component of every URL
|
60
|
+
# --strip-query Enables/disables stripping the query component of every URL
|
61
|
+
# --visit-host HOST Visit URLs with the matching host name
|
62
|
+
# --visit-hosts-like /REGEX/ Visit URLs with hostnames that match the REGEX
|
63
|
+
# --ignore-host HOST Ignore the host name
|
64
|
+
# --ignore-hosts-like /REGEX/ Ignore the host names matching the REGEX
|
65
|
+
# --visit-port PORT Visit URLs with the matching port number
|
66
|
+
# --visit-ports-like /REGEX/ Visit URLs with port numbers that match the REGEX
|
67
|
+
# --ignore-port PORT Ignore the port number
|
68
|
+
# --ignore-ports-like /REGEX/ Ignore the port numbers matching the REGEXP
|
69
|
+
# --visit-link URL Visit the URL
|
70
|
+
# --visit-links-like /REGEX/ Visit URLs that match the REGEX
|
71
|
+
# --ignore-link URL Ignore the URL
|
72
|
+
# --ignore-links-like /REGEX/ Ignore URLs matching the REGEX
|
73
|
+
# --visit-ext FILE_EXT Visit URLs with the matching file ext
|
74
|
+
# --visit-exts-like /REGEX/ Visit URLs with file exts that match the REGEX
|
75
|
+
# --ignore-ext FILE_EXT Ignore the URLs with the file ext
|
76
|
+
# --ignore-exts-like /REGEX/ Ignore URLs with file exts matching the REGEX
|
77
|
+
# -r, --robots Specifies whether to honor robots.txt
|
78
|
+
# -v, --verbose Enables verbose output
|
79
|
+
# --lfi-os unix|windows Sets the OS to test for
|
80
|
+
# --lfi-depth COUNT Sets the directory depth to escape up
|
81
|
+
# --lfi-filter-bypass null-byte|double-escape|base64|rot13|zlib
|
82
|
+
# Sets the filter bypass strategy to use
|
83
|
+
# --rfi-filter-bypass double-encode|suffix-escape|null-byte
|
84
|
+
# Optional filter-bypass strategy to use
|
85
|
+
# --rfi-script-lang asp|asp.net|coldfusion|jsp|php|perl
|
86
|
+
# Explicitly specify the scripting language to test for
|
87
|
+
# --rfi-test-script-url URL Use an alternative test script URL
|
88
|
+
# --sqli-escape-quote Escapes quotation marks
|
89
|
+
# --sqli-escape-parens Escapes parenthesis
|
90
|
+
# --sqli-terminate Terminates the SQL expression with a --
|
91
|
+
# --ssti-test-expr {X*Y | X/Z | X+Y | X-Y}
|
92
|
+
# Optional numeric test to use
|
93
|
+
# --open-redirect-url URL Optional test URL to try to redirect to
|
94
|
+
#
|
95
|
+
# @since 2.0.0
|
96
|
+
#
|
97
|
+
class Vulns < Command
|
98
|
+
|
99
|
+
include Core::CLI::Logging
|
100
|
+
include SpiderOptions
|
101
|
+
include Ronin::Vulns::CLI::Printing
|
102
|
+
include Ronin::Vulns::CLI::Importable
|
103
|
+
|
104
|
+
option :first, short: '-F',
|
105
|
+
desc: 'Stops spidering once the first vulnerability is found' do
|
106
|
+
@scan_mode = :first
|
107
|
+
end
|
108
|
+
|
109
|
+
option :all, short: '-A',
|
110
|
+
desc: 'Spiders every URL and tests every param' do
|
111
|
+
@scan_mode = :all
|
112
|
+
end
|
113
|
+
|
114
|
+
option :print_curl, desc: 'Also prints an example curl command for each vulnerability'
|
115
|
+
|
116
|
+
option :print_http, desc: 'Also prints an example HTTP request for each vulnerability'
|
117
|
+
|
118
|
+
option :import, desc: 'Imports discovered vulnerabilities into the database'
|
119
|
+
|
120
|
+
option :lfi_os, value: {
|
121
|
+
type: [:unix, :windows]
|
122
|
+
},
|
123
|
+
desc: 'Sets the OS to test for' do |os|
|
124
|
+
lfi_kwargs[:os] = os
|
125
|
+
end
|
126
|
+
|
127
|
+
option :lfi_depth, value: {
|
128
|
+
type: Integer,
|
129
|
+
usage: 'COUNT'
|
130
|
+
},
|
131
|
+
desc: 'Sets the directory depth to escape up' do |depth|
|
132
|
+
lfi_kwargs[:depth] = depth
|
133
|
+
end
|
134
|
+
|
135
|
+
option :lfi_filter_bypass, value: {
|
136
|
+
type: {
|
137
|
+
'null-byte' => :null_byte,
|
138
|
+
'double-escape' => :double_escape,
|
139
|
+
'base64' => :base64,
|
140
|
+
'rot13' => :rot13,
|
141
|
+
'zlib' => :zlib
|
142
|
+
}
|
143
|
+
},
|
144
|
+
desc: 'Sets the filter bypass strategy to use' do |filter_bypass|
|
145
|
+
lfi_kwargs[:filter_bypass] = filter_bypass
|
146
|
+
end
|
147
|
+
|
148
|
+
option :rfi_filter_bypass, value: {
|
149
|
+
type: {
|
150
|
+
'double-encode' => :double_encode,
|
151
|
+
'suffix-escape' => :suffix_escape,
|
152
|
+
'null-byte' => :null_byte
|
153
|
+
}
|
154
|
+
},
|
155
|
+
desc: 'Optional filter-bypass strategy to use' do |filter_bypass|
|
156
|
+
rfi_kwargs[:filter_bypass] = filter_bypass
|
157
|
+
end
|
158
|
+
|
159
|
+
option :rfi_script_lang, value: {
|
160
|
+
type: {
|
161
|
+
'asp' => :asp,
|
162
|
+
'asp.net' => :asp_net,
|
163
|
+
'coldfusion' => :cold_fusion,
|
164
|
+
'jsp' => :jsp,
|
165
|
+
'php' => :php,
|
166
|
+
'perl' => :perl
|
167
|
+
}
|
168
|
+
},
|
169
|
+
desc: 'Explicitly specify the scripting language to test for' do |script_lang|
|
170
|
+
rfi_kwargs[:script_lang] = script_lang
|
171
|
+
end
|
172
|
+
|
173
|
+
option :rfi_test_script_url, value: {
|
174
|
+
type: String,
|
175
|
+
usage: 'URL'
|
176
|
+
},
|
177
|
+
desc: 'Use an alternative test script URL' do |test_script_url|
|
178
|
+
rfi_kwargs[:test_script_url] = test_script_url
|
179
|
+
end
|
180
|
+
|
181
|
+
option :sqli_escape_quote, desc: 'Escapes quotation marks' do
|
182
|
+
sqli_kwargs[:escape_quote] = true
|
183
|
+
end
|
184
|
+
|
185
|
+
option :sqli_escape_parens, desc: 'Escapes parenthesis' do
|
186
|
+
sqli_kwargs[:escape_parens] = true
|
187
|
+
end
|
188
|
+
|
189
|
+
option :sqli_terminate, desc: 'Terminates the SQL expression with a --' do
|
190
|
+
sqli_kwargs[:terminate] = true
|
191
|
+
end
|
192
|
+
|
193
|
+
option :ssti_test_expr, value: {
|
194
|
+
type: %r{\A\d+\s*[\*/\+\-]\s*\d+\z},
|
195
|
+
usage: '{X*Y | X/Z | X+Y | X-Y}'
|
196
|
+
},
|
197
|
+
desc: 'Optional numeric test to use' do |expr|
|
198
|
+
ssti_kwargs[:test_expr] = Ronin::Vulns::SSTI::TestExpression.parse(expr)
|
199
|
+
end
|
200
|
+
|
201
|
+
option :open_redirect_url, value: {
|
202
|
+
type: String,
|
203
|
+
usage: 'URL'
|
204
|
+
},
|
205
|
+
desc: 'Optional test URL to try to redirect to' do |test_url|
|
206
|
+
open_redirect_kwargs[:test_url] = test_url
|
207
|
+
end
|
208
|
+
|
209
|
+
description "Spiders a website and scans every URL for web vulnerabilities"
|
210
|
+
|
211
|
+
man_page 'ronin-web-vulns.1'
|
212
|
+
|
213
|
+
# The scan mode
|
214
|
+
#
|
215
|
+
# @return [:first, :all]
|
216
|
+
attr_reader :scan_mode
|
217
|
+
|
218
|
+
# Keyword arguments for `Ronin::Vulns::URLScanner.scan`.
|
219
|
+
#
|
220
|
+
# @return [Hash{Symbol => Object}]
|
221
|
+
attr_reader :scan_kwargs
|
222
|
+
|
223
|
+
#
|
224
|
+
# Initializes the `ronin-web vulns` command.
|
225
|
+
#
|
226
|
+
# @param [Hash{Symbol => Object}] kwargs
|
227
|
+
# Additional keyword arguments.
|
228
|
+
#
|
229
|
+
def initialize(**kwargs)
|
230
|
+
super(**kwargs)
|
231
|
+
|
232
|
+
@scan_mode = :all
|
233
|
+
@scan_kwargs = {}
|
234
|
+
end
|
235
|
+
|
236
|
+
#
|
237
|
+
# Runs the `ronin-web vulns` command.
|
238
|
+
#
|
239
|
+
def run
|
240
|
+
db_connect if options[:import]
|
241
|
+
|
242
|
+
vulns = []
|
243
|
+
|
244
|
+
begin
|
245
|
+
new_agent do |agent|
|
246
|
+
case @scan_mode
|
247
|
+
when :first
|
248
|
+
agent.every_url do |url|
|
249
|
+
log_info "Testing #{url}"
|
250
|
+
|
251
|
+
if (vuln = test_url(url))
|
252
|
+
process_vuln(vuln)
|
253
|
+
vulns << vuln
|
254
|
+
|
255
|
+
agent.pause!
|
256
|
+
end
|
257
|
+
end
|
258
|
+
when :all
|
259
|
+
agent.every_url do |url|
|
260
|
+
log_info "Testing #{url}"
|
261
|
+
|
262
|
+
scan_url(url) do |vuln|
|
263
|
+
process_vuln(vuln)
|
264
|
+
vulns << vuln
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
rescue Interrupt
|
270
|
+
puts
|
271
|
+
end
|
272
|
+
|
273
|
+
puts unless vulns.empty?
|
274
|
+
print_vulns(vulns)
|
275
|
+
end
|
276
|
+
|
277
|
+
#
|
278
|
+
# Logs and optioanlly imports a new discovered web vulnerability.
|
279
|
+
#
|
280
|
+
# @param [Ronin::Vulns::WebVuln] vuln
|
281
|
+
# The discovered web vulnerability.
|
282
|
+
#
|
283
|
+
def process_vuln(vuln)
|
284
|
+
log_vuln(vuln)
|
285
|
+
import_vuln(vuln) if options[:import]
|
286
|
+
end
|
287
|
+
|
288
|
+
#
|
289
|
+
# Prints detailed information about a discovered web vulnerability.
|
290
|
+
#
|
291
|
+
# @param [Array<Ronin::Vulns::WebVuln>] vulns
|
292
|
+
# The web vulnerability to log.
|
293
|
+
#
|
294
|
+
# @param [Boolean] print_curl
|
295
|
+
# Prints an example `curl` command to trigger the web vulnerability.
|
296
|
+
#
|
297
|
+
# @param [Boolean] print_http
|
298
|
+
# Prints an example HTTP request to trigger the web vulnerability.
|
299
|
+
#
|
300
|
+
def print_vulns(vulns, print_curl: options[:print_curl],
|
301
|
+
print_http: options[:print_http])
|
302
|
+
super(vulns, print_curl: print_curl, print_http: print_http)
|
303
|
+
end
|
304
|
+
|
305
|
+
#
|
306
|
+
# The default headers to send with every request.
|
307
|
+
#
|
308
|
+
# @return [Hash{String => String}]
|
309
|
+
#
|
310
|
+
# @since 2.0.0
|
311
|
+
#
|
312
|
+
def default_headers
|
313
|
+
@scan_kwargs[:headers] ||= super
|
314
|
+
end
|
315
|
+
|
316
|
+
#
|
317
|
+
# Sets the `User-Agent` header that will be sent with every request.
|
318
|
+
#
|
319
|
+
# @param [String] new_user_agent
|
320
|
+
#
|
321
|
+
# @return [String]
|
322
|
+
#
|
323
|
+
def user_agent=(new_user_agent)
|
324
|
+
@scan_kwargs[:user_agent] ||= super(new_user_agent)
|
325
|
+
end
|
326
|
+
|
327
|
+
#
|
328
|
+
# Sets the `Referer` header that will be sent with every request.
|
329
|
+
#
|
330
|
+
# @param [String] new_referer
|
331
|
+
#
|
332
|
+
# @return [String, nil]
|
333
|
+
#
|
334
|
+
# @note
|
335
|
+
# Also sets the `Referer` header that will be used during web
|
336
|
+
# vulnerability scanning.
|
337
|
+
#
|
338
|
+
def referer=(new_referer)
|
339
|
+
@scan_kwargs[:referer] ||= super(new_referer)
|
340
|
+
end
|
341
|
+
|
342
|
+
#
|
343
|
+
# @group URL Scanning Methods
|
344
|
+
#
|
345
|
+
|
346
|
+
#
|
347
|
+
# Keyword arguments which will be passed to
|
348
|
+
# `Ronin::Vulns::URLScanner.scan` or `Ronin::Vulns::URLScanner.test`
|
349
|
+
# via the `lfi:` keyword.
|
350
|
+
#
|
351
|
+
# @return [Hash{Symbol => Object}]
|
352
|
+
#
|
353
|
+
def lfi_kwargs
|
354
|
+
@scan_kwargs[:lfi] ||= {}
|
355
|
+
end
|
356
|
+
|
357
|
+
#
|
358
|
+
# Keyword arguments which will be passed to
|
359
|
+
# `Ronin::Vulns::URLScanner.scan` or `Ronin::Vulns::URLScanner.test`
|
360
|
+
# via the `rfi:` keyword.
|
361
|
+
#
|
362
|
+
# @return [Hash{Symbol => Object}]
|
363
|
+
#
|
364
|
+
def rfi_kwargs
|
365
|
+
@scan_kwargs[:rfi] ||= {}
|
366
|
+
end
|
367
|
+
|
368
|
+
#
|
369
|
+
# Keyword arguments which will be passed to
|
370
|
+
# `Ronin::Vulns::URLScanner.scan` or `Ronin::Vulns::URLScanner.test`
|
371
|
+
# via the `sqli:` keyword.
|
372
|
+
#
|
373
|
+
# @return [Hash{Symbol => Object}]
|
374
|
+
#
|
375
|
+
def sqli_kwargs
|
376
|
+
@scan_kwargs[:sqli] ||= {}
|
377
|
+
end
|
378
|
+
|
379
|
+
#
|
380
|
+
# Keyword arguments which will be passed to
|
381
|
+
# `Ronin::Vulns::URLScanner.scan` or `Ronin::Vulns::URLScanner.test`
|
382
|
+
# via the `ssti:` keyword.
|
383
|
+
#
|
384
|
+
# @return [Hash{Symbol => Object}]
|
385
|
+
#
|
386
|
+
def ssti_kwargs
|
387
|
+
@scan_kwargs[:ssti] ||= {}
|
388
|
+
end
|
389
|
+
|
390
|
+
#
|
391
|
+
# Keyword arguments which will be passed to
|
392
|
+
# `Ronin::Vulns::URLScanner.scan` or `Ronin::Vulns::URLScanner.test`
|
393
|
+
# via the `open_redirect:` keyword.
|
394
|
+
#
|
395
|
+
# @return [Hash{Symbol => Object}]
|
396
|
+
#
|
397
|
+
def open_redirect_kwargs
|
398
|
+
@scan_kwargs[:open_redirect] ||= {}
|
399
|
+
end
|
400
|
+
|
401
|
+
#
|
402
|
+
# Keyword arguments which will be passed to
|
403
|
+
# `Ronin::Vulns::URLScanner.scan` or `Ronin::Vulns::URLScanner.test`
|
404
|
+
# via the `reflected_xss:` keyword.
|
405
|
+
#
|
406
|
+
# @return [Hash{Symbol => Object}]
|
407
|
+
#
|
408
|
+
def reflected_xss_kwargs
|
409
|
+
@scan_kwargs[:reflected_xss] ||= {}
|
410
|
+
end
|
411
|
+
|
412
|
+
#
|
413
|
+
# Scans the URL for web vulnerabilities.
|
414
|
+
#
|
415
|
+
# @param [URI::HTTP, String] url
|
416
|
+
# The URL to scan.
|
417
|
+
#
|
418
|
+
# @param [Hash{Symbol => Object}] kwargs
|
419
|
+
# Additional keyword arguments for `Ronin::Vulns::URLScanner.scan`.
|
420
|
+
#
|
421
|
+
# @yield [vuln]
|
422
|
+
# The given block will be yielded each discovered web vulnerability.
|
423
|
+
#
|
424
|
+
# @yieldparam [Ronin::Vulns::LFI,
|
425
|
+
# Ronin::Vulns::RFI,
|
426
|
+
# Ronin::Vulns::SQLI,
|
427
|
+
# Ronin::Vulns::SSTI,
|
428
|
+
# Ronin::Vulns::ReflectedXSS,
|
429
|
+
# Ronin::Vulns::OpenRedirect] vuln
|
430
|
+
# A discovered web vulnerability in the URL.
|
431
|
+
#
|
432
|
+
def scan_url(url,**kwargs,&block)
|
433
|
+
Ronin::Vulns::URLScanner.scan(url,**kwargs,**@scan_kwargs,&block)
|
434
|
+
end
|
435
|
+
|
436
|
+
#
|
437
|
+
# Tests the URL for web vulnerabilities and prints the first
|
438
|
+
# vulnerability.
|
439
|
+
#
|
440
|
+
# @param [URI::HTTP, String] url
|
441
|
+
# The URL to scan.
|
442
|
+
#
|
443
|
+
# @param [Hash{Symbol => Object}] kwargs
|
444
|
+
# Additional keyword arguments for `Ronin::Vulns::URLScanner.test`.
|
445
|
+
#
|
446
|
+
# @return [Ronin::Vulns::LFI,
|
447
|
+
# Ronin::Vulns::RFI,
|
448
|
+
# Ronin::Vulns::SQLI,
|
449
|
+
# Ronin::Vulns::SSTI,
|
450
|
+
# Ronin::Vulns::ReflectedXSS,
|
451
|
+
# Ronin::Vulns::OpenRedirect, nil]
|
452
|
+
# The first discovered web vulnerability or `nil` if no
|
453
|
+
# vulnerabilities were discovered.
|
454
|
+
#
|
455
|
+
def test_url(url,**kwargs)
|
456
|
+
Ronin::Vulns::URLScanner.test(url,**kwargs,**@scan_kwargs)
|
457
|
+
end
|
458
|
+
|
459
|
+
end
|
460
|
+
end
|
461
|
+
end
|
462
|
+
end
|
463
|
+
end
|