wpscan 3.2.1 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +73 -70
- data/app/controllers.rb +1 -1
- data/app/controllers/enumeration.rb +1 -1
- data/app/controllers/enumeration/cli_options.rb +32 -15
- data/app/controllers/enumeration/enum_methods.rb +7 -0
- data/app/controllers/password_attack.rb +108 -0
- data/app/finders.rb +2 -0
- data/app/finders/config_backups/known_filenames.rb +1 -1
- data/app/finders/db_exports.rb +17 -0
- data/app/finders/db_exports/known_locations.rb +49 -0
- data/app/finders/interesting_findings/mu_plugins.rb +1 -0
- data/app/finders/main_theme/css_style.rb +1 -1
- data/app/finders/medias/attachment_brute_forcing.rb +1 -1
- data/app/finders/passwords.rb +3 -0
- data/app/finders/passwords/wp_login.rb +22 -0
- data/app/finders/passwords/xml_rpc.rb +22 -0
- data/app/finders/passwords/xml_rpc_multicall.rb +102 -0
- data/app/finders/users.rb +2 -0
- data/app/finders/users/author_id_brute_forcing.rb +3 -3
- data/app/finders/users/author_posts.rb +2 -2
- data/app/finders/users/login_error_messages.rb +1 -1
- data/app/finders/users/oembed_api.rb +4 -4
- data/app/finders/users/rss_generator.rb +38 -0
- data/app/finders/users/wp_json_api.rb +5 -5
- data/app/finders/wp_version/atom_generator.rb +1 -1
- data/app/finders/wp_version/rdf_generator.rb +1 -1
- data/app/finders/wp_version/rss_generator.rb +1 -1
- data/app/models.rb +1 -1
- data/app/models/db_export.rb +5 -0
- data/app/models/wp_item.rb +2 -0
- data/app/views/cli/core/banner.erb +1 -1
- data/app/views/cli/enumeration/db_exports.erb +11 -0
- data/app/views/cli/{brute_force → password_attack}/users.erb +0 -0
- data/app/views/json/enumeration/db_exports.erb +10 -0
- data/app/views/json/{brute_force → password_attack}/users.erb +1 -1
- data/bin/wpscan +1 -1
- data/lib/wpscan/browser.rb +1 -1
- data/lib/wpscan/db/dynamic_finders/plugin.rb +2 -2
- data/lib/wpscan/db/dynamic_finders/wordpress.rb +2 -2
- data/lib/wpscan/db/fingerprints.rb +1 -1
- data/lib/wpscan/db/updater.rb +4 -1
- data/lib/wpscan/finders/dynamic_finder/version/query_parameter.rb +2 -1
- data/lib/wpscan/finders/dynamic_finder/wp_item_version.rb +2 -1
- data/lib/wpscan/finders/dynamic_finder/wp_version.rb +5 -4
- data/lib/wpscan/target.rb +13 -0
- data/lib/wpscan/target/platform/wordpress/custom_directories.rb +1 -1
- data/lib/wpscan/version.rb +1 -1
- metadata +29 -22
- data/app/controllers/brute_force.rb +0 -116
- data/app/models/user.rb +0 -31
- data/app/views/cli/brute_force/error.erb +0 -1
- data/app/views/cli/brute_force/found.erb +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5eac3c3174f8ae7798069fddfc45fd67f837b388
|
4
|
+
data.tar.gz: 626cfade1aeb099be9bfc1fbadf68a319a25fa55
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 031efaee33293d3ee7f0ff05a0a7100b8cf87b8b3f1429c513a6cb5ddd7d0a015fb6d7d462fb7fcc8cfbf18fd15c6ffe7db2428cb2ea77fed577c18055d975b4
|
7
|
+
data.tar.gz: b010b70018627700aa90cfebb98adf0f5f3de157690e1baa56885405725f1e16fa96c2d1b65bc19d73fbd6707146e2ab1c712ad283cf388753a26218a0bdd5a4
|
data/README.md
CHANGED
@@ -3,7 +3,79 @@
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/wpscan.svg)](https://badge.fury.io/rb/wpscan)
|
4
4
|
[![Build Status](https://travis-ci.org/wpscanteam/wpscan-v3.svg?branch=master)](https://travis-ci.org/wpscanteam/wpscan-v3)
|
5
5
|
[![Code Climate](https://codeclimate.com/github/wpscanteam/wpscan-v3/badges/gpa.svg)](https://codeclimate.com/github/wpscanteam/wpscan-v3)
|
6
|
-
[![
|
6
|
+
[![Patreon Donate](https://img.shields.io/badge/patreon-donate-green.svg)](https://www.patreon.com/wpscan)
|
7
|
+
|
8
|
+
# INSTALL
|
9
|
+
|
10
|
+
## Prerequisites:
|
11
|
+
|
12
|
+
- Ruby >= 2.2.2 - Recommended: 2.3.3
|
13
|
+
- Curl >= 7.21 - Recommended: latest - FYI the 7.29 has a segfault
|
14
|
+
- RubyGems - Recommended: latest
|
15
|
+
|
16
|
+
### From RubyGems:
|
17
|
+
|
18
|
+
```
|
19
|
+
gem install wpscan
|
20
|
+
```
|
21
|
+
|
22
|
+
### From sources:
|
23
|
+
|
24
|
+
Prerequisites: Git
|
25
|
+
|
26
|
+
```
|
27
|
+
git clone https://github.com/wpscanteam/wpscan-v3 wpscan
|
28
|
+
|
29
|
+
cd wpscan/
|
30
|
+
|
31
|
+
bundle install && rake install
|
32
|
+
```
|
33
|
+
|
34
|
+
# Docker
|
35
|
+
|
36
|
+
Pull the repo with ```docker pull wpscanteam/wpscan-v3```
|
37
|
+
|
38
|
+
# Usage
|
39
|
+
|
40
|
+
```wpscan --url blog.tld``` This will scan the blog using default options with a good compromise between speed and accuracy. For example, the plugins will be checked passively but their version with a mixed detection mode (passively + aggressively). Potential config backup files will also be checked, along with other interesting findings. If a more stealthy approach is required, then ```wpscan --stealthy --url blog.tld``` can be used.
|
41
|
+
As a result, when using the ```--enumerate``` option, don't forget to set the ```--plugins-detection``` accordingly, as its default is 'passive'.
|
42
|
+
|
43
|
+
For more options, open a terminal and type ```wpscan --help``` (if you built wpscan from the source, you should type the command outside of the git repo)
|
44
|
+
|
45
|
+
The DB is located at ~/.wpscan/db
|
46
|
+
|
47
|
+
WPScan can load all options (including the --url) from configuration files, the following locations are checked (order: first to last):
|
48
|
+
|
49
|
+
* ~/.wpscan/cli_options.json
|
50
|
+
* ~/.wpscan/cli_options.yml
|
51
|
+
* pwd/.wpscan/cli_options.json
|
52
|
+
* pwd/.wpscan/cli_options.yml
|
53
|
+
|
54
|
+
If those files exist, options from them will be loaded and overridden if found twice.
|
55
|
+
|
56
|
+
e.g:
|
57
|
+
|
58
|
+
~/.wpscan/cli_options.yml:
|
59
|
+
```
|
60
|
+
proxy: 'http://127.0.0.1:8080'
|
61
|
+
verbose: true
|
62
|
+
```
|
63
|
+
|
64
|
+
pwd/.wpscan/cli_options.yml:
|
65
|
+
```
|
66
|
+
proxy: 'socks5://127.0.0.1:9090'
|
67
|
+
url: 'http://target.tld'
|
68
|
+
```
|
69
|
+
|
70
|
+
Running ```wpscan``` in the current directory (pwd), is the same as ```wpscan -v --proxy socks5://127.0.0.1:9090 --url http://target.tld```
|
71
|
+
|
72
|
+
# PROJECT HOME
|
73
|
+
|
74
|
+
[https://wpscan.org](https://wpscan.org)
|
75
|
+
|
76
|
+
# VULNERABILITY DATABASE
|
77
|
+
|
78
|
+
[https://wpvulndb.com](https://wpvulndb.com)
|
7
79
|
|
8
80
|
# LICENSE
|
9
81
|
|
@@ -83,72 +155,3 @@ Running WPScan against websites without prior mutual consent may be illegal in y
|
|
83
155
|
### 11. Trademark
|
84
156
|
|
85
157
|
The "wpscan" term is a registered trademark. This License does not grant the use of the "wpscan" trademark or the use of the WPScan logo.
|
86
|
-
|
87
|
-
# INSTALL
|
88
|
-
|
89
|
-
## Prerequisites:
|
90
|
-
|
91
|
-
- Ruby >= 2.2.2 - Recommended: 2.3.3
|
92
|
-
- Curl >= 7.21 - Recommended: latest - FYI the 7.29 has a segfault
|
93
|
-
- RubyGems - Recommended: latest
|
94
|
-
|
95
|
-
|
96
|
-
### From RubyGems:
|
97
|
-
|
98
|
-
```gem install wpscan```
|
99
|
-
|
100
|
-
### From sources:
|
101
|
-
|
102
|
-
Prerequisites: Git
|
103
|
-
|
104
|
-
```git clone https://github.com/wpscanteam/wpscan-v3```
|
105
|
-
|
106
|
-
```cd wpscan```
|
107
|
-
|
108
|
-
```bundle install && rake install```
|
109
|
-
|
110
|
-
# Docker
|
111
|
-
|
112
|
-
Pull the repo with ```docker pull wpscanteam/wpscan-v3```
|
113
|
-
|
114
|
-
# Usage
|
115
|
-
|
116
|
-
```wpscan --url blog.tld``` This will scan the blog using default options with a good compromise between speed and accuracy. For example, the plugins will be checked passively but their version with a mixed detection mode (passively + aggressively). Potential config backup files will also be checked, along with other interesting findings. If a more stealthy approach is required, then ```wpscan --stealthy --url blog.tld``` can be used.
|
117
|
-
As a result, when using the ```--enumerate``` option, don't forget to set the ```--plugins-detection``` accordingly, as its default is 'passive'.
|
118
|
-
|
119
|
-
For more options, open a terminal and type ```wpscan --help``` (if you built wpscan from the source, you should type the command outside of the git repo)
|
120
|
-
|
121
|
-
The DB is located at ~/.wpscan/db
|
122
|
-
|
123
|
-
WPScan can load all options (including the --url) from configuration files, the following locations are checked (order: first to last):
|
124
|
-
|
125
|
-
* ~/.wpscan/cli_options.json
|
126
|
-
* ~/.wpscan/cli_options.yml
|
127
|
-
* pwd/.wpscan/cli_options.json
|
128
|
-
* pwd/.wpscan/cli_options.yml
|
129
|
-
|
130
|
-
If those files exist, options from them will be loaded and overridden if found twice.
|
131
|
-
|
132
|
-
e.g:
|
133
|
-
|
134
|
-
~/.wpscan/cli_options.yml:
|
135
|
-
```
|
136
|
-
proxy: 'http://127.0.0.1:8080'
|
137
|
-
verbose: true
|
138
|
-
```
|
139
|
-
|
140
|
-
pwd/.wpscan/cli_options.yml:
|
141
|
-
```
|
142
|
-
proxy: 'socks5://127.0.0.1:9090'
|
143
|
-
url: 'http://target.tld'
|
144
|
-
```
|
145
|
-
|
146
|
-
Running ```wpscan``` in the current directory (pwd), is the same as ```wpscan -v --proxy socks5://127.0.0.1:9090 --url http://target.tld```
|
147
|
-
|
148
|
-
# PROJECT HOME
|
149
|
-
|
150
|
-
[https://wpscan.org](https://wpscan.org)
|
151
|
-
|
152
|
-
# VULNERABILITY DATABASE
|
153
|
-
|
154
|
-
[https://wpvulndb.com](https://wpvulndb.com)
|
data/app/controllers.rb
CHANGED
@@ -3,5 +3,5 @@ require_relative 'controllers/custom_directories'
|
|
3
3
|
require_relative 'controllers/wp_version'
|
4
4
|
require_relative 'controllers/main_theme'
|
5
5
|
require_relative 'controllers/enumeration'
|
6
|
-
require_relative 'controllers/
|
6
|
+
require_relative 'controllers/password_attack'
|
7
7
|
require_relative 'controllers/aliases'
|
@@ -16,7 +16,7 @@ module WPScan
|
|
16
16
|
enum_plugins if enum_plugins?(enum)
|
17
17
|
enum_themes if enum_themes?(enum)
|
18
18
|
|
19
|
-
%i[timthumbs config_backups medias].each do |key|
|
19
|
+
%i[timthumbs config_backups db_exports medias].each do |key|
|
20
20
|
send("enum_#{key}".to_sym) if enum.key?(key)
|
21
21
|
end
|
22
22
|
|
@@ -4,7 +4,8 @@ module WPScan
|
|
4
4
|
class Enumeration < CMSScanner::Controller::Base
|
5
5
|
def cli_options
|
6
6
|
cli_enum_choices + cli_plugins_opts + cli_themes_opts +
|
7
|
-
cli_timthumbs_opts + cli_config_backups_opts +
|
7
|
+
cli_timthumbs_opts + cli_config_backups_opts + cli_db_exports_opts +
|
8
|
+
cli_medias_opts + cli_users_opts
|
8
9
|
end
|
9
10
|
|
10
11
|
# @return [ Array<OptParseValidator::OptBase> ]
|
@@ -14,26 +15,27 @@ module WPScan
|
|
14
15
|
OptMultiChoices.new(
|
15
16
|
['--enumerate [OPTS]', '-e', 'Enumeration Process'],
|
16
17
|
choices: {
|
17
|
-
vp:
|
18
|
-
ap:
|
19
|
-
p:
|
20
|
-
vt:
|
21
|
-
at:
|
22
|
-
t:
|
23
|
-
tt:
|
24
|
-
cb:
|
25
|
-
|
26
|
-
|
18
|
+
vp: OptBoolean.new(['--vulnerable-plugins']),
|
19
|
+
ap: OptBoolean.new(['--all-plugins']),
|
20
|
+
p: OptBoolean.new(['--plugins']),
|
21
|
+
vt: OptBoolean.new(['--vulnerable-themes']),
|
22
|
+
at: OptBoolean.new(['--all-themes']),
|
23
|
+
t: OptBoolean.new(['--themes']),
|
24
|
+
tt: OptBoolean.new(['--timthumbs']),
|
25
|
+
cb: OptBoolean.new(['--config-backups']),
|
26
|
+
dbe: OptBoolean.new(['--db-exports']),
|
27
|
+
u: OptIntegerRange.new(['--users', 'User IDs range. e.g: u1-5'], value_if_empty: '1-10'),
|
28
|
+
m: OptIntegerRange.new(['--medias', 'Media IDs range. e.g m1-15'], value_if_empty: '1-100')
|
27
29
|
},
|
28
|
-
value_if_empty: 'vp,vt,tt,cb,u,m',
|
30
|
+
value_if_empty: 'vp,vt,tt,cb,dbe,u,m',
|
29
31
|
incompatible: [%i[vp ap p], %i[vt at t]],
|
30
32
|
default: { all_plugins: true, config_backups: true }
|
31
33
|
),
|
32
34
|
OptRegexp.new(
|
33
35
|
[
|
34
36
|
'--exclude-content-based REGEXP_OR_STRING',
|
35
|
-
'Exclude all responses
|
36
|
-
'Regexp delimiters are not required.'
|
37
|
+
'Exclude all responses matching the Regexp (case insensitive) during parts of the enumeration.',
|
38
|
+
'Both the headers and body are checked. Regexp delimiters are not required.'
|
37
39
|
], options: Regexp::IGNORECASE
|
38
40
|
)
|
39
41
|
]
|
@@ -110,7 +112,22 @@ module WPScan
|
|
110
112
|
),
|
111
113
|
OptChoice.new(
|
112
114
|
['--config-backups-detection MODE',
|
113
|
-
'Use the supplied mode to enumerate
|
115
|
+
'Use the supplied mode to enumerate Config Backups, instead of the global (--detection-mode) mode.'],
|
116
|
+
choices: %w[mixed passive aggressive], normalize: :to_sym
|
117
|
+
)
|
118
|
+
]
|
119
|
+
end
|
120
|
+
|
121
|
+
# @return [ Array<OptParseValidator::OptBase> ]
|
122
|
+
def cli_db_exports_opts
|
123
|
+
[
|
124
|
+
OptFilePath.new(
|
125
|
+
['--db-exports-list FILE-PATH', 'List of DB exports\' paths to use'],
|
126
|
+
exists: true, default: File.join(DB_DIR, 'db_exports.txt')
|
127
|
+
),
|
128
|
+
OptChoice.new(
|
129
|
+
['--db-exports-detection MODE',
|
130
|
+
'Use the supplied mode to enumerate DB Exports, instead of the global (--detection-mode) mode.'],
|
114
131
|
choices: %w[mixed passive aggressive], normalize: :to_sym
|
115
132
|
)
|
116
133
|
]
|
@@ -136,6 +136,13 @@ module WPScan
|
|
136
136
|
output('config_backups', config_backups: target.config_backups(opts))
|
137
137
|
end
|
138
138
|
|
139
|
+
def enum_db_exports
|
140
|
+
opts = default_opts('db_exports').merge(list: parsed_options[:db_exports_list])
|
141
|
+
|
142
|
+
output('@info', msg: 'Enumerating DB Exports') if user_interaction?
|
143
|
+
output('db_exports', db_exports: target.db_exports(opts))
|
144
|
+
end
|
145
|
+
|
139
146
|
def enum_medias
|
140
147
|
opts = default_opts('medias').merge(range: parsed_options[:enumerate][:medias])
|
141
148
|
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module WPScan
|
2
|
+
module Controller
|
3
|
+
# Password Attack Controller
|
4
|
+
class PasswordAttack < CMSScanner::Controller::Base
|
5
|
+
def cli_options
|
6
|
+
[
|
7
|
+
OptFilePath.new(
|
8
|
+
['--passwords FILE-PATH', '-P',
|
9
|
+
'List of passwords to use during the password attack.',
|
10
|
+
'If no --username/s option supplied, user enumeration will be run.'],
|
11
|
+
exists: true
|
12
|
+
),
|
13
|
+
OptSmartList.new(['--usernames LIST', '-U', 'List of usernames to use during the password attack.']),
|
14
|
+
OptInteger.new(['--multicall-max-passwords MAX_PWD',
|
15
|
+
'Maximum number of passwords to send by request with XMLRPC multicall'],
|
16
|
+
default: 500),
|
17
|
+
OptChoice.new(['--password-attack ATTACK',
|
18
|
+
'Force the supplied attack to be used rather than automatically determining one.'],
|
19
|
+
choices: %w[wp-login xmlrpc xmlrpc-multicall],
|
20
|
+
normalize: %i[downcase underscore to_sym])
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
def run
|
25
|
+
return unless parsed_options[:passwords]
|
26
|
+
|
27
|
+
if user_interaction?
|
28
|
+
output('@info',
|
29
|
+
msg: "Performing password attack on #{attacker.titleize} against #{users.size} user/s")
|
30
|
+
end
|
31
|
+
|
32
|
+
attack_opts = {
|
33
|
+
show_progression: user_interaction?,
|
34
|
+
multicall_max_passwords: parsed_options[:multicall_max_passwords]
|
35
|
+
}
|
36
|
+
|
37
|
+
begin
|
38
|
+
found = []
|
39
|
+
|
40
|
+
attacker.attack(users, passwords(parsed_options[:passwords]), attack_opts) do |user|
|
41
|
+
found << user
|
42
|
+
|
43
|
+
attacker.progress_bar.log("[SUCCESS] - #{user.username} / #{user.password}")
|
44
|
+
end
|
45
|
+
ensure
|
46
|
+
output('users', users: found)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [ CMSScanner::Finders::Finder ] The finder used to perform the attack
|
51
|
+
def attacker
|
52
|
+
@attacker ||= attacker_from_cli_options || attacker_from_automatic_detection
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [ WPScan::XMLRPC ]
|
56
|
+
def xmlrpc
|
57
|
+
@xmlrpc ||= target.xmlrpc
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [ CMSScanner::Finders::Finder ]
|
61
|
+
def attacker_from_cli_options
|
62
|
+
return unless parsed_options[:password_attack]
|
63
|
+
|
64
|
+
case parsed_options[:password_attack]
|
65
|
+
when :wp_login
|
66
|
+
WPScan::Finders::Passwords::WpLogin.new(target)
|
67
|
+
when :xmlrpc
|
68
|
+
WPScan::Finders::Passwords::XMLRPC.new(xmlrpc)
|
69
|
+
when :xmlrpc_multicall
|
70
|
+
WPScan::Finders::Passwords::XMLRPCMulticall.new(xmlrpc)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# @return [ CMSScanner::Finders::Finder ]
|
75
|
+
def attacker_from_automatic_detection
|
76
|
+
if xmlrpc&.enabled? && xmlrpc.available_methods.include?('wp.getUsersBlogs')
|
77
|
+
wp_version = target.wp_version
|
78
|
+
|
79
|
+
if wp_version && wp_version < '4.4'
|
80
|
+
WPScan::Finders::Passwords::XMLRPCMulticall.new(xmlrpc)
|
81
|
+
else
|
82
|
+
WPScan::Finders::Passwords::XMLRPC.new(xmlrpc)
|
83
|
+
end
|
84
|
+
else
|
85
|
+
WPScan::Finders::Passwords::WpLogin.new(target)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [ Array<Users> ] The users to brute force
|
90
|
+
def users
|
91
|
+
return target.users unless parsed_options[:usernames]
|
92
|
+
|
93
|
+
parsed_options[:usernames].reduce([]) do |acc, elem|
|
94
|
+
acc << CMSScanner::User.new(elem.chomp)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# @param [ String ] wordlist_path
|
99
|
+
#
|
100
|
+
# @return [ Array<String> ]
|
101
|
+
def passwords(wordlist_path)
|
102
|
+
@passwords ||= File.open(wordlist_path).reduce([]) do |acc, elem|
|
103
|
+
acc << elem.chomp
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/app/finders.rb
CHANGED
@@ -5,9 +5,11 @@ require_relative 'finders/main_theme'
|
|
5
5
|
require_relative 'finders/timthumb_version'
|
6
6
|
require_relative 'finders/timthumbs'
|
7
7
|
require_relative 'finders/config_backups'
|
8
|
+
require_relative 'finders/db_exports'
|
8
9
|
require_relative 'finders/medias'
|
9
10
|
require_relative 'finders/users'
|
10
11
|
require_relative 'finders/plugins'
|
11
12
|
require_relative 'finders/plugin_version'
|
12
13
|
require_relative 'finders/theme_version'
|
13
14
|
require_relative 'finders/themes'
|
15
|
+
require_relative 'finders/passwords'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative 'db_exports/known_locations'
|
2
|
+
|
3
|
+
module WPScan
|
4
|
+
module Finders
|
5
|
+
module DbExports
|
6
|
+
# DB Exports Finder
|
7
|
+
class Base
|
8
|
+
include CMSScanner::Finders::SameTypeFinder
|
9
|
+
|
10
|
+
# @param [ WPScan::Target ] target
|
11
|
+
def initialize(target)
|
12
|
+
finders << DbExports::KnownLocations.new(target)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module WPScan
|
2
|
+
module Finders
|
3
|
+
module DbExports
|
4
|
+
# DB Exports finder
|
5
|
+
# See https://github.com/wpscanteam/wpscan-v3/issues/62
|
6
|
+
class KnownLocations < CMSScanner::Finders::Finder
|
7
|
+
include CMSScanner::Finders::Finder::Enumerator
|
8
|
+
|
9
|
+
# @param [ Hash ] opts
|
10
|
+
# @option opts [ String ] :list
|
11
|
+
# @option opts [ Boolean ] :show_progression
|
12
|
+
#
|
13
|
+
# @return [ Array<DBExport> ]
|
14
|
+
def aggressive(opts = {})
|
15
|
+
found = []
|
16
|
+
|
17
|
+
enumerate(potential_urls(opts), opts) do |res|
|
18
|
+
next unless res.code == 200 && res.body =~ /INSERT INTO/
|
19
|
+
|
20
|
+
found << WPScan::DbExport.new(res.request.url, found_by: DIRECT_ACCESS, confidence: 100)
|
21
|
+
end
|
22
|
+
|
23
|
+
found
|
24
|
+
end
|
25
|
+
|
26
|
+
# @param [ Hash ] opts
|
27
|
+
# @option opts [ String ] :list Mandatory
|
28
|
+
#
|
29
|
+
# @return [ Hash ]
|
30
|
+
def potential_urls(opts = {})
|
31
|
+
urls = {}
|
32
|
+
domain_name = target.uri.host[/(^[\w|-]+)/, 1]
|
33
|
+
|
34
|
+
File.open(opts[:list]).each_with_index do |path, index|
|
35
|
+
path.gsub!('{domain_name}', domain_name)
|
36
|
+
|
37
|
+
urls[target.url(path.chomp)] = index
|
38
|
+
end
|
39
|
+
|
40
|
+
urls
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_progress_bar(opts = {})
|
44
|
+
super(opts.merge(title: ' Checking DB Exports -'))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|