wpscan 3.8.13 → 3.8.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +21 -5
- data/app/controllers/core.rb +1 -1
- data/app/controllers/enumeration/cli_options.rb +6 -0
- data/app/finders/db_exports/known_locations.rb +45 -6
- data/app/finders/users.rb +14 -0
- data/app/finders/wp_version.rb +1 -1
- data/app/models/timthumb.rb +1 -1
- data/app/models/wp_item.rb +4 -2
- data/app/views/cli/vuln_api/status.erb +1 -1
- data/app/views/cli/wp_version/version.erb +1 -1
- data/app/views/json/vuln_api/status.erb +1 -1
- data/lib/wpscan.rb +1 -0
- data/lib/wpscan/db/dynamic_finders/base.rb +5 -1
- data/lib/wpscan/target/platform/wordpress/custom_directories.rb +4 -4
- data/lib/wpscan/version.rb +1 -1
- data/lib/wpscan/vulnerability.rb +1 -0
- metadata +11 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e7fc9dea6d2aa00fc366bbe8f1cde8af5668597020b0f3762aba9c8bd0f4f720
|
4
|
+
data.tar.gz: 5bd79cbef80eb57065cafab7bbf787f4d71de73052068ac37d6a407ca86b813c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d093d424143d40bc594dc8f5ef5e6b577bdb09e8e1aff5289da2f471a1b5b7bccdde600c91700300a940281763b6b74e0b6384a23220d928b9e1edef947dac21
|
7
|
+
data.tar.gz: 4032d8268e1961adc1c767bf6857ba5ff46c929c3534955f56550af65aa6996c59e3a2ec17f2c95f8c1af6efbc992122c5cc4f6ee3c012b978e4a5a5c9446e28
|
data/README.md
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
|
16
16
|
<p align="center">
|
17
17
|
<a href="https://badge.fury.io/rb/wpscan" target="_blank"><img src="https://badge.fury.io/rb/wpscan.svg"></a>
|
18
|
+
<a href="https://hub.docker.com/r/wpscanteam/wpscan/" target="_blank"><img src="https://img.shields.io/docker/pulls/wpscanteam/wpscan.svg"></a>
|
18
19
|
<a href="https://github.com/wpscanteam/wpscan/actions?query=workflow%3ABuild" target="_blank"><img src="https://github.com/wpscanteam/wpscan/workflows/Build/badge.svg"></a>
|
19
20
|
<a href="https://codeclimate.com/github/wpscanteam/wpscan" target="_blank"><img src="https://codeclimate.com/github/wpscanteam/wpscan/badges/gpa.svg"></a>
|
20
21
|
</p>
|
@@ -24,10 +25,11 @@
|
|
24
25
|
## Prerequisites
|
25
26
|
|
26
27
|
- (Optional but highly recommended: [RVM](https://rvm.io/rvm/install))
|
27
|
-
- Ruby >= 2.
|
28
|
+
- Ruby >= 2.5 - Recommended: latest
|
28
29
|
- Ruby 2.5.0 to 2.5.3 can cause an 'undefined symbol: rmpd_util_str_to_d' error in some systems, see [#1283](https://github.com/wpscanteam/wpscan/issues/1283)
|
29
|
-
- Curl >= 7.
|
30
|
+
- Curl >= 7.72 - Recommended: latest
|
30
31
|
- The 7.29 has a segfault
|
32
|
+
- The < 7.72 could result in `Stream error in the HTTP/2 framing layer` in some cases
|
31
33
|
- RubyGems - Recommended: latest
|
32
34
|
- Nokogiri might require packages to be installed via your package manager depending on your OS, see https://nokogiri.org/tutorials/installing_nokogiri.html
|
33
35
|
|
@@ -35,6 +37,10 @@
|
|
35
37
|
|
36
38
|
When using a pentesting distubution (such as Kali Linux), it is recommended to install/update wpscan via the package manager if available.
|
37
39
|
|
40
|
+
### In macOSX via Homebrew
|
41
|
+
|
42
|
+
`brew install wpscanteam/tap/wpscan`
|
43
|
+
|
38
44
|
### From RubyGems
|
39
45
|
|
40
46
|
```shell
|
@@ -47,7 +53,7 @@ On MacOSX, if a ```Gem::FilePermissionError``` is raised due to the Apple's Syst
|
|
47
53
|
|
48
54
|
You can update the local database by using ```wpscan --update```
|
49
55
|
|
50
|
-
Updating WPScan itself is either done via ```gem update wpscan``` or the packages manager (this is quite important for distributions such as in Kali Linux: ```apt-get update && apt-get upgrade```) depending how WPScan was (pre)installed
|
56
|
+
Updating WPScan itself is either done via ```gem update wpscan``` or the packages manager (this is quite important for distributions such as in Kali Linux: ```apt-get update && apt-get upgrade```) depending on how WPScan was (pre)installed
|
51
57
|
|
52
58
|
# Docker
|
53
59
|
|
@@ -80,9 +86,19 @@ For more options, open a terminal and type ```wpscan --help``` (if you built wps
|
|
80
86
|
|
81
87
|
The DB is located at ~/.wpscan/db
|
82
88
|
|
83
|
-
## Vulnerability Database
|
89
|
+
## Optional: WordPress Vulnerability Database API
|
90
|
+
|
91
|
+
The WPScan CLI tool uses the [WordPress Vulnerability Database API](https://wpscan.com/api) to retrieve WordPress vulnerability data in real time. For WPScan to retrieve the vulnerability data an API token must be supplied via the `--api-token` option, or via a configuration file, as discussed below. An API token can be obtained by registering an account on [WPScan.com](https://wpscan.com/register).
|
92
|
+
|
93
|
+
Up to 25 API requests per day are given free of charge, that should be suitable to scan most WordPress websites at least once per day. When the daily 25 API requests are exhausted, WPScan will continue to work as normal but without any vulnerability data. Users can upgrade to paid API usage to increase their API limits within their user profile on [WPScan.com](https://wpscan.com/).
|
94
|
+
|
95
|
+
#### The Free plan allows 25 API requests per day. View the different [available API plans](https://wpscan.com/api).
|
96
|
+
|
97
|
+
### How many API requests do you need?
|
84
98
|
|
85
|
-
|
99
|
+
- Our WordPress scanner makes one API request for the WordPress version, one request per installed plugin and one request per installed theme.
|
100
|
+
- On average, a WordPress website has 22 installed plugins.
|
101
|
+
- The Free plan should cover around 50% of all WordPress websites.
|
86
102
|
|
87
103
|
## Load CLI options from file/s
|
88
104
|
|
data/app/controllers/core.rb
CHANGED
@@ -39,7 +39,7 @@ module WPScan
|
|
39
39
|
output('@notice', msg: 'It seems like you have not updated the database for some time.')
|
40
40
|
print '[?] Do you want to update now? [Y]es [N]o, default: [N]'
|
41
41
|
|
42
|
-
/^y/i.match?(Readline.readline)
|
42
|
+
/^y/i.match?(Readline.readline)
|
43
43
|
end
|
44
44
|
|
45
45
|
def update_db
|
@@ -170,6 +170,12 @@ module WPScan
|
|
170
170
|
['--users-detection MODE',
|
171
171
|
'Use the supplied mode to enumerate Users, instead of the global (--detection-mode) mode.'],
|
172
172
|
choices: %w[mixed passive aggressive], normalize: :to_sym, advanced: true
|
173
|
+
),
|
174
|
+
OptRegexp.new(
|
175
|
+
[
|
176
|
+
'--exclude-usernames REGEXP_OR_STRING',
|
177
|
+
'Exclude usernames matching the Regexp/string (case insensitive). Regexp delimiters are not required.'
|
178
|
+
], options: Regexp::IGNORECASE
|
173
179
|
)
|
174
180
|
]
|
175
181
|
end
|
@@ -7,7 +7,7 @@ module WPScan
|
|
7
7
|
class KnownLocations < CMSScanner::Finders::Finder
|
8
8
|
include CMSScanner::Finders::Finder::Enumerator
|
9
9
|
|
10
|
-
SQL_PATTERN = /(?:DROP|(?:UN)?LOCK|CREATE) TABLE|INSERT INTO/.freeze
|
10
|
+
SQL_PATTERN = /(?:DROP|(?:UN)?LOCK|CREATE|ALTER) (?:TABLE|DATABASE)|INSERT INTO/.freeze
|
11
11
|
|
12
12
|
# @param [ Hash ] opts
|
13
13
|
# @option opts [ String ] :list
|
@@ -39,18 +39,57 @@ module WPScan
|
|
39
39
|
#
|
40
40
|
# @return [ Hash ]
|
41
41
|
def potential_urls(opts = {})
|
42
|
-
urls
|
43
|
-
|
42
|
+
urls = {}
|
43
|
+
index = 0
|
44
44
|
|
45
|
-
File.open(opts[:list]).
|
46
|
-
path.
|
45
|
+
File.open(opts[:list]).each do |path|
|
46
|
+
path.chomp!
|
47
47
|
|
48
|
-
|
48
|
+
if path.include?('{domain_name}')
|
49
|
+
urls[target.url(path.gsub('{domain_name}', domain_name))] = index
|
50
|
+
|
51
|
+
if domain_name != domain_name_with_sub
|
52
|
+
urls[target.url(path.gsub('{domain_name}', domain_name_with_sub))] = index + 1
|
53
|
+
|
54
|
+
index += 1
|
55
|
+
end
|
56
|
+
else
|
57
|
+
urls[target.url(path)] = index
|
58
|
+
end
|
59
|
+
|
60
|
+
index += 1
|
49
61
|
end
|
50
62
|
|
51
63
|
urls
|
52
64
|
end
|
53
65
|
|
66
|
+
def domain_name
|
67
|
+
@domain_name ||= if Resolv::AddressRegex.match?(target.uri.host)
|
68
|
+
target.uri.host
|
69
|
+
else
|
70
|
+
(PublicSuffix.domain(target.uri.host) || target.uri.host)[/(^[\w|-]+)/, 1]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def domain_name_with_sub
|
75
|
+
@domain_name_with_sub ||=
|
76
|
+
if Resolv::AddressRegex.match?(target.uri.host)
|
77
|
+
target.uri.host
|
78
|
+
else
|
79
|
+
parsed = PublicSuffix.parse(target.uri.host)
|
80
|
+
|
81
|
+
if parsed.subdomain
|
82
|
+
parsed.subdomain.gsub(".#{parsed.tld}", '')
|
83
|
+
elsif parsed.domain
|
84
|
+
parsed.domain.gsub(".#{parsed.tld}", '')
|
85
|
+
else
|
86
|
+
target.uri.host
|
87
|
+
end
|
88
|
+
end
|
89
|
+
rescue PublicSuffix::DomainNotAllowed
|
90
|
+
@domain_name_with_sub = target.uri.host
|
91
|
+
end
|
92
|
+
|
54
93
|
def create_progress_bar(opts = {})
|
55
94
|
super(opts.merge(title: ' Checking DB Exports -'))
|
56
95
|
end
|
data/app/finders/users.rb
CHANGED
@@ -11,6 +11,16 @@ require_relative 'users/yoast_seo_author_sitemap'
|
|
11
11
|
|
12
12
|
module WPScan
|
13
13
|
module Finders
|
14
|
+
# Specific Finders container to filter the usernames found
|
15
|
+
# and remove the ones matching ParsedCli.exclude_username if supplied
|
16
|
+
class UsersFinders < SameTypeFinders
|
17
|
+
def filter_findings
|
18
|
+
findings.delete_if { |user| ParsedCli.exclude_usernames.match?(user.username) } if ParsedCli.exclude_usernames
|
19
|
+
|
20
|
+
findings
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
14
24
|
module Users
|
15
25
|
# Users Finder
|
16
26
|
class Base
|
@@ -28,6 +38,10 @@ module WPScan
|
|
28
38
|
Users::AuthorIdBruteForcing.new(target) <<
|
29
39
|
Users::LoginErrorMessages.new(target)
|
30
40
|
end
|
41
|
+
|
42
|
+
def finders
|
43
|
+
@finders ||= Finders::UsersFinders.new
|
44
|
+
end
|
31
45
|
end
|
32
46
|
end
|
33
47
|
end
|
data/app/finders/wp_version.rb
CHANGED
@@ -10,7 +10,7 @@ module WPScan
|
|
10
10
|
module Finders
|
11
11
|
# Specific Finders container to filter the version detected
|
12
12
|
# and remove the one with low confidence to avoid false
|
13
|
-
# positive when there is not
|
13
|
+
# positive when there is not enough information to accurately
|
14
14
|
# determine it.
|
15
15
|
class WpVersionFinders < UniqueFinders
|
16
16
|
def filter_findings
|
data/app/models/timthumb.rb
CHANGED
@@ -63,7 +63,7 @@ module WPScan
|
|
63
63
|
def webshot_enabled?
|
64
64
|
res = Browser.get(url, params: { webshot: 1, src: "http://#{default_allowed_domains.sample}" })
|
65
65
|
|
66
|
-
|
66
|
+
!/WEBSHOT_ENABLED == true/.match?(res.body)
|
67
67
|
end
|
68
68
|
|
69
69
|
# @return [ Array<String> ] The default allowed domains (between the 2.0 and 2.8.13)
|
data/app/models/wp_item.rb
CHANGED
@@ -53,7 +53,9 @@ module WPScan
|
|
53
53
|
#
|
54
54
|
# @return [ Boolean ]
|
55
55
|
def vulnerable_to?(vuln)
|
56
|
-
return
|
56
|
+
return false if version && vuln&.introduced_in && version < vuln.introduced_in
|
57
|
+
|
58
|
+
return true unless version && vuln&.fixed_in && !vuln.fixed_in.empty?
|
57
59
|
|
58
60
|
version < vuln.fixed_in
|
59
61
|
end
|
@@ -160,7 +162,7 @@ module WPScan
|
|
160
162
|
#
|
161
163
|
# @return [ Typhoeus::Response ]
|
162
164
|
def head_and_get(path, codes = [200], params = {})
|
163
|
-
final_path =
|
165
|
+
final_path = @path_from_blog.dup # @path_from_blog is set in the plugin/theme
|
164
166
|
final_path << path unless path.nil?
|
165
167
|
|
166
168
|
blog.head_and_get(final_path, codes, params)
|
@@ -9,5 +9,5 @@
|
|
9
9
|
<% end -%>
|
10
10
|
<% else -%>
|
11
11
|
<%= warning_icon %> No WPScan API Token given, as a result vulnerability data has not been output.
|
12
|
-
<%= warning_icon %> You can get a free API token with
|
12
|
+
<%= warning_icon %> You can get a free API token with 25 daily requests by registering at https://wpscan.com/register
|
13
13
|
<% end -%>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<% if @version -%>
|
2
|
-
<%= info_icon %> WordPress version <%= @version.number %> identified (<%= @version.status.
|
2
|
+
<%= info_icon %> WordPress version <%= @version.number %> identified (<%= @version.status.tr('-', '_').humanize %>, released on <%= @version.release_date %>).
|
3
3
|
<%= render('@finding', item: @version) -%>
|
4
4
|
<% else -%>
|
5
5
|
<%= notice_icon %> The WordPress version could not be detected.
|
@@ -8,6 +8,6 @@
|
|
8
8
|
"requests_remaining": <%= @status['requests_remaining'].to_json %>
|
9
9
|
<% end -%>
|
10
10
|
<% else -%>
|
11
|
-
"error": "No WPScan API Token given, as a result vulnerability data has not been output.\nYou can get a free API token with
|
11
|
+
"error": "No WPScan API Token given, as a result vulnerability data has not been output.\nYou can get a free API token with 25 daily requests by registering at https://wpscan.com/register"
|
12
12
|
<% end -%>
|
13
13
|
},
|
data/lib/wpscan.rb
CHANGED
@@ -11,7 +11,11 @@ module WPScan
|
|
11
11
|
|
12
12
|
# @return [ Hash ]
|
13
13
|
def self.all_df_data
|
14
|
-
@all_df_data ||=
|
14
|
+
@all_df_data ||= if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('4.0.0')
|
15
|
+
YAML.safe_load(File.read(df_file), permitted_classes: [Regexp])
|
16
|
+
else
|
17
|
+
YAML.safe_load(File.read(df_file), [Regexp])
|
18
|
+
end
|
15
19
|
end
|
16
20
|
|
17
21
|
# @return [ Array<Symbol> ]
|
@@ -125,14 +125,14 @@ module WPScan
|
|
125
125
|
return @uri.to_s unless path
|
126
126
|
|
127
127
|
if %r{wp-content/plugins}i.match?(path)
|
128
|
-
|
128
|
+
new_path = path.gsub('wp-content/plugins', plugins_dir)
|
129
129
|
elsif /wp-content/i.match?(path)
|
130
|
-
|
130
|
+
new_path = path.gsub('wp-content', content_dir)
|
131
131
|
elsif path[0] != '/' && sub_dir
|
132
|
-
|
132
|
+
new_path = "#{sub_dir}/#{path}"
|
133
133
|
end
|
134
134
|
|
135
|
-
super(path)
|
135
|
+
super(new_path || path)
|
136
136
|
end
|
137
137
|
end
|
138
138
|
end
|
data/lib/wpscan/version.rb
CHANGED
data/lib/wpscan/vulnerability.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wpscan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.8.
|
4
|
+
version: 3.8.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- WPScanTeam
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cms_scanner
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.13.
|
19
|
+
version: 0.13.5
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.13.
|
26
|
+
version: 0.13.5
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,28 +100,28 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 1.
|
103
|
+
version: 1.16.0
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 1.
|
110
|
+
version: 1.16.0
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: rubocop-performance
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 1.
|
117
|
+
version: 1.11.0
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 1.
|
124
|
+
version: 1.11.0
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: simplecov
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -170,14 +170,14 @@ dependencies:
|
|
170
170
|
requirements:
|
171
171
|
- - "~>"
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version: 3.
|
173
|
+
version: 3.13.0
|
174
174
|
type: :development
|
175
175
|
prerelease: false
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
177
177
|
requirements:
|
178
178
|
- - "~>"
|
179
179
|
- !ruby/object:Gem::Version
|
180
|
-
version: 3.
|
180
|
+
version: 3.13.0
|
181
181
|
description: WPScan is a black box WordPress vulnerability scanner.
|
182
182
|
email:
|
183
183
|
- contact@wpscan.com
|
@@ -397,7 +397,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
397
397
|
- !ruby/object:Gem::Version
|
398
398
|
version: '0'
|
399
399
|
requirements: []
|
400
|
-
rubygems_version: 3.0.3
|
400
|
+
rubygems_version: 3.0.3.1
|
401
401
|
signing_key:
|
402
402
|
specification_version: 4
|
403
403
|
summary: WPScan - WordPress Vulnerability Scanner
|