wpscan 3.7.2 → 3.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/custom_directories.rb +1 -1
- data/app/finders/users/author_id_brute_forcing.rb +4 -1
- data/app/finders/users/oembed_api.rb +2 -0
- data/app/finders/wp_items/urls_in_homepage.rb +6 -4
- data/app/models/theme.rb +1 -1
- data/lib/wpscan/target/platform/wordpress.rb +15 -7
- data/lib/wpscan/target/platform/wordpress/custom_directories.rb +3 -6
- data/lib/wpscan/version.rb +1 -1
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b09450bc3d471ad71176d276e4e1d5961ce9bc8b12511a133efe17145fe5206b
|
4
|
+
data.tar.gz: b31d1f2425c69100b985f660447e967d88a2706f737fe313d2517cc2ed3b726a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 24e87decb82a9f01edcdf77b46fbecb7c816bef1b1ed2c7a3d839ef3f5975326920d1b3d6cd74684054744d56a8d0baa0f85f831c39477d9ac02355d9f47b8ca
|
7
|
+
data.tar.gz: 4c593ed0dd0bc0bb27bbf8b1827095d82ea601a25b17f673cc972c6e540ad21d13f61162d95c32b32fb06e7a93153264b432e5147caa779cfcbdba93d508b943
|
@@ -18,7 +18,7 @@ module WPScan
|
|
18
18
|
target.content_dir = ParsedCli.wp_content_dir if ParsedCli.wp_content_dir
|
19
19
|
target.plugins_dir = ParsedCli.wp_plugins_dir if ParsedCli.wp_plugins_dir
|
20
20
|
|
21
|
-
return if target.content_dir
|
21
|
+
return if target.content_dir
|
22
22
|
|
23
23
|
raise Error::WpContentDirNotDetected
|
24
24
|
end
|
@@ -97,9 +97,12 @@ module WPScan
|
|
97
97
|
# @return [ String, nil ]
|
98
98
|
def display_name_from_body(body)
|
99
99
|
page = Nokogiri::HTML.parse(body)
|
100
|
+
|
100
101
|
# WP >= 3.0
|
101
102
|
page.css('h1.page-title span').each do |node|
|
102
|
-
|
103
|
+
text = node.text.to_s.strip
|
104
|
+
|
105
|
+
return text unless text.empty?
|
103
106
|
end
|
104
107
|
|
105
108
|
# WP < 3.0
|
@@ -34,6 +34,8 @@ module WPScan
|
|
34
34
|
def user_details_from_oembed_data(oembed_data)
|
35
35
|
return unless oembed_data
|
36
36
|
|
37
|
+
oembed_data = oembed_data.first if oembed_data.is_a?(Array)
|
38
|
+
|
37
39
|
if oembed_data['author_url'] =~ %r{/author/([^/]+)/?\z}
|
38
40
|
details = [Regexp.last_match[1], 'Author URL', 90]
|
39
41
|
elsif oembed_data['author_name'] && !oembed_data['author_name'].empty?
|
@@ -15,7 +15,9 @@ module WPScan
|
|
15
15
|
target.in_scope_uris(target.homepage_res) do |uri|
|
16
16
|
next unless uri.to_s =~ item_attribute_pattern(type)
|
17
17
|
|
18
|
-
|
18
|
+
slug = Regexp.last_match[1]&.strip
|
19
|
+
|
20
|
+
found << slug unless slug&.empty?
|
19
21
|
end
|
20
22
|
|
21
23
|
uniq ? found.uniq.sort : found.sort
|
@@ -28,7 +30,7 @@ module WPScan
|
|
28
30
|
def items_from_codes(type, uniq = true)
|
29
31
|
found = []
|
30
32
|
|
31
|
-
target.homepage_res.html.
|
33
|
+
target.homepage_res.html.xpath('//script[not(@src)]|//style[not(@src)]').each do |tag|
|
32
34
|
code = tag.text.to_s
|
33
35
|
next if code.empty?
|
34
36
|
|
@@ -42,7 +44,7 @@ module WPScan
|
|
42
44
|
#
|
43
45
|
# @return [ Regexp ]
|
44
46
|
def item_attribute_pattern(type)
|
45
|
-
@item_attribute_pattern ||= %r{
|
47
|
+
@item_attribute_pattern ||= %r{#{item_url_pattern(type)}([^/]+)/}i
|
46
48
|
end
|
47
49
|
|
48
50
|
# @param [ String ] type
|
@@ -59,7 +61,7 @@ module WPScan
|
|
59
61
|
item_dir = type == 'plugins' ? target.plugins_dir : target.content_dir
|
60
62
|
item_url = type == 'plugins' ? target.plugins_url : target.content_url
|
61
63
|
|
62
|
-
url = /#{item_url.gsub(/\A(?:
|
64
|
+
url = /#{item_url.gsub(/\A(?:https?)/i, 'https?').gsub('/', '\\\\\?\/')}/i
|
63
65
|
item_dir = %r{(?:#{url}|\\?\/#{item_dir.gsub('/', '\\\\\?\/')}\\?/)}i
|
64
66
|
|
65
67
|
type == 'plugins' ? item_dir : %r{#{item_dir}#{type}\\?\/}i
|
data/app/models/theme.rb
CHANGED
@@ -101,7 +101,7 @@ module WPScan
|
|
101
101
|
#
|
102
102
|
# @return [ String ]
|
103
103
|
def parse_style_tag(body, tag)
|
104
|
-
value = body[
|
104
|
+
value = body[/#{Regexp.escape(tag)}:[\t ]*([^\r\n\*]+)/i, 1]
|
105
105
|
|
106
106
|
value && !value.strip.empty? ? value.strip : nil
|
107
107
|
end
|
@@ -11,7 +11,9 @@ module WPScan
|
|
11
11
|
module WordPress
|
12
12
|
include CMSScanner::Target::Platform::PHP
|
13
13
|
|
14
|
-
WORDPRESS_PATTERN
|
14
|
+
WORDPRESS_PATTERN = %r{/(?:(?:wp-content/(?:themes|(?:mu\-)?plugins|uploads))|wp-includes)/}i.freeze
|
15
|
+
WP_JSON_OEMBED_PATTERN = %r{/wp\-json/oembed/}i.freeze
|
16
|
+
WP_ADMIN_AJAX_PATTERN = %r{\\?/wp\-admin\\?/admin\-ajax\.php}i.freeze
|
15
17
|
|
16
18
|
# These methods are used in the associated interesting_findings finders
|
17
19
|
# to keep the boolean state of the finding rather than re-check the whole thing again
|
@@ -23,27 +25,33 @@ module WPScan
|
|
23
25
|
# @param [ Symbol ] detection_mode
|
24
26
|
#
|
25
27
|
# @return [ Boolean ]
|
28
|
+
# rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
|
26
29
|
def wordpress?(detection_mode)
|
27
30
|
in_scope_uris(homepage_res) do |uri|
|
28
|
-
return true if uri.path.match(
|
31
|
+
return true if WORDPRESS_PATTERN.match?(uri.path) || WP_JSON_OEMBED_PATTERN.match?(uri.path)
|
29
32
|
end
|
30
33
|
|
31
|
-
homepage_res.html.css('meta[name="generator"]').
|
32
|
-
|
34
|
+
return true if homepage_res.html.css('meta[name="generator"]').any? do |node|
|
35
|
+
/wordpress/i.match?(node['content'])
|
33
36
|
end
|
34
37
|
|
35
38
|
return true unless comments_from_page(/wordpress/i, homepage_res).empty?
|
36
39
|
|
40
|
+
return true if homepage_res.html.xpath('//script[not(@src)]').any? do |node|
|
41
|
+
WP_ADMIN_AJAX_PATTERN.match?(node.text)
|
42
|
+
end
|
43
|
+
|
37
44
|
if %i[mixed aggressive].include?(detection_mode)
|
38
45
|
%w[wp-admin/install.php wp-login.php].each do |path|
|
39
|
-
in_scope_uris(Browser.get_and_follow_location(url(path))).
|
40
|
-
|
46
|
+
return true if in_scope_uris(Browser.get_and_follow_location(url(path))).any? do |uri|
|
47
|
+
WORDPRESS_PATTERN.match?(uri.path)
|
41
48
|
end
|
42
49
|
end
|
43
50
|
end
|
44
51
|
|
45
52
|
false
|
46
53
|
end
|
54
|
+
# rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity
|
47
55
|
|
48
56
|
COOKIE_PATTERNS = {
|
49
57
|
'vjs' => /createCookie\('vjs','(?<c_value>\d+)',\d+\);/i
|
@@ -82,7 +90,7 @@ module WPScan
|
|
82
90
|
def wordpress_hosted?
|
83
91
|
return true if /\.wordpress\.com$/i.match?(uri.host)
|
84
92
|
|
85
|
-
unless content_dir
|
93
|
+
unless content_dir
|
86
94
|
pattern = %r{https?://s\d\.wp\.com#{WORDPRESS_PATTERN}}i.freeze
|
87
95
|
|
88
96
|
uris_from_page(homepage_res) do |uri|
|
@@ -13,12 +13,11 @@ module WPScan
|
|
13
13
|
@plugins_dir = dir.chomp('/')
|
14
14
|
end
|
15
15
|
|
16
|
-
# @param [ Symbol ] detection_mode
|
17
16
|
# @return [ String ] The wp-content directory
|
18
|
-
def content_dir
|
17
|
+
def content_dir
|
19
18
|
unless @content_dir
|
20
19
|
# scope_url_pattern is from CMSScanner::Target
|
21
|
-
pattern = %r{#{scope_url_pattern}([\w\s\-/]
|
20
|
+
pattern = %r{#{scope_url_pattern}([\w\s\-/]+?)\\?/(?:themes|plugins|uploads|cache)\\?/}i
|
22
21
|
|
23
22
|
in_scope_uris(homepage_res) do |uri|
|
24
23
|
return @content_dir = Regexp.last_match[1] if uri.to_s.match(pattern)
|
@@ -29,9 +28,7 @@ module WPScan
|
|
29
28
|
return @content_dir = match[1]
|
30
29
|
end
|
31
30
|
|
32
|
-
|
33
|
-
return @content_dir = 'wp-content' if default_content_dir_exists?
|
34
|
-
end
|
31
|
+
return @content_dir = 'wp-content' if default_content_dir_exists?
|
35
32
|
end
|
36
33
|
|
37
34
|
@content_dir
|
data/lib/wpscan/version.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.7.
|
4
|
+
version: 3.7.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- WPScanTeam
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-10-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cms_scanner
|
@@ -72,28 +72,28 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '13.0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '13.0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: rspec
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 3.
|
89
|
+
version: 3.9.0
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 3.
|
96
|
+
version: 3.9.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rspec-its
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,28 +114,28 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 0.
|
117
|
+
version: 0.75.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: 0.
|
124
|
+
version: 0.75.0
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: rubocop-performance
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
129
|
- - "~>"
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: 1.
|
131
|
+
version: 1.5.0
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
136
|
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: 1.
|
138
|
+
version: 1.5.0
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: simplecov
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|